Web渗透之SQL注入-URL解码注入(URL Decode Injection) 📅 发布时间:2026/9/10 22:37:18 👁 浏览次数: 本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行任何未经授权使用文中技术的行为均与作者无关请务必遵守法律法规获得许可后方可进行渗透测试。目录一、概念1、核心原理2、常见场景3、实际例子4、更隐蔽的双重编码5、检测与利用方法6、防御措施7、总结二、URL解码原理1. URL编码简介2. 解码过程3. 为什么需要URL解码4. URL解码与注入的关系5. 关键点总结三、URL解码注入原理1. 正常处理流程无漏洞2. URL解码注入的核心——二次解码3. 为什么二次解码会导致注入4. 绕过 WAF 和黑名单5. 利用场景6. 防御措施7. 总结一句话四、靶场渗透示例一、漏洞代码二、注入原理双重编码三、注入过程1. 正常请求2. 尝试普通注入失败3. 双重编码绕过成功闭合引号4. 联合查询提取数据四、漏洞根本原因五、防御措施六、总结一、概念URL解码注入是一种利用 URL 编码百分号编码与应用程序解码顺序不一致导致的注入技术。攻击者将恶意 SQL 语句中的特殊字符如单引号、双引号、井号#等进行 URL 编码例如%27、%22、%23如果应用程序在接收参数后先进行 URL 解码再拼接到 SQL 语句中这些原本被编码的字符就会恢复原样从而改变 SQL 语义形成注入。1、核心原理大多数 Web 应用会自动对GET和POST参数进行一次 URL 解码。如果开发者错误地手动额外调用了解码函数如 PHP 的urldecode()、rawurldecode()或者应用服务器存在“二次解码”行为攻击者就可以利用编码绕过输入过滤如关键字黑名单、简单的转义。示例流程正常输入1 or 11攻击者 URL 编码为1%27%20or%20%271%27%271服务器自动解码一次1 or 11如果应用再次解码或使用不当则原始恶意 SQL 注入成功。2、常见场景双重 URL 解码某些 Web 应用在获取参数后会调用urldecode()而 Web 服务器如 Apache、IIS已经自动解码过一次导致二次解码。例如%2527%25解码为%再解码一次成为。输入1%2527→ 第一次解码得1%27→ 第二次解码得1。绕过简单的黑名单过滤如果应用拦截了、、#等字符但未对 URL 编码形式做检查攻击者可以用%27代替在解码后注入。WAF 绕过部分 Web 应用防火墙WAF对请求进行检测时可能只识别原始字符串而忽略了 URL 编码形式。攻击者通过编码可以绕过规则。3、实际例子假设 PHP 代码如下$id urldecode($_GET[id]); // 额外的一次解码 $sql SELECT * FROM users WHERE id$id;攻击者访问http://example.com/page.php?id1%27%20or%20%271%27%271URL 编码部分%27→%20→ 空格。经过urldecode()后$id的值为1 or 11。最终 SQL 变为SELECT * FROM users WHERE id1 or 11导致注入成功返回所有用户。4、更隐蔽的双重编码http://example.com/page.php?id1%2527%2520or%2520%25271%2527%25271%25解码为%%27解码为二次解码后得到1 or 11。5、检测与利用方法输入1%27观察是否触发数据库错误如单引号未闭合。输入1%2527观察是否出现同样的错误。使用%23代替#进行注释%2d%2d代替--等。6、防御措施避免手动 URL 解码Web 服务器已经自动解码一次程序不应再调用urldecode()、rawurldecode()。使用参数化查询预编译语句完全不受注入影响。输入验证采用白名单校验或直接使用类型转换如intval()处理数字型参数。WAF 规则优化检测 URL 编码后的危险字符如%27、%22、%23以及双重编码模式。正确设置字符编码确保 UTF-8 等一致性避免编码漏洞。7、总结URL 解码注入的本质是应用程序对用户输入进行了不必要的二次 URL 解码导致原本被编码的 SQL 元字符恢复活性从而利用注入漏洞。防御的核心是不要手动解码参数化查询。如果必须解码应确保在安全处理之后如先解码再转义但最佳实践是不解码。二、URL解码原理URL解码也称为百分号解码是 URL 编码百分号编码的逆过程。其核心原理是将%后跟两位十六进制数如%20、%27、%E4%BD%A0转换回原始字符。1. URL编码简介URL中只允许包含ASCII 字符集中的一部分安全字符字母、数字、-、_、.、~其他字符如汉字、空格、#、、、等必须编码为%后跟该字符的ASCII 码或UTF-8字节序列的十六进制表示。空格→ ASCII 码 320x20 →%20单引号→ ASCII 码 390x27 →%27井号#→ ASCII 码 350x23 →%23中文“你”→ UTF-8 编码为三个字节0xE4 0xBD 0xA0→%E4%BD%A02. 解码过程解码时从左到右扫描字符串遇到普通字符非%直接原样输出。遇到%则读取其后的两个字符必须是合法的十六进制数字 0-9、A-F、a-f将它们组合成一个字节0~255然后输出该字节对应的 ASCII 字符或 UTF-8 序列的一部分。示例输入Hello%20World%21 - %20 → 0x20 → 空格 - %21 → 0x21 → ! 输出Hello World!示例UTF-8多字节输入%E4%BD%A0 - %E4 → 0xE4 - %BD → 0xBD - %A0 → 0xA0 这三个字节组合成 UTF-8 编码的“你”字。 输出你3. 为什么需要URL解码浏览器会自动将 URL 中的百分号编码解码后显示地址栏看到的是原始字符但实际传输的是编码。服务器收到请求后Web 服务器如 Apache、Nginx、IIS会自动进行一次 URL 解码将%XX还原为对应字符然后将解码后的参数交给 Web 应用如 PHP、Java。开发人员通常无需手动解码因为$_GET、$_POST等超全局变量已经是解码后的值。4. URL解码与注入的关系正常情况应用只依赖 Web 服务器的自动解码不存在二次解码因此%27会被还原为可能引发 SQL 注入如果应用本身有注入漏洞。危险情况开发者错误地调用urldecode()或rawurldecode()对已解码的输入再次解码造成二次解码。攻击者可以利用双重编码如%2527绕过输入过滤或 WAF。二次解码示例原始输入%2527 服务器第一次解码%25 → %%27 → 结果变为 %27 开发者手动解码%27 → 最终得到单引号实现注入。5. 关键点总结URL解码就是将%XX序列还原成原始字节/字符的过程。解码算法简单识别%取后两位十六进制数转为十进制 ASCII 码输出对应字符。浏览器和 Web 服务器都进行一次解码。应用层不应再手动解码否则可能引入双重解码漏洞。防范 URL 解码注入的最佳方法是参数化查询而不是依赖过滤或转义。三、URL解码注入原理URL解码注入本质上是应用程序对用户输入进行了多余的、额外的URL解码导致原本安全的编码字符在多次解码后还原成SQL元字符从而改变SQL语句结构实现注入。1. 正常处理流程无漏洞浏览器/客户端 → Web服务器自动解码一次→ 应用层直接使用解码后数据 例如 用户输入1%27→ 服务器自动解码为1→ PHP 的$_GET[id]得到1。 如果应用存在SQL注入漏洞此时1就会触发错误。这是普通注入不是URL解码注入。2. URL解码注入的核心——二次解码当应用在获取参数后再次手动调用解码函数如 PHP 的urldecode()、rawurldecode()就会产生二次解码。典型错误代码$id urldecode($_GET[id]); // 已经解码过一次又解码第二次 $sql SELECT * FROM users WHERE id$id;攻击过程攻击者输入1%2527其中%25是%的编码%27是的编码。第一次解码Web服务器自动%25→%%27→得到1%27。第二次解码urldecode手动1%27→1。最终 SQLSELECT * FROM users WHERE id1→ 语法错误或注入成功。更典型的注入 payload1%2527%20or%20%271%27%271经过二次解码后变成1 or 11实现经典万能密码注入。3. 为什么二次解码会导致注入正常情况下单引号在第一次解码后就已经还原如果应用有转义如addslashes它会被转义成\从而失效。但是二次解码时%2527经过第一次解码变成%27这个%27不是单引号字符而是一个百分号和数字串因此不会被转义函数处理因为转义函数只作用于字符不作用于字符串%27。第二次解码将%27变成此时才出现但转义过程已经结束从而成功注入。4. 绕过 WAF 和黑名单许多 WAF 或输入过滤器会检查、、#等危险字符但可能忽略%2527双重编码。服务器解码两次后WAF 只看到了第一次解码后的%27不是危险字符而第二次解码在 WAF 检测之后发生因此绕过。5. 利用场景PHP 中使用urldecode()、rawurldecode()处理 GET 或 POST 参数。某些框架或中间件如 Tomcat、IIS在特定配置下会产生额外解码。开发人员错误地将已经解码的数据再次解码。6. 防御措施不要手动解码 URL 参数$_GET、$_POST已经是解码后的值无需再调用urldecode。使用参数化查询无论是否解码预编译语句都能彻底防御 SQL 注入。输入验证对数字型参数使用intval()对字符串使用白名单。WAF 规则检测双重编码特征如%25后跟十六进制。7. 总结一句话URL解码注入是利用应用程序对用户输入进行多余的二次URL解码使得原本被编码的SQL元字符在解码后才出现从而绕过转义和过滤实现SQL注入的攻击技术。四、靶场渗透示例一、漏洞代码$id addslashes($_GET[id]); // 转义特殊字符 $id urldecode($id); // 再次URL解码 ← 危险操作 $sql select * from userinfo where id{$id};关键点addslashes会在单引号、双引号、反斜杠\、NULL 前加反斜杠。正常情况下用户输入1会被转义为1\无法注入。但代码中二次调用urldecode使得攻击者可以利用双重 URL 编码绕过转义。二、注入原理双重编码攻击者输入1%2527--%25是%的 URL 编码%27是的 URL 编码。Web 服务器自动解码一次 →1%27--。addslashes处理1%27-- 此时字符串中的%27只是普通字符%、2、7没有单引号所以addslashes不会添加反斜杠。结果仍为1%27--。urldecode再次解码将%27转换为得到1--。拼接到 SQL... where id1-- 成功闭合引号并注释掉后面的内容实现注入。关键addslashes作用于未解码的%27字符串此时它不是单引号故不被转义二次解码后才变成真正的单引号从而绕过防护。三、注入过程1. 正常请求http://127.0.0.1/demo5.php?id1页面显示select * from userinfo where id1 Array ( [0] 1 [1] dsqaf [2] sadfsaf )2. 尝试普通注入失败http://127.0.0.1/demo5.php?id1 -- -SQL 变成id1\ -- -单引号被转义无法注入仍返回原数据。3. 双重编码绕过成功闭合引号http://127.0.0.1/demo5.php?id1%2527--页面显示 SQLselect * from userinfo where id1-- 说明%2527成功变为并注释掉了后面的内容。此时查询返回原数据因为id1存在但证明注入点可用。4. 联合查询提取数据http://127.0.0.1/demo5.php?id1%2527 union select 1,2,3 limit 1,1--页面显示select * from userinfo where id1 union select 1,2,3 limit 1,1-- Array ( [0] 1 [1] 2 [2] 3 )成功通过联合查询获取了1,2,3说明可以任意执行 SQL 语句。四、漏洞根本原因错误的处理顺序先转义addslashes后解码urldecode导致二次解码产生的新特殊字符未被转义。双重 URL 编码%2527在一次解码后变为%27仍不是特殊字符二次解码后才成为成功绕过。五、防御措施不要手动解码 URL 参数$_GET、$_POST已经自动解码禁止再次调用urldecode/rawurldecode。使用参数化查询这是根本解决方案与编码、转义无关。如果必须处理编码应先解码再转义但最安全的是不用转义直接用预编译。输入验证数字型参数用intval()字符串用白名单。六、总结本次实战演示了URL解码注入二次解码的经典利用方式通过%2527双重编码绕过addslashes转义最终实现 SQL 注入。该漏洞的根源在于应用层多余的urldecode操作使得攻击者能够“复活”被编码的单引号。