WordPress 站点地址被恶意篡改的防护方案讨论

WordPress 站点的安全性非常重要,稍有不慎就有可能受到恶意攻击。一种常见的手段是通过篡改站点的地址,于是用户访问网站时将会被重新定向到恶意网站。

WordPress 站点地址被恶意篡改的防护方案讨论

一般情况下,有 2 种手段可以达到这个目的,下面就让长老带领大家一步步去看整个攻击手段是如何实施的,并找到每个环节的安全防护措施,大家可以根据自己的情况使用其中的某个或多个防护措施。也欢迎大家留言分享各自的防护心得。

第一种攻击手段是在文件中写入恶意代码。

该恶意代码的表现形式为在网页加载时执行一段 JS 代码, 跳转到恶意网址。

尽管我们可以保证自己购买的插件和主题都是正版软件,我们也无法保证插件和主题没有任何安全漏洞。一部分国产主题为了激活的校验以及防止盗版,往往会故意留下一个口子,用来往数据库中写入授权信息,再加上 WordPress 的插件和主题文件本身就被设计成了可以被修改的,所以这样的口子就会成为一个危险的入口。

最根本的方法当然是及时修补这个漏洞,将插件和主题更新到最新版。但是在此之前,我们只能通过一些并不是“治本”的方法来阻止这件事情发生。

WordPress 站点地址被恶意篡改的防护方案讨论

WordFence 之类的安全防护软件也可以找到恶意代码的源头,但是很多恶意代码并不是很显而易见的,它会多次中转,使得前面的代码看上去都是非常正常的内容,这样就算删掉了最后的危险代码,由于前面的代码还在,所以过段时间就会死灰复燃。

如图是在一个主题文件中插入恶意代码的示例,恶意代码十分隐晦,并不能直接通过搜索 <script> 关键字查找,而且要调用好几层。

WordPress 站点地址被恶意篡改的防护方案讨论

注意这段代码并不是通过 Unix Shell 执行的,而是被 PHP 执行的,所以,就算我们没有给这个文件执行的权限,也依然无法阻止这段恶意代码被执行。因此,「权限不要给太高」这个教训在这儿并不好使,这不是权限上能解决的。

这段代码通过 POST 请求去访问了一个被 BASE64 加密的网址,然后将请求得到的内容写到了一个名为 _a 的文件中,并将 _a 包含进了主题文件中,因此,只要主题被加载了,_a 也被加载了。

WordPress 站点地址被恶意篡改的防护方案讨论

获取到的这段代码被写到了 <?php 后面,因此仍然会被作为 PHP 代码执行。_a 是一段 Unix Shell 命令,通过 PHP 的 shell_exec() 执行了这段命令。命令通过 wget 请求了一个脚本,并执行了这个脚本。

这个危险的脚本做的事情是在 WordPress 的核心的几个 index.php 的文件开始处,加上一段 <script src="bad_zzw.js"></script> 的文件,这样当 WordPress 被加载时,就会执行这段 JS 代码,去请求了 src="bad_zzw.js" 中的 JS,而 bad_zzw.js 的内容只有 2 行,包括了一句 windows.location,即将当前页面重定向到一个恶意的链接页面。

到这里,我们得到了第一个防护措施,那就是 PHP 官方推荐的:禁用 shell_exec()

可是,万一本机别的服务需要用到 shell_exec() 呢,这个虽然不安全,但是我却不得不使用它。在没有可能改变其他业务的情况下,这个函数不能被禁用。

那我们就要尝试将主题文件和 WordPress 核心的文件设置为只读了。

一般而言,文件的最小权限会被设置为 644640,即自己可读写、组内其他用户只读、组外用户只读(或者组外用户无权限),不会给执行权限 x;而目录的最小权限会被设置为 755 或者 750,对于目录而言,x 不再表示执行,而是表示是否可以进入该目录访问其中的内容。

于是我们有了第二个防护措施,那就是将主题、插件文件夹递归地设置为只读:首先 chown -R www:www . 确保整个目录都在 www 用户组内,然后 chmod 0640 -R . 递归地将目录下的文件全部修改为 640 权限,最后 find -type d -exec chmod 0750 {} \; . 递归地找到目录下所有的类型为目录的,并调用 exec 将权限修改为 750

对于 WordPress,只读的权限不会带来任何问题,www 用户组也足以完成全部的操作。只是需要注意的是,这样将不再支持有文件读写操作的行为,例如插件的更新、例如某些插件需要在目录中生成缓存或配置文件等。

第二种攻击手段是修改数据库的字段。

我们这里不讨论数据库密码泄露、数据库管理面板漏洞这样的问题,只考虑数据库用户和密码足够复杂,而攻击者利用 WordPress 的「合法的」数据库访问操作来修改了数据库的字段。由于所有的操作都是 WordPress 的「合法的」数据库访问,所以我们没有办法判断这是恶意攻击,还是正常的数据库访问(例如更新设置、读写文章)。

恶意攻击通常会篡改 wp_options 中的 siteurl 值和 home 值,使得用户访问站点时,站点 URL 部分被替换成恶意网站,实现跳转,并且由于 /wp-admin 的访问也会校验站点地址,所以我们甚至无法登录后台去修改回来。

网上有很多这样的案例,并且也给出了解决方案。

网上参见的解决方案为:首先想办法进入数据库,不管是 phpMyAdmin 或者 Unix Shell 登录。修改 WordPress 数据库中 wp_options 表中的 siteurlhome,保存。这时候就可以登录后台了,只需要把确实的设置重新修改。

还可以修改 wp-config.php,通过 define('WP_HOME','https://www.jxtxzzw.com'); define('WP_SITEURL','https://www.jxtxzzw.com'); 来指定自己的站点地址。

这里长老再说一种方法:修改数据表,增加触发器。

CREATE DEFINER=`wp_user`@`localhost` TRIGGER `trg_update_wp_options_forbidden`
BEFORE UPDATE ON `wp_options`
FOR EACH ROW
IF (NEW.option_id IN (1,2,3,4)) THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;

这个触发器是在修改 wp_options 之前被触发,如果新修改的值的 ID 是 1、2、3、4,那么就令 SQL 执行超时,并输出信息「Cannot update locked record」。

注意:① 添加触发器需要较高级别的权限,你可以根据需要修改为 root。② 上面的 (1,2,3,4) 在我的数据表中对应 siteurlhomeblognameblogdescription,你可以根据自己的情况修改这些 ID,也可以直接指定 NEW.option_name。③ 你可以增加更多锁定的字段,例如 userscanregisterWPLANGdate_format 等等。④ 添加触发器前请先将内容修改为期望的值。⑤ 如果再次修改,需要先解除触发器。

保存后,让我们修改这个字段,发现已经不能修改了。

但这不会影响后台的设置,当我们同时修改了后台的「站点标题」和「新用户默认角色」后点击保存,我们发现没有被锁定的记录仍然可以正常修改,而被锁定的记录仍保持了锁定的内容。

如果你的兴致到这里就结束了,那么,已经做好了防护,可以去玩啦。站点地址已经不能被篡改。

WordPress 站点地址被恶意篡改的防护方案讨论

如果你还有兴趣,那么可以打开 SQL 的 general_log(这会保存下所有的 SQL 操作,文件大小增速很恐怖,记得及时关掉),去挖掘到底是什么时候、被谁、执行了怎么样的一条指令,再配合其他的手段,一步一步定位真凶,并进一步地去将它绳之以法。

关键词:WordPress,篡改,挂马,恶意,攻击,注入,跳转,重定向,网址,siteurl,home,url,hacked,jump,redirect

摘要:WordPress 站点稍有不慎就有可能受到恶意攻击。一种常见的手段是通过篡改站点的地址,用户访问网站时将会被重新定向到恶意网站。长老将分析两种常见的攻击手段:修改文件和修改数据库,并分享一些安全防护的小技巧。

原文链接:https://www.jxtxzzw.com/archives/5572

上一篇:Prometheus Operator 自定义配置


下一篇:桥接模式 VS 装饰器模式、状态模式 VS 策略模式的微妙之处