在进行sql注入时,字段类型分为字符型或者数字型,意味着我们需要构造不同的sql语句。
假设存在sql注入的url是:http://192.168.0.1/id=1
假设数据库的执行语句是:select * from table where id=$id
当查询id=1的页面时返回正常页面,此时执行的语句是:select * from table where id=1
假如在1后面加上 and 1=2 , $id的值就是1 and 1=2
这时数据库执行的语句就是 select * from table where id=1 and 1=2
1=2为假,真and假=假
语句正确,逻辑错误,页面返回错误
同理 如果$id的值就是1 and 1=1, 真and真=真,页面返回正常
假如在1后面加上 or 1=2, $id的值就是1 or 1=2
这时数据库执行的语句就是 select * from table where id=1 or 1=2
1=2为假,真or假=真
语句正确,逻辑正确,页面返回正常
同理 如果$id的值就是1 or 1=2, 真or假=真,页面返回正常
所以,我们可以使用and或者or这两个逻辑运算符来判断字段是否是数字型,但因为字段型的and和or返回的结果都为正常页面,我们就不好通过or来进行比较,一般习惯于用and 1=2,如果是数字型,返回错误,但如果是字符型,返回正确,这样两者之间就有了不同,有了比较。具体的理解可以接着往下看。
假如在1后面加上单引号’ , $id的值就是1’
这时数据库执行的语句就是 select * from table where id=1’
单引号不匹配,语句正确,页面返回错误
假设数据库的执行语句是:select * from table where id=’$id’
当查询id=1的页面时返回正常页面,此时执行的语句是:select * from table where id=‘1’
假如在1后面加上 and 1=2 $id的值就是1 and 1=2
这时数据库执行的语句就是 select * from table where id=‘1 and 1=2’
页面返回正常
假如在1后面加上 or 1=1 $id的值就是1 or 1=1
这时数据库执行的语句就是 select * from table where id=‘1 or 1=1’
页面返回正常
不管是and或者or,执行结果都是一样的,都会返回id=1的页面,那么为什么会这样呢?
因为数据库中id的类型是数值型,比如int型,而MySQL数据库在执行语句时是会自动进行类型转换的,输入的字符1 or 1=1会在执行时被自动转换成int型的1,所以最终的执行语句还是select * from table where id=‘1’
这是数据库的特性问题,后面的字符可以是任意的,不会影响查询,我们在1后面加上任意字符,比如1dogjoreg,最后都会被转换为1来进行语句执行。
如果id本身就是varchar类型的,那么数据库查询的时候就会进行精准的匹配,这样子’1dogjoreg’等类似的数据由于数据库里没有匹配项,查询结果为空。
所以,如果字段是字符型的,那么我们使用and或者or来测试时页面返回都是正常的,接上文,比较不同可以得出结论
输入$id=1’
执行的SQL语句就是select * from table where id=‘1’’
单引号不匹配,语句错误,页面错误
所以我们要闭合多余的单引号,使用注释符#或者–+
执行的SQL语句就是select * from table where id=‘1’ --+’
语句正确,页面正常
这里就和上文中数字型判定方式产生了不同了,数字型判定尽管加上注释符,执行的SQL语句是select * from table where id=1’ --+’ 因为单引号还是不匹配,语句还是错误的,页面还是返回错误。
综上,可以得出下表:
$id | 数字型(id=$id) | 字符型 (id=’$id’) |
---|---|---|
1 and 1=1 | id=1 and 1=1 返回正常 | id=‘1 and 1=1’ 返回正常 |
1 and 1=2 | id=1 and 1=2 返回错误 | id=‘1 and 1=2’ 返回正常 |
1 or 1=1 | id= 1 or 1=1 返回正常 | id= ‘1 or 1=1’ 返回正常 |
1 or 1=2 | id=1 or 1=2 返回正常 | id=‘1 or 1=2’ 返回正常 |
1’ | id=1’ 返回错误 | id=‘1’’ 返回错误 |
1’ --+ | id=1’ --+ 返回错误 | id=‘1’ --+’’ 返回正常 |