|
攻击者把一段PHP代码塞进一个图片文件,注入改名为shell.jpg,注入然后上传到目标站点的注入/uploads目录。浏览器访问这个jpg,注入服务器直接执行了里面的注入代码——一个中国菜刀连接上了,整个网站的注入后台权限就此易主。这是注入最经典的webshell注入场景,也是注入我在安全测试中反复验证过的事实。 webshell的注入本质就是一段能执行系统命令的脚本。它不一定叫shell.php,注入可以伪装成图片、注入日志、注入甚至看似无害的注入CSS文件。关键在于服务器如何解析它——如果Apache配置了将.jpg文件按PHP解析,注入那图片就是注入木马。很多站长以为上传目录不做脚本执行权限就安全了,但Nginx的解析漏洞曾经让任何上传的图片都能被当PHP执行,只要在URL后面加上/x.php。这类漏洞现在依然存在于一些老旧系统中,我见过不少企业因为这种配置疏忽被拖库。 注入方式五花八门,但路径无非三条。文件上传是最直接的,攻击者利用表单验证不严,绕过content-type检查,把恶意脚本送进服务器。其次是数据库备份或日志导入功能,把PHP代码写入到可访问的文件中——比如把一句话木马写进日志,然后包含日志文件触发执行。第三种是反序列化漏洞,攻击者构造特殊对象,让应用在反序列化时执行任意代码。别笑,我见过一个内部系统把用户输入直接拼接进eval()里,那简直是把大门钥匙挂在门口。 检测webshell比注入更头疼。静态扫描能查出已知特征码,但攻击者随便混淆一下变量名就能绕过。动态检测观察文件是否被意外修改、进程是否有异常子进程,可这需要基线数据,很多公司根本不知道自己的Web目录正常时该是什么样。有一次我帮客户排查,发现他们的图片目录里有个文件修改时间比服务器上线时间还早,一查果然是攻击者手动改的时间戳——这种精心伪装需要行为分析才能揪出来。 防御得从根上做。上传目录强制禁止脚本执行,这是最有效的——就算攻击者传上来shell,服务器也只当它是静态文件。然后是对上传内容做二次渲染,比如图片用GD库重新生成一次,把里面的PHP代码直接过滤掉。还有限制上传文件类型,白名单比黑名单靠谱,允许的扩展名就那么几个,其余全拒绝。代码层面别用eval、system这类危险函数,用正则替换代替拼接执行,如果非用不可,至少加个白名单过滤。 但真正的问题是,很多开发团队根本没把webshell当回事。他们觉得“服务器是运维管的,代码是开发写的,安全是安全团队的事”。结果运维开了上传目录的写权限,开发把用户输入拼进SQL查询,安全团队连日志都没开。等被入侵了才互相甩锅。我见过一家电商公司,攻击者拿到shell后潜伏了三个月,每个月悄悄修改支付接口的收款账号,直到用户投诉才被发现。那种沉默的代价,比任何安全投入都昂贵。 防住一次注入不难,难的是持续防住。攻击者会不断尝试新姿势,而你的系统每增加一个功能,就可能多一个攻击面。所以别指望装个WAF就万事大吉,那只是降低了门槛,不是关上了门。定期做渗透测试、监控文件完整性、保持组件更新,这些琐碎的事才是真正的防线。如果你懒得做,那就祈祷攻击者比你还懒——可惜,他们通常勤快得很。 |