WordPress开发:实现过滤包含恶意代码的危险评论的插件

操作环境

操作系统信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
master@ubuntu:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
master@ubuntu:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.4 LTS Release: 18.04 Codename: bionic
master@ubuntu:~$ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:    18.04
Codename:    bionic

WordPress 信息:

主程序版本:WordPress 5.3.2
主题及版本:Twenty Sixteen(版本:2.0, 由WordPress团队开发)

需求分析

运行在公网中的 WordPress 站点极易遭受 SQL 注入攻击以及 XSS 跨站脚本攻击等。即便是一个不开放用户注册功能的个人博客,也存在攻击切入点,例如评论框。目前版本的 WordPress (WordPress 5.3.2) 本身并不会把可能包含恶意代码的评论删除,在 WordPress 没有被暴露出漏洞的时候,这么做可能并没有什么问题,但是一旦被发现存在漏洞,那么允许包含恶意代码的数据存入数据库就会变得很危险。因此,我的需求就是,一旦评论中被检测到存在可能的恶意代码,就要把该评论删除,同时,用一条表达警示信息的预置标准评论代替该评论,从而使得任何可能包含恶意代码的评论都不被写入数据库,最大程度地防范 SQL 注入攻击和 XSS 跨站脚本攻击等。

格式说明

  • 在本文中所出现的代码中,凡是我自己定义的函数和变量等,一般都会以 zkf_ 作为其前缀;
  • 没有使用 zkf_ 作为前缀的函数或者变量等,一般情况下都是 WordPress 平台或者 PHP 提供的。
  • 在没有特殊说明的情况下,下文中出现的 “WordPress” 和 “WP” 所代表的是相同的含义。
  • 本文代码块中出现的 ... ... 表示这些位置还存在其他代码,但与当前要说明的问题关系不大,故省略之。

实现过程

前面的需求可以转换成如下步骤,如图 1:

图 1.

要获取评论内容,我们就需要使用 WordPress 平台提供的如下函数:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
wp_insert_comment( array $commentdata )
wp_insert_comment( array $commentdata )
wp_insert_comment( array $commentdata )

关于该函数的更多详细信息参见 References [1].

该函数的作用是将一个评论插入数据库中。该函数提供了很多参数,我们只需要使用其中一个参数,如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
comment_content
comment_content
comment_content

comment_content 参数可以返回评论的内容,类型为 string.

wp-includes/comment.php 文件中,我们可以找到如下钩子激活点:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function wp_insert_comment( $commentdata ) {
... ...
/**
* Fires immediately after a comment is inserted into the database.
*
* @since 2.8.0
*
* @param int $id The comment ID.
* @param WP_Comment $comment Comment object.
*/
do_action( 'wp_insert_comment', id,comment );
... ...
}
function wp_insert_comment( $commentdata ) { ... ... /** * Fires immediately after a comment is inserted into the database. * * @since 2.8.0 * * @param int idThecommentID.@paramWPCommentcomment Comment object. */ do_action( 'wp_insert_comment', id,comment ); ... ... }
function wp_insert_comment( $commentdata ) {

... ...

/**
         * Fires immediately after a comment is inserted into the database.
         *
         * @since 2.8.0
         *
         * @param int        $id      The comment ID.
         * @param WP_Comment $comment Comment object.
         */
        do_action( 'wp_insert_comment', $id, $comment );

... ...

}

去掉注释更清楚:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function wp_insert_comment( $commentdata ) {
... ...
do_action( 'wp_insert_comment', id,comment );
... ...
}
function wp_insert_comment( $commentdata ) { ... ... do_action( 'wp_insert_comment', id,comment ); ... ... }
function wp_insert_comment( $commentdata ) {

... ...

    do_action( 'wp_insert_comment', $id, $comment );

... ...

}

关于该钩子激活点的更多详细信息参见 References [2].

由上面提到的 do_action( 'wp_insert_comment', $id, $comment ); 钩子激活点的格式我们知道,wp_insert_comment 这个钩子函数可以提供两个参数,分别是评论 ID $id 和评论内容 $comment. 因此,在定义动作函数 zkf_comment_check() 时,我们同样需要为其设置两个参数,这样才能完成挂载。

接下来,使用 add_actionzkf_comment_check() 函数挂载到 wp_insert_comment, 我们之后的实现代码将写在 zkf_comment_check() 动作函数中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);

根据上面的代码,我们知道,该挂载点的优先级为 10, 需要为该挂载点 (即 zkf_comment_check() 函数) 传入参数的个数为 2.

接下来,开始实现 zkf_comment_check() 函数。

首先定义 zkf_comment_check() 函数并为其传入两个参数:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function zkf_comment_check(zkfcommentid,zkf_comment_object){
}
function zkf_comment_check(zkfcommentid,zkf_comment_object){ }
function zkf_comment_check($zkf_comment_id, $zkf_comment_object){

}

之后,开始在 zkf_comment_check() 函数中写入具体的实现代码。

首先创建一个数组,命名为 $zkf_commentarr

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$zkf_commentarr = array();
$zkf_commentarr = array();
$zkf_commentarr = array();

接着使用从钩子函数那里接收到的评论 ID 为数组赋值:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$zkf_commentarr['comment_ID'] = $zkf_comment_id;
zkfcommentarr[commentID]=zkf_comment_id;
$zkf_commentarr['comment_ID'] = $zkf_comment_id;

在上面的代码中,我们用到了 WP 平台提供的 comment_ID 函数,该函数的作用是返回当前评论的 ID. 详情可参见 References [3].

之后,通过 comment_content 参数获取当前评论的内容:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
zkfnewcomment=zkf_comment_object->comment_content;
zkfnewcomment=zkf_comment_object->comment_content;
$zkf_new_comment = $zkf_comment_object->comment_content;

之后,将评论中的字母全部转换成小写,作为防止大小写绕过的第一道关卡:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$zkf_new_comment_check = strtolower($zkf_new_comment);
zkfnewcommentcheck=strtolower(zkf_new_comment);
$zkf_new_comment_check = strtolower($zkf_new_comment);

通过分析常见的 SQL 注入语句和 XSS 跨站脚本攻击代码,我总结出了如下危险关键字,一旦评论中出现了这些关键字,则评论者极有可能是在尝试进行攻击:

  • +
  • #
  • %
  • ||
  • @
  • @@
  • insert
  • update
  • delete
  • and
  • or
  • union
  • select
  • from
  • where
  • limit
  • order by
  • guoup by

我们要对上面这些危险关键字进行过滤,实现代码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$zkf_str = "+\#\--\%\||\@\@@\insert\update\delete\and\or\union\select\from\where\limit\order by\guoup by\<script>\</script>";
$zkf_str = "+\#\--\%\||\@\@@\insert\update\delete\and\or\union\select\from\where\limit\order by\guoup by\<script>\</script>";
$zkf_str = "+\\#\\--\\%\\||\\@\\@@\\insert\\update\\delete\\and\\or\\union\\select\\from\\where\\limit\\order by\\guoup by\\<script>\\</script>";

使用 \ 做分割标记,将字符打散为数组 $zkf_arr:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$zkf_arr=explode("\",$zkf_str);
zkfarr=explode("",zkf_str);
$zkf_arr=explode("\\",$zkf_str);

接下来,使用 PHP 提供的 foreach() 函数,对数组 $zkf_arr 中的每一个键值进行遍历,之后,在 foreach() 函数中使用 stripos 函数对评论内容和取出的键值进行忽略大小写的比较(这里是防止大小写绕过的第二道关卡)并将比对的结果赋值给 $zkf_flag. 若 $zkf_flag = flase, 则代表评论中不包含预置的危险代码,若 $zkf_flag = true, 则代表评论中包含预置的危险代码,此时,评论内容会被替换成“《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》”,原来含有危险代码的评论会被丢弃,不会写入数据库。代码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
foreach(zkfarraszkf_key => $zkf_val){
//使用 PHP strpos() 函数对内容进行过滤
//stripos() 函数不区分大小写
//strpos() 函数区分大小写
/*
前面已经将所有字符都转换成小写了
这里使用 stripos() 函数再次忽略大小写
可以起到双保险的作用
*/
$zkf_flag=stripos(zkfnewcommentcheck,zkf_val);
if ($zkf_flag){
$zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
}
}
foreach(zkfarraszkf_key => $zkf_val){ //使用 PHP strpos() 函数对内容进行过滤 //stripos() 函数不区分大小写 //strpos() 函数区分大小写 /* 前面已经将所有字符都转换成小写了 这里使用 stripos() 函数再次忽略大小写 可以起到双保险的作用 */ zkfflag=stripos(zkf_new_comment_check,zkfval);if(zkf_flag){ $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》"; } }
foreach($zkf_arr as $zkf_key => $zkf_val){

//使用 PHP strpos() 函数对内容进行过滤
//stripos() 函数不区分大小写
//strpos() 函数区分大小写
/*
前面已经将所有字符都转换成小写了
这里使用 stripos() 函数再次忽略大小写
可以起到双保险的作用
*/
    $zkf_flag=stripos($zkf_new_comment_check,$zkf_val);
    if ($zkf_flag){
        $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
    }
}

去掉注释更清楚:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
foreach(zkfarraszkf_key => $zkf_val){
$zkf_flag=stripos(zkfnewcommentcheck,zkf_val);
if ($zkf_flag){
$zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
}
}
foreach(zkfarraszkf_key => $zkf_val){ zkfflag=stripos(zkf_new_comment_check,zkfval);if(zkf_flag){ $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》"; } }
foreach($zkf_arr as $zkf_key => $zkf_val){
    $zkf_flag=stripos($zkf_new_comment_check,$zkf_val);
    if ($zkf_flag){
        $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
    }
}

最后,使用 wp_update_comment 函数对数据库中已经存在的评论进行一次更新,关于该函数的更多详细信息参见 References [4].

完整的实现代码如下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//危险评论内容过滤模块
//添加评论时触发 zkf_comment_check() 函数
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);
//定义 zkf_comment_check() 函数
//传入评论 ID 和评论内容两个参数
function zkf_comment_check(zkfcommentid,zkf_comment_object){
//创建数组 $zkf_commentarr
$zkf_commentarr = array();
//PHP 会把单引号里的内容当成纯文本
//单引号里面是什么就理解成什么
//PHP 中的方括号[]和花括号{}都可以用来访问数组单元对应的值
//为数组赋值
$zkf_commentarr['comment_ID'] = $zkf_comment_id;
//获取当前的评论内容
zkfnewcomment=zkf_comment_object->comment_content;
//使用 PHP strtolower() 函数将评论内容中的
//将所有字母都转换成小写
$zkf_new_comment_check = strtolower($zkf_new_comment);
//把数据库查询代码和JS标记代码都视作危险代码
$zkf_str = "+\#\--\%\||\@\@@\insert\update\delete\and\or\union\select\from\where\limit\order by\guoup by\<script>\</script>";
//使用 \ 做分割标记,将字符打散为数组
$zkf_arr=explode("\",$zkf_str);
foreach(zkfarraszkf_key => $zkf_val){
//使用 PHP strpos() 函数对内容进行过滤
//stripos() 函数不区分大小写
//strpos() 函数区分大小写
/*
前面已经将所有字符都转换成小写了
这里使用 stripos() 函数再次忽略大小写
可以起到双保险的作用
*/
$zkf_flag=stripos(zkfnewcommentcheck,zkf_val);
if ($zkf_flag){
$zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
}
}
//对数据库中已经存在的评论进行更新
wp_update_comment($zkf_commentarr);
}
//危险评论内容过滤模块 //添加评论时触发 zkf_comment_check() 函数 add_action('wp_insert_comment', 'zkf_comment_check', 10, 2); //定义 zkf_comment_check() 函数 //传入评论 ID 和评论内容两个参数 function zkf_comment_check(zkfcommentid,zkf_comment_object){ //创建数组 zkfcommentarrzkf_commentarr = array(); //PHP 会把单引号里的内容当成纯文本 //单引号里面是什么就理解成什么 //PHP 中的方括号[]和花括号{}都可以用来访问数组单元对应的值 //为数组赋值 zkfcommentarr[commentID]=zkf_comment_id; //获取当前的评论内容 zkfnewcomment=zkf_comment_object->comment_content; //使用 PHP strtolower() 函数将评论内容中的 //将所有字母都转换成小写 zkfnewcommentcheck=strtolower(zkf_new_comment); //把数据库查询代码和JS标记代码都视作危险代码 You can't use 'macro parameter character #' in math modezkf_arr=explode("\",zkfstr);foreach(zkf_arr as zkfkey=>zkf_val){ //使用 PHP strpos() 函数对内容进行过滤 //stripos() 函数不区分大小写 //strpos() 函数区分大小写 /* 前面已经将所有字符都转换成小写了 这里使用 stripos() 函数再次忽略大小写 可以起到双保险的作用 */ zkfflag=stripos(zkf_new_comment_check,zkfval);if(zkf_flag){ Extra close brace or missing open bracezkf_commentarr); }
//危险评论内容过滤模块

//添加评论时触发 zkf_comment_check() 函数
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);

//定义 zkf_comment_check() 函数
//传入评论 ID 和评论内容两个参数
function zkf_comment_check($zkf_comment_id, $zkf_comment_object){

//创建数组 $zkf_commentarr
    $zkf_commentarr = array();

//PHP 会把单引号里的内容当成纯文本
//单引号里面是什么就理解成什么
//PHP 中的方括号[]和花括号{}都可以用来访问数组单元对应的值
//为数组赋值
    $zkf_commentarr['comment_ID'] = $zkf_comment_id;

//获取当前的评论内容
    $zkf_new_comment = $zkf_comment_object->comment_content;

//使用 PHP strtolower() 函数将评论内容中的
//将所有字母都转换成小写
    $zkf_new_comment_check = strtolower($zkf_new_comment);

//把数据库查询代码和JS标记代码都视作危险代码
    $zkf_str = "+\\#\\--\\%\\||\\@\\@@\\insert\\update\\delete\\and\\or\\union\\select\\from\\where\\limit\\order by\\guoup by\\<script>\\</script>";

//使用 \\ 做分割标记,将字符打散为数组
    $zkf_arr=explode("\\",$zkf_str);
    foreach($zkf_arr as $zkf_key => $zkf_val){

//使用 PHP strpos() 函数对内容进行过滤
//stripos() 函数不区分大小写
//strpos() 函数区分大小写
/*
前面已经将所有字符都转换成小写了
这里使用 stripos() 函数再次忽略大小写
可以起到双保险的作用
*/
    $zkf_flag=stripos($zkf_new_comment_check,$zkf_val);
        if ($zkf_flag){
            $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
        }
    }

//对数据库中已经存在的评论进行更新
    wp_update_comment($zkf_commentarr);
}

去掉注释更清楚:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);
function zkf_comment_check(zkfcommentid,zkf_comment_object){
$zkf_commentarr = array();
$zkf_commentarr['comment_ID'] = $zkf_comment_id;
zkfnewcomment=zkf_comment_object->comment_content;
$zkf_new_comment_check = strtolower($zkf_new_comment);
$zkf_str = "+\#\--\%\||\@\@@\insert\update\delete\and\or\union\select\from\where\limit\order by\guoup by\<script>\</script>";
$zkf_arr=explode("\",$zkf_str);
foreach(zkfarraszkf_key => $zkf_val){
$zkf_flag=stripos(zkfnewcommentcheck,zkf_val);
if ($zkf_flag){
$zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
}
}
wp_update_comment($zkf_commentarr);
}
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2); function zkf_comment_check(zkfcommentid,zkf_comment_object){ zkfcommentarr=array();zkf_commentarr['comment_ID'] = zkfcommentid;zkf_new_comment = zkfcommentobject>commentcontent;zkf_new_comment_check = strtolower(zkfnewcomment);zkf_str = "+\#\--\%\||\@\@@\insert\update\delete\and\or\union\select\from\where\limit\order by\guoup by\<script>\</script>"; zkfarr=explode("",zkf_str); foreach(zkfarraszkf_key => zkfval)$zkfflag=stripos($zkfnewcommentcheck,$zkfval);if($zkfflag)$zkfcommentarr[commentcontent]="";wpupdatecomment(zkf_commentarr); }
add_action('wp_insert_comment', 'zkf_comment_check', 10, 2);

function zkf_comment_check($zkf_comment_id, $zkf_comment_object){

    $zkf_commentarr = array();

    $zkf_commentarr['comment_ID'] = $zkf_comment_id;

    $zkf_new_comment = $zkf_comment_object->comment_content;

    $zkf_new_comment_check = strtolower($zkf_new_comment);

    $zkf_str = "+\\#\\--\\%\\||\\@\\@@\\insert\\update\\delete\\and\\or\\union\\select\\from\\where\\limit\\order by\\guoup by\\<script>\\</script>";

    $zkf_arr=explode("\\",$zkf_str);
    foreach($zkf_arr as $zkf_key => $zkf_val){

    $zkf_flag=stripos($zkf_new_comment_check,$zkf_val);
        if ($zkf_flag){
            $zkf_commentarr['comment_content'] = "《该评论中发现危险代码,已被箭幕防御系统危险评论拦截模块删除。》";
        }
    }

    wp_update_comment($zkf_commentarr);
}

运行效果如图 2 所示:

图 2.

References:
[1]. wp_insert_comment() | Function | WordPress Developer Resources
https://developer.wordpress.org/reference/functions/wp_insert_comment/
[2]. wp_insert_comment | Hook | WordPress Developer Resources
https://developer.wordpress.org/reference/hooks/wp_insert_comment/
[3]. comment_ID() | Function | WordPress Developer Resources
https://developer.wordpress.org/reference/functions/comment_id/
[4]. wp_update_comment() | Function | WordPress Developer Resources
https://developer.wordpress.org/reference/functions/wp_update_comment/

EOF


荒原之梦网全部内容均为原创,提供了涵盖考研数学基础知识、考研数学真题、考研数学练习题和计算机科学等方面,大量精心研发的学习资源。

豫 ICP 备 17023611 号-1 | 公网安备 - 荒原之梦 豫公网安备 41142502000132 号 | SiteMap
Copyright © 2017-2024 ZhaoKaifeng.com 版权所有 All Rights Reserved.

Copyright © 2024   zhaokaifeng.com   All Rights Reserved.
豫ICP备17023611号-1
 豫公网安备41142502000132号

荒原之梦 自豪地采用WordPress