SQL注入过程中注释符号有以下几种表达方式:
- --
- #
- %23
SQL注入过程中注释符号的作用是把后面不需要的语句注释掉,以保证SQL命令的完整性。
以Less-1为例,分析源代码:
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
在进行注入时,输入?id=1,参数传入到后台中输入的值1会替换$id,源代码中闭合值就是这样的:
$sql="SELECT * FROM users WHERE id='1' LIMIT 0,1";
![](/qrcode.jpg)
如果输入的参数是id=1 and 1=1时,后台源代码中闭合如下:
$sql="SELECT * FROM users WHERE id='1 and 1=1' LIMIT 0,1";
源代码中因为单引号把输入的值1 and 1=1当成字符串闭合了,如果我们不想当成字符串处理的话就需要绕过单引号闭合,输入id=1' and 1=1#,源代码中闭合如下:
$sql="SELECT * FROM users WHERE id='1' and 1=1#' LIMIT 0,1";
源代码中成功将id=1闭合,然后dan 1=1单独作为一个条件拼接到SQL语句中,#符号将后面的语句都给注释掉了,这样构造的SQL语句可以保证其完整性。
SQL语句还是能正常执行:
来看一个注释符号绕过waf的案例:
无论是输入?id=1'--+还是?id=1'#,后台还是对SQL语句进行了报错,这时我们需要考虑是不是被waf(web防火墙)把敏感关键字或语句给过滤掉了。
如何判断页面过滤对象:
从最简单的注入语句开始,逐渐增加复杂性,然后通过该方法判断过滤对象。
分析Less-23的部分关键源代码:
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
preg_replace 函数是用于查找和替换字符串的,例如preg_replace($reg, $replace, $id);语句中,preg_replace 函数会从$id中查找符合reg中的字符,用replace中的字符进行替换。分析Less-23代码可知,对于传入的参数$id,后台会检测查找“#”或“--”等特殊字符,然后用空字符进行替换。
现在换一种思路,在id后面手动再加一个单引号,即:?id=1' and 1=1',把源代码中的单引号闭合掉:
虽然可以把后面的单引号成功闭合,但LIMIT 0,1不能配合整条SQL语句执行,数据库在执行过程中仍然会报错,根本原因在于单引号闭合在某些情况下是无法跟and或or语句一起使用的。
这次改进一下,不加其他参数,还是使用单引号闭合,输入?id=1''进行闭合:
SQL语句可以正常执行,没有任何报错,再配合union联合查询进行注入:
红色部分就是手动输入的SQL注入语句,最终后台会将SQL语句拼接成如下图所示:
数据库可以正确执行SQL命令,使用联合注入确定了显示位后,可以将2,3的位置替换成database()和version()函数,查询数据库名和版本等信息。
注意:如果web页面是数字型注入方式的话,就不需要考虑闭合方式,在注入过程中也不需要使用注释符号。
如果Less-23源代码中闭合方式是('')这样的,那么在构造SQL注入的时候,就需要这样构造SQL注入语句进行绕过:
http://www.sqli.com/Less-23/?id=-1') union select 1,version(),3 or ('1')=('1
如何绕过后台过滤?
如果是数字型注入,则不需要考虑绕过。
如果是字符型注入,需要考虑三种情况:
1. 单引号闭合需要在后面增加一个单引号即可
2. 双引号闭合需要在后面注入语句后面增加一个双引号
3. ('')单引号加括号这种需要多加一个or ('')=('1
4. ("")双引号加括号这种需要多加一个or ("")=("1
释符号是WAF绕过中经常使用的一种方式,注释符号绕过方式主要的作用就是对注入的SQL指令变形和混淆,从而绕过WAF防火墙的过滤。
在前面学习数据库中已知的注释符号有:“#” 和 “--+”两种方式,第三种/* */注释符号在mysql数据库中是多行注释的作用,在WAF绕过中对SQL注入指令变形和混淆会用的比较多。通常,数据库对/* */注释符号里的内容是不做任何解释和执行的。
例如来看这条SQL语句:
select * /*and*/ from users where id>5 , 数据库在执行这条SQL执行时会把/*and*/符号里的内容当做注释来处理。
如果想要让数据库执行/* */注释符号里的内容时可以使用这样的SQL语句(/*!xxx*/):
/*!xxx*/是mysql数据库对/**/符号功能的一种扩展,如果在/* */注释符号内最前面添加了感叹号的话,那么多行注释符号里的内容将会执行。也就是说,上图中的SQL语句在执行过程中,会将/*!where id >5*/里的内容当做SQL指令来执行,而不是当做注释来处理。
再来看另一个SQL语句:
这条SQL指令中仅仅只是在/*!xxx*/做了一点改变:添加了一个五位数的数字。数据库在执行SQL执行时没有将/*!50005 where id >5*/里的内容当做SQL指令来执行,这是因为/*!50000 where id >5*/指令中的数字50000表示:数据库在执行之前会先判断当前数据库的版本,如果当前数据库的版本是在5.00.05以上的话,注释符号里的内容会被当做SQL指令执行。
通过查看数据库版本发现,数据库的版本是在5.6.17版本,很明显要高于5.00.05,但是要低于7.00.07,因此第一条SQL指令的注释符号里的内容会被当做SQL指令执行,而第二条SQL指令则不会。
通过这种方式我们可以绕过WAF的过滤,例如对select和union进行绕过:
有些WAF会对union select进行过滤,但在构造SQL注入语句时可以使用/*!80000or*/对注入指令中的union和select关键字进行变形混淆,绕过WAF的检测。