一道简单的SQL注入题

这是我真正意义上来说做的第一道SQL题目,感觉从这个题目里还是能学到好多东西的,这里记录一下这个题目的writeup和在其中学到的东西
link://www.ichunqiu.com/battalion Web分类下的SQL

尝试SQL注入

进入这个模拟环境之后,会得到一个提示为flag在数据库中,这时候查看url栏可以发现

嗯这个就有SQL注入内味了,然后试一下id=2或者id=3,发现id=2时候可以出来提示为test,然后再往后就什么都不出来了,这时候我先假装id后面的东西是一个数字变量,输入id=1 and 1=1,发现网页给出提示是这是SQL注入代码,这说明这个网站是有对SQL注入做基本的防护的,所以现在的问题就变成了如何绕过服务器的过滤规则。

对过滤or、and、xor、not的绕过

对这些的绕过一般的操作是

  • and = &&
  • or = ||
  • xor = | # 异或
  • not = !
    现在我们换一下把输入变成id=1 && 1=1,发现并没有报错,这说明我们成功进行了注入的第一步。这时候我们可以发现,很有可能该数据库仅对我们展示了表中某一列的数据,所以现在就要判断这个表到底有几列,这里使用的方法是order by。url里输入id=1 order by 1,报错提示这是sql注入代码,所以现在要进行进一步的绕过

SQL关键字过滤绕过

  • 改变大小写:例如select变为SELect(本题中没用)
  • 添加内联注释:把一些MYSQL的语句放在/*!...*/中,例如/*!order*/(本题中没用)
  • 双写关键字:一些waf中替换使用的是replace()函数,因此可以输入selselectect,在经过waf处理后变为select(本题中没用)
  • 空格过滤绕过:有些waf会过滤掉注入中的空格导致无法正常允许,这里可以把空格用/**/,反单引号,(),回车等进行代替(本题中暂时不用考虑)
  • 等号绕过:使用like和rlike模拟=的功能,在不添加通配符%时候,like xxxrlike xxx= xxx是等价的(本题中暂不用考虑)
  • 添加<>或者//:因为有的waf会对<>或//进行过滤,所里可以利用这一点,使用sel<>ect进行绕过(本题有用)
    现在进行分割,注意分割时候order不要分割为了or<>der因为这样又会引入or,现在我们输入ord<>er by x进行尝试,发现最多到order by 3就停止了,这说明这个表只有3列。现在我们就需要找出具体的flag位置,这就涉及到对mysql数据库结构的了解。

查找flag

MYSQL数据库

Mysql数据库里面有一个数据库叫information_schema,这个数据库中很多有用的信息都存在这个里面

  • schemata表里面存储了不同数据库的信息,如下所示:
  • tables表里面存储着每个数据库中包含的所有的表的信息,如下所示:
  • columns表里面存储着每个数据库中列的信息,如下所示:

查看数据库信息

知道这些东西之后,我们现在要找flag,我认为flag多半是在这个数据库里面,首先我们查看一下当先数据库的名称,因为已知查询到的数据是3列,现在我们要计算,输出在前端的到底是哪一列的数据,这里我们构造一个payload为?id=1 un<>ion sel<>ect 1,2,3,发现输出的有2,那么可以肯定输出在前端的就是第二列。
现在我们想要知道这个表在哪个数据库,所以就可以构造一个payload为?id=1 un<>ion sel<>ect 1,database(),3,得到前端的返回结果为

现在我们就要查找这个sqli数据库中存在哪些表,在前面我们说过,表的信息存在tables中,所以这里构造一个payload为?id=1 un<>ion sel<>ect 1,table_name,3 from information_schema.tables whe<>re table_schema='sqli',然后可以得到该数据库中有两张表,一个是info,一个是users

现在我们分别查一下这两个表里面都有哪些列,信息从columns里面查到,这时候我们可以构造payload为?id=1 un<>ion sel<>ect 1,column_name,3 from information_schema.columns where table_schema='sqli' an<>d table_name='users'?id=1 un<>ion sel<>ect 1,column_name,3 from information_schema.columns where table_schema='sqli' an<>d table_name='info',分别如下所示:

找到flag

好吧看了一下列名称,竟然都有flag这个东西,那只能一个表一个表找了,首先找一下第一个表users,这时候我们可以构造payload为?id=1 un<>ion sel<>ect 1,flag_9c861b688330,3 fr<>om users,但是发现并出不来任何东西。。感到疑惑,好吧那就试下一个构造payload为?id=1 un<>ion sel<>ect 1,flAg_T5ZNdrm,3 fr<>om info,这时候出来结果了,如下所示:

然后复制这个flag交差,就ok啦!

感想

这是第一次做sql注入的题,虽然这个题比较简单,但是总的来说我还是学到了不少东西的,比如Mysql数据库中的表结构和sql注入的绕过等,我觉得还是很有教育意义的。

Tags: