运维笔记:为WP“报警”插件添加管理员白名单功能,减少误报

我从2023年下半年开始,建设了自己的Wordpress安全运维插件,主要用于向威胁情报平台汇报入侵指标(IoC)。对于这个插件,日常维护的很大一块工作量在误报率处理上。举两个典型场景为例,管理员(我)登录后请求了某些敏感路径,或是管理员在未登录情况下请求敏感路径,这些情况理应被插件排除在外,不作为入侵指标上报。

一、思路打开

因为考虑到存在上述两种典型情况,即是管理员处于:①已登录;②未登录两个状态。那么第一个问题就是,如何在管理员未登录情况下,尽可能减少误报率呢?这一块我主要从管理员常用IP地址出发,用超全局变量$_SERVER[‘REMOTE_ADDR’]获取请求IP,比对管理员IP,不在管理员IP地址内的,则判断不匹配,返回false。这是小问题,如果用IP白名单这样简单粗暴的方法解决问题,新问题就会浮现。

现在进入第二个问题,管理员在异地登录,请求了敏感路径,如何减少误报率?这次我从Wordpress的cookie入手。已知用户登录后,Wordpress会生成名为wordpress_logged_in_<hash>的cookie,用于储存用户信息(还有一个wordpress_sec_<hash>,作用和wordpress_logged_in类似)。那么方法就是用超全局变量$_COOKIE来获取当前cookie,并检查cookie的键值,是否包含wordpress_logged_in,或wordpress_sec字段,如果不包含,则返回false。

在整个逻辑设计上,以上两个条件,必须同时为false,即请求IP既不是管理员IP,也未检测到用户登录cookie,才会启动上报流程。

二、三种实现方式

因为第一个检测是否为管理员IP的比较简单,用in_array(多个管理员IP)或者运算符(单个管理员IP)就可以轻松解决。而第二个检测cookie的,因为涉及到字符串部分匹配,同时可能要循环两个数组(wordpress_logged_in、wordpress_sec,以及$_COOKIE数组),稍微啰嗦一点。

循环两个数组,可能脑子里第一反应就是两个for循环叠加。但我个人极度厌恶循环嵌套,因此不得不寻求其他解决方法。

先来看下单个检测字符串的情况(wordpress_logged_in或wordpress_sec,二者选其一):

解决方法一:

$admin_cookie_key = 'wordpress_logged_in'; // 可自行修改为第二个字符串
foreach ($cookie_array as $key => $value) {
     if (strpos($key, $admin_cookie_key) !== false) {
         return true;
     }
}
return false;

解决方法二:

if (preg_match('/wordpress_sec/', var_export($cookie_array, true))) {
    return true;
}
return false;

如果你要同时检测两个数组,那么不用循环的情况下,可以这么写:

$admin_cookie_key = array('wordpress_logged_in', 'wordpress_sec');
$matching_keys = preg_grep('/' . implode('|', $admin_cookie_key) . '/', array_keys($cookie_array));
if (!empty($matching_keys)) {
    return true;
} else {
    return false;
}

发布者

发表回复

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