游客发表
去年秋天,站漏一个做外贸的洞修朋友半夜给我发消息,说网站首页被挂了一个跳转代码,站漏手机端访问直接跳到一个博彩页面。洞修我让他把源码打包发过来,站漏翻了几分钟就定位到问题:产品展示页的洞修某个参数没有过滤,直接拼进了SQL查询里。站漏这不是洞修什么高深漏洞,就是站漏典型的SQL注入,但造成的洞修后果很直接——数据库里的管理员密码被拖走,攻击者进后台改了模板文件。站漏
很多人觉得PHP网站漏洞离自己很远,洞修尤其是站漏那些用现成CMS搭站的。事实是洞修,大量被黑的站漏站点恰恰是用了过时的插件或主题。我见过一个WordPress站点,核心程序更新到最新版,但一个三年前停更的滑块插件还在跑,那个插件里有个文件上传接口,验证逻辑写得很随意,只检查了MIME类型,改成image/jpeg就能传上去一个PHP文件。攻击者拿到这个文件后,整台服务器基本就交出去了。
修复漏洞这件事,第一步永远不是去改代码,而是先搞清楚入口在哪。我习惯先看访问日志,找那些返回200状态码的可疑请求。比如某个不存在的页面被反复访问,或者参数里带了单引号、../、base64这类特征。有一次我发现一个请求路径是/data/cache.php?action=../../../../etc/passwd,这明显是目录穿越,顺着这个文件去看,果然在include之前没有对action做白名单校验。
确认漏洞点之后,修复方式要分情况。SQL注入最直接的办法是改用预处理语句。很多老代码用mysql_query拼字符串,改成PDO或mysqli的prepare加bind_param,基本能堵死。但要注意,如果表名或字段名是动态的,预处理帮不上忙,这时候必须用白名单限制。我见过有人把用户输入的表名直接拼进ORDER BY,这种场景预处理无能为力,只能自己写映射。
文件上传漏洞更麻烦。只判断后缀名不够,phtml、php5、pht这些都可能被解析。稳妥的做法是重命名文件,并且把上传目录的PHP解析权限关掉。Nginx里加一条location ~* /uploads/.*\.php$ { deny all; },Apache用.htaccess写php_flag engine off。另外,文件内容也要检查,用getimagesize()验证是不是真图片,防止图片马。
XSS修复相对简单,输出到HTML上下文用htmlspecialchars($str, ENT_QUOTES, 'UTF-8'),输出到JS里用json_encode,输出到属性里加引号并转义。但有个坑:htmlspecialchars默认只转义双引号,如果属性用单引号包裹,必须加ENT_QUOTES。我见过有人漏了这个参数,结果单引号闭合属性后注入事件。
会话安全也常被忽略。很多站点登录后只设置$_SESSION['user'],没有session_regenerate_id(true),导致会话固定攻击。攻击者先访问站点拿到一个session id,诱导受害者用这个id登录,之后攻击者就能用同一个id访问已登录状态。修复就是在登录成功后立刻重新生成session id,并且给cookie加上HttpOnly和Secure标记。
最后说一个真实案例。一个客户站点被植入后门,我删掉后门文件后,第二天又出现了。查了crontab没发现异常,最后在/tmp下找到一个伪装成日志的脚本,里面用curl从远程拉取新后门。清理时不能只删Web目录下的文件,要检查计划任务、启动项、/tmp、/dev/shm这些地方。很多时候,修复漏洞不只是改代码,还要把系统里被埋的钉子拔干净。
漏洞修复没有一劳永逸。今天补了SQL注入,明天可能冒出反序列化。保持依赖更新、日志监控、最小权限原则,比任何单次修复都管用。
友情链接