![WordPress 任意文件删除漏洞分析与防御插图 WordPress 任意文件删除漏洞分析与防御插图](https://blog.eswlnk.com/wp-content/uploads/wpcy/69421911873c87668f33d8a0bb577e67.jpg)
前言
这个漏洞在去年就已经批露,但是wordpress官方一直没有修复。攻击者可以通过该漏洞删除wp-config.php
,进而重装wordpress充值admin密码来getshell。唯一的一点限制就是需要媒体文件的修改权限,这里只需要作者权限即可,不需要管理员。看完之后,就想起了不久前的铁三,被wordpress支配的恐惧。。。
漏洞利用
![WordPress 任意文件删除漏洞分析与防御插图1 mark](https://static.esw.eswlnk.com/2023/05/20230530041328599.png-esw)
首先上传一个图片文件,然后编辑这个图片。
![WordPress 任意文件删除漏洞分析与防御插图2 mark](https://static.esw.eswlnk.com/2023/05/20230530041327941.png-esw)
从源码中找到_wpnonce的值,然后使用curl或burp构造http请求。
![WordPress 任意文件删除漏洞分析与防御插图3 mark](https://static.esw.eswlnk.com/2023/05/20230530041329132.png-esw)
thumb参数为想删除的文件,接下来在编辑页面,点击永久删除。
![WordPress 任意文件删除漏洞分析与防御插图4 mark](https://static.esw.eswlnk.com/2023/05/20230530041329738.png-esw)
若成功删除,页面会直接跳转到安装界面。
漏洞分析
既然是任意文件删除漏洞,那我们就从删除功能入手,先来看wp-admin/post.php
的246-268行:
case 'delete':
check_admin_referer('delete-post_' . $post_id);
if ( ! $post )
wp_die( __( 'This item has already been deleted.' ) );
if ( ! $post_type_object )
wp_die( __( 'Invalid post type.' ) );
if ( ! current_user_can( 'delete_post', $post_id ) )
wp_die( __( 'Sorry, you are not allowed to delete this item.' ) );
if ( $post->post_type == 'attachment' ) { //删除附件
$force = ( ! MEDIA_TRASH );
if ( ! wp_delete_attachment( $post_id, $force ) )
wp_die( __( 'Error in deleting.' ) );
} else {
if ( ! wp_delete_post( $post_id, true ) )
wp_die( __( 'Error in deleting.' ) );
}
wp_redirect( add_query_arg('deleted', 1, $sendback) );
exit();
由于我们删除的是图片附件,所以程序会进入wp_delete_attachment
函数,跟进:
wp-include/post.php
,函数太长,只截取关键部分,5061-5088行。
/*
前面的代码基本都是准备工作,从数据库将图片的各种信息取出来,删除与图片相关的评论、缓存等。然后到达关键部分
*/
if ( ! empty($meta['thumb']) ) {
// Don't delete the thumb if another attachment uses it.
if (! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id)) ) {
$thumbfile = str_replace(basename($file), $meta['thumb'], $file);
/** This filter is documented in wp-includes/functions.php */
$thumbfile = apply_filters( 'wp_delete_file', $thumbfile );
@ unlink( path_join($uploadpath['basedir'], $thumbfile) );
}
}
// Remove intermediate and backup images if there are any.
if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
foreach ( $meta['sizes'] as $size => $sizeinfo ) {
$intermediate_file = str_replace( basename( $file ), $sizeinfo['file'], $file );
/** This filter is documented in wp-includes/functions.php */
$intermediate_file = apply_filters( 'wp_delete_file', $intermediate_file );
@ unlink( path_join( $uploadpath['basedir'], $intermediate_file ) );
}
}
if ( is_array($backup_sizes) ) {
foreach ( $backup_sizes as $size ) {
$del_file = path_join( dirname($meta['file']), $size['file'] );
/** This filter is documented in wp-includes/functions.php */
$del_file = apply_filters( 'wp_delete_file', $del_file );
@ unlink( path_join($uploadpath['basedir'], $del_file) );
}
}
if ( is_array($backup_sizes) ) {
foreach ( $backup_sizes as $size ) {
$del_file = path_join( dirname($meta['file']), $size['file'] );
/** This filter is documented in wp-includes/functions.php */
$del_file = apply_filters( 'wp_delete_file', $del_file );
@ unlink( path_join($uploadpath['basedir'], $del_file) );
}
}
wp_delete_file( $file );
整个wp_delete_attachment
函数只有这几处调用了unlink
函数,虽然表面上我们只上传了一张图片,但是wordpress后端为了其他功能将图片处理成了很多张图片。
![WordPress 任意文件删除漏洞分析与防御插图5 mark](https://static.esw.eswlnk.com/2023/05/20230530041328541.png-esw)
这几处中只有第一个,即删除thumbfile
时,文件名是可能可控的。那么可控点在哪呢?还记得漏洞利用的第一步吗?现在我们就回到wp-admin/post.php
看一下具体代码。
//178-189行
case 'editattachment':
check_admin_referer('update-post_' . $post_id);
// Don't let these be changed
unset($_POST['guid']);
$_POST['post_type'] = 'attachment';
// Update the thumbnail filename
$newmeta = wp_get_attachment_metadata( $post_id, true ); //获取附件的属性
$newmeta['thumb'] = $_POST['thumb'];
wp_update_attachment_metadata( $post_id, $newmeta ); //更新数据库中的信息
可以看到这里$_POST['thumb']
没有经过任何过滤直接赋值,然后进入了数据库中。
![WordPress 任意文件删除漏洞分析与防御插图6 mark](https://static.esw.eswlnk.com/2023/05/20230530041328186.png-esw)
漏洞防御
- 过滤
. \
等关键字符 $newmeta['thumb'] = $_POST['thumb'];
改为$newmeta['thumb'] = basename($_POST['thumb']);
📮评论