对discuz论坛的赵小姐灌水机器人处理

虽然BBS的已经衰落了,而大部分有着悠久历史的BBS也进入了很不活跃的状态,然而经历过这个时代的人来说保留好这些历史数据作为一份回忆就很不错。最近有个朋友找到我帮忙处理一下他的BBS遇到的问题,他的BBS是10年前的discuz7.0没升级过,然后管理员密码被盗,被赵小姐灌水机器人每天发很多帖子,本人也无法登陆。我花了点时间处理了一下顺便把简单方案总结一下。

首先,由于这些有历史BBS有漏洞且没有打过补丁,我遇到的就是一个discuz7.0版本的BBS,升级是不可能升级的了,这辈子都不可能升级了。所以这里最好把discuz的版本去搜一下,去官方看看有漏洞的把补丁打上:http://www.discuz.net/forum-10-1.html,至少可以过滤一部分脚本小子。这里我们看到discuz7.0恰好有一个严重的漏洞,于是按照官方办法补上。

然后是备份好源码和数据,因为还是可能有漏洞,攻击者删了源码或者数据库就麻烦了。源码我这里用git做备份,这里只需要备份源码就OK了,再.gitignore文件中把图片文件和log文件过滤掉,也就是这样:

cat .gitignore
*.jpg
*.JPG
*.png
*.PNG
*.rar
*.RAR
*.zip
*.ZIP
*.log

然后再git中把源码加入git管理,虽然discuz可能会动态生成一些php文件,但是这些都是写缓存啥的,我们不用care,因为我们的目的是保护网站源码。其实我们都知道discuz可能还有洞,按理说这种情况应该跑在docker容器里面的,否则别人拿到你webshell就可以搞你这台主机上别的东西提权,但是我遇到的是共享的PHP空间,根本装不了任何软件。而且我看了一下她空间里除了discuz之外放了很多别的杂七杂八的东西,我估计别人要拿webshell不难,只是没人感兴趣而已,不过这里我们就破罐破摔至少保证源码不被破坏吧。

源码目录用git管理好之后,我看了一下这个虚拟空间的apache运行用户和虚拟空间用户是一样的,所以别人只要拿到webshell之后想删你.git你也没办法,如果apache以其他用户运行还好说,没办法了。这也就导致了我们给源码目录+文件和缓存目录设置文件权限是徒劳的,如果你的apache/php-fpm的运行用户和源码用户不一样,可以设置一下就算别人拿到webshell也能少动你一点。

然后是数据库,用mysqldump来把数据库做一次备份,如果你有耐心的话可以再crontab中用一个shell脚本来定时备份,不过这个BBS没有新帖子所以备份一次就OK了。

之后是解决BBS本身的问题了,这个赵小姐灌水机器人比较坏,通过任意代码执行漏洞或者穷举的方式拿到了管理员的权限,进入了后台把另一个管理员的名字改成了test,然后把自己的密码改了,这就导致BBS的维护者无法登陆。首先我得重置BBS的密码,得了,先连上数据库吧,我本地用GUI连发现虚拟空间得数据库限制了ip,嘛,理所当然得。于是用filezilla上传了一个phpMyAdmin,然后再里面看了一下discuz得表,还挺多得,这08年的discuz版本已经搞这么复杂了。结合源码和数据库看了一下discuz的登陆机制,在网上也搜到了似乎是”md5(md5($password).$salt);”这样设置的密码,在uc的members那张表里面看到有salt,为了验证一下我拿一个普通账号的密码按照这个来算了一下发现的确如此,所以给2个管理员账号用初始密码加salt算出了hash值,最后更新到数据库中,这样初始密码就重置了。

然后用管理员密码登陆后台,发现赵小姐灌水机器人还把管理员给ban了,我给改回来,然后批量删除了有小姐关键字的几千个帖子,基本上清理的工作就到这里就结束了,然而还有一些善后的工作。

刷s1的时候就经常被赵小姐刷屏呢,可见这其实是非常难以处理的一个问题,现在这个场景摆在我面前我肯定想挑战一下。首先思路上来说,一个BBS的账号太多了,而弱密码很多很多,所以赵小姐灌水机器人可以很轻松的暴力穷举很多账号的密码(当然了如果BBS有漏洞的话,直接拿更简单),所以限制注册或者手动ban用户的方法是行不通的。另外禁止ip的办法也是行不通的,因为搞过爬虫的我最了解换ip是多么简单的事了。此外,我还希望我的这个解决方案最好不要去动discuz的源码,具有普适性一点,考虑了很久的解决思路如下:

由于赵小姐灌水机器人里面特征很明显,都是小姐啊电话啊等等,我们用一个简单的正则匹配就能检测到谁是机器人,然后把对应的用户放到黑名单里就ok了。可是由于我手里这个空间装了很多乱七八糟的东西,而且我不想弄她的源码。所以就只好用hack一点的方式来做了,首先在php.ini中用auto_prepend_file和auto_append_file里面自动包含一些处理逻辑,然后实现上面的思路,为了能在auto_prepend_file里就能截断用户,这是很dirty的办法。

那么更好的办法是啥呢?如果这个逻辑放到discuz源码里面来做的话是很简单的:

首先我们在根目录下的config.inc.php末尾添加一个检查敏感词的函数:

//对发现赵小姐的内容进行检测,然后把该用户加入禁言用户组

function block($content)
{
global $db;
global $discuz_user;
global $discuz_uid;
global $tablepre;
$content = preg_replace("#\W#u", "", $content);
$key_words="小姐|电话|電話|微信";
if(preg_match("#{$key_words}#", $content, $matches))
{
$msg = "discuz_uid:{$discuz_uid}, discuz_user:{$discuz_user}, {$matches[0]} is forbidden in {$key_words}! context:" . json_encode([$_GET, $_SERVER]) . PHP_EOL;
file_put_contents(__DIR__ ."/block.log", $msg, FILE_APPEND);
$db->query("UPDATE {$tablepre}members SET groupid='4' WHERE uid='{$discuz_uid}'");
$uri = dirname($_SERVER['PHP_SELF']);
header("Location: {$uri}/");
exit();
}
}

然后再discuz的include目录下的newthread.php和newreply.php这两个文件是发帖和更贴的,我们只需要再开头的地方,也就是这里引用一下这个函数:

if(!defined('IN_DISCUZ')) {
exit('Access Denied');
}
block($message);

然后就能再用户发帖或者跟帖的时候,检测内容是否含有几个赵小姐的关键词,如果是的话,就去数据库把用户弄到禁言组里面去,如果存在误杀的情况就需要管理员回去加回来了。至于到底哪些用户被禁言了,可以看根目录下的block.log这个文件了(虽然这里直接把block.log暴露给所有人都能下载感觉不太好,不过我偷个懒吧)。

大概就这样了。

回想当初一群人玩BBS也是非常开心的。

对discuz论坛的赵小姐灌水机器人处理》有1个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注