SQL注入学习前置知识
一、sql注入的原理
SQL注入是由于web应用程序对用户输入数据的合法性判断不严格导致攻击者可以利用用户输入数据的媒介执行SQL语句
例如
select * from table where username = 'input' and passwd='input';
如果再次此处用户输入数据的过滤不严格,在用户输入用户名admin’ #时便可以在不输入密码的情况下进行admin账户的登录
二、sql注入的类型
在本篇博客中对各种类型的SQL注入进行一个大概的总结,具体内容和实现以及各种过滤和绕过方式有待补充。在本篇博客的介绍中大部分注入攻击的距离是以在get传值id的情况进行分析以供参考。
(1)union联合查询
union联合查询会把多条查询的结果合并成一个结果集,在以即为在传值?id=1背后添加union查询语句进行查询。为了避免原本的查询项干扰,通常把id设置为一个非常大的数或者-1这样明显没有查询结果的数字以摆出原本的id传值查询出的结果对union关键字后我们人为进行的查询结果进行干扰。
这里也对有无回显的情况进行分析。首先使用order by语句确定列数,而后通过selelct语句进行有无回显的判断。举个栗子,假如已经判断完列数为4,即使用select 1,2,3,4以观察网页,若网页中出现相应的数字即在相应的列部分有回显,可以直接在相应的位置进行诸如查询。如果没有回显的话则需要盲注、报错查询等其他方法,后面会慢慢介绍。
(2)利用or、and、xor等逻辑符号进行查询
在SQL语句中可以使用or、and、xor等逻辑符号,并且有
1 or 1=1,1 or 0=1 ,0 or 0=0
1 and 1 =1,1 and 0=0,0 and 0=0
1 xor 0=1,1 xor 1=0,0 xor 0=0
我们也可以通过利用这些逻辑运算的性质进行注入,例如
?id=1 and (substr(payload,1,1)='?')
当右边substr函数取得的字符和引号中的字符相同时返回1,即为1 and 1=1,若不同则为1 and 0=0,进而可以逐个字符爆破得到查询结果
这种方式一般用于无回显的注入中,通过编写脚本进行字符爆破,称为布尔盲注
同样的,也可以通过sleep()函数利用逻辑符号或者if函数进行查询,称为时间盲注
?id=1' and if(payload,sleep(10),1) --+
其原理同布尔盲注大致相同
(3)报错注入
报错注入的前提在这个网站开启了错误调试信息,即为当注入的sql语句引发错误时会返回错误信息。我们可以利用其返回的错误信息进行注入查询。
1.利用updatexml()函数进行报错查询
updatexml执行需要第二个参数传入合法的xpath路径,否则会报错。但是如果非法参数为sql语句的话updatexml函数报错的同时会将非法的语句结果进行输出,达到查询的目的。
利用这个特性,我们可以直接在第二个参数的位置输入我们的查询语句,通过报错信息进行查询
?id=1' or updatexml(1,payload,1) --+
2.双查询注入
主要是利用floor函数、rand函数和count函数的特性。
floor函数会返回不大于其参数的最大整数。rand函数会产生一个0到1的随机数,如果构造floor(rand()*2)的话则会产生一个1或者0的随机数字。
双随机注入这里还利用了group by语句:
我们将想要查询的结果与floor(rand()*2)利用concat函数进行连接,在通过group by语句进行分组管理。group by语句在执行的过程中会利用一个虚拟表,查看数据的主键值如果在虚拟表中不存在则在虚拟表中创建对应的数据,如果存在则在对应的主键值下进行汇总,重复内容合并成同一项。
如果我们使用count()函数进行聚集,则会产生新的问题:
由于group by 语句执行下一条数据会经过检查和插入两个过程,而在检查和插入的过程中rand函数又会分别运行。在count函数和group by语句的共同作用下产生的结果为如果存在则count函数的数值加1,如果不存在则插入。这样就导致在检查的过程中rand函数随机到了新的数字使得group by语句决定将数据的主键插入到虚拟表中,而在插入的过程中如果rand函数和floor函数共同作用随机到了和之前相同数值的整数,也就意味着将要插入的主键值已经在虚拟表中存在,由此会报错,并且会将重复的主键值的内容报出。
这样我们便可以利用报错中的主键值内容进行查询
select count(*),concat((payload),floor(rand()*2)) as a from information_schema.tables group by a;
通过构造这样的语句我们便可以报出payload字段中所查询的东西了
(4)二次注入
二次注入顾名思义需要分成两步进行注入,分别为恶意数据的插入以及恶意数据的引用。这种方法一般应用于攻击目标的后端代码对非法字符进行转义操作存储在数据库中,然而在引用恶意数据时原先被转义的非法字符被还原从而引发注入攻击。举一个最简单的例子,在sqli-24中便是通过注册用户名为admin '#的用户通过修改密码引用该用户名达到修改用户名为admin的密码的操作。
三、sql注入的各种过滤以及绕过姿势(待补充)
(1)关于过滤空格的处理方式
在只过滤了空格的情况下可以使用一些其他空白字符进行绕过。
URL编码:%0a、%0b、%0c、%0d、%0e9、%a0
注释符绕过/**/
括号绕过select(*)from(table);
(2)嵌套绕过敏感词替换
例如遇到了将select替换为空值时,可以构造selselectelct进行使用。这样在将select替换为空值时select左右两边仍然能够合并为一个完整的select进行使用
(3)十六进制替换绕过
在某些情况下可以使用十六进制数代替字符进行相关关键词的过滤,如讲select替换为selec\x74
(4)双重URL编码绕过
将‘%’也替换为url编码的形式绕过,例入将%27替换为%2527,在一次url解析后变成%27,即为单引号
(5)引号被替换
1.没有过滤反斜杠
这时则需要两个可控点,例入
select * from table where username='admin\' and password ='or x#'
此时我们在可控点username处引入了一个反斜杠使其第二个单引号被转义,这样第一个可控点的第一个单引号便会与第二个可控点的第一个单引号组合。之后第二个可控点的第二个单引号通过注释的方式进行消除即可。语句中x的位置便是我们可以进行注入语句的位置。
2.引号默认转义
指允许用户输入引号但会自动的将其转义。这时有多种攻击手段可以使用,如二次注入,字符串截断(即为输入结果超过字符长度限制在反斜杠和引号间进行过滤,这时便构造出和没有过滤反斜杠相似的效果)和宽字节注入等等
(6)内联注释绕过
在mysql中形如
/*!code*/
这样的形式的内容会被执行
(7)等号被过滤
可以用不使用通配符的like来代替等号
(8)逗号被过滤
substr函数中可以使用from x fory代替x,y
limit 0,1等价于limit 1 offset 0
select x,y可以变为select (x)a join select (y)b
(9)其他
其他绕过方式有待补充
菜鸡学习ing…