PicoC is a miniature code interpreter developed for C scripting. According to their documentation, PicoC was first written as the scripting language for a UAV’s on-board flight system. In this zero-day post we are going to speedrun the discovery of a null pointer dereference (CWE-476) denial of service (DoS) vulnerability in the PicoC interpreter. I discovered the vulnerability using AFL++ and notified the development team immediately. The DoS vulnerability affects PicoC up to version 3.2.2.
C Programming and Compilation
Basic Understanding of AFL++
Denial of Service Vulnerabilities
Disclosure and Disclaimer
The null pointer dereference vulnerability was responsibly disclosed to the PicoC development team. This post was intended for developers who are interested in keeping their applications secure and is for EDUCATIONAL PURPOSES ONLY. I do not condone illegal activity and cannot be held responsible for the misuse of this information.
Let’s get started…
Browse to the PicoC Source Code Directory
Point the Compiler Variable in the Makefile Towards ‘afl-clang-fast‘
Run the ‘Make’ Command to Build Our Executable
Creating Input/Output Directories and Input Files
Moving Our Input File to the Input Directory and Starting AFL-Fuzz
Scanning the Output For Crashes
Listing the ‘output/default/crashes’ Directory
After opening the crash files we find an interesting crash input:
Replicating the Crash With GDB and Verifying the Null Pointer Dereference
The best part about security research is the myriad of ways you can find bugs. Sometimes bugs present themselves through diligent research and planning over decades, some bugs demand deep thinking and well-positioned tools, and other times you throw your water bottle at the keyboard and something unexpected happens. Finding the buffer overflow vulnerability in md2roff version 1.7 was somewhat of a combination of these tactics.
Even though buffer overflows are slowly dwindling due to compiler and CPU enhancements, they are still very common in programs written in C and C++. In this post, we are going to step through the process of how I discovered a buffer overflow zero-day in the md2roff tool using AFL++ (American Fuzzy Lop).
Basic C Programming and Compilation
Basic Linux Command Line Tools
Basic Understanding of Buffer Overflows
Basic Understanding of the Stack and Heap
Basic Understanding of Fuzzers
Disclosure and Disclaimer
The buffer overflow vulnerability was responsibly disclosed to the md2roff security team. This post was intended for developers who are interested in keeping their applications secure and is for EDUCATIONAL PURPOSES ONLY. I do not condone illegal activity and cannot be held responsible for the misuse of this information.
Let’s start with a brief introduction on AFL++. At its core, AFL++ is a fuzzer that generates (mostly) random input based on an initial test case given to it by a user. The randomly generated input is subsequently fed into a target software program. As AFL++ learns more about the program, it mutates the input to better identify bugs with the goal of crashing the program by making it exhibit unexpected behavior. I would highly recommend checking out their Github for more details on exactly how this works. The entire process from compiling a target using AFL++ instrumentation to inciting a crash can be seen below:
AFL++ is the successor to AFL, which was originally developed by Michał Zalewski at Google. This quick overview is quite an oversimplification of what AFL++ does. The important bits of information required to get started with AFL++ are compilation using instrumentation, creating inputs, fuzzing the program, and triaging crashes.
If you are running Kali Linux, AFL++ can be installed using the APT package manager.
Once AFL++ is installed, the process of fuzzing a binary becomes unbelievably simple. We only need to complete a few steps to get AFL++ started.
Compile the Program Using ‘afl-clang-fast‘
I downloaded the md2roff tool from GitHub onto my local machine and browsed to the folder containing the source code and Makefile. Like any other C/C++ code, we have to compile the program to produce an executable. AFL++ includes a special clang compiler used for instrumentation. Instrumentation is the process of adding code, variables, and symbols to the program to help AFL++ better identify the program flow and produce a crash. Typically the $(CC) variable is used in Makefiles to specify which compiler to use. Let’s point the ‘CC’ environmental variable to the location of our ‘afl-clang-fast’ compiler. Once we have verified this variable is set, we can run the ‘make’ command to compile the source code.
Creating Input and Output Directories
AFL++ requires two folders before it can get started. The first folder will contain our sample input, and the second will be an output directory where AFL++ will write the fuzzing results.
Our input folder needs to contain a test case that will be utilized and modified by AFL++. If we want to fuzz md2roff’s markdown processing functionality, our input directory must have a sample markdown file with primitive contents. This file serves as a ‘base case’ of what program input should resemble.
Once we have verified our sample input we can start AFL++ by using the ‘afl-fuzz’ command:
afl-fuzz– The AFL++ command used to fuzz a binary
-i input– The input directory containing our base case
-o output– The output directory that AFL++ will write our results to
./md2roff- The name of the program we want to start with any applicable flags.
@@– This syntax tells AFL++ that the input is coming from a file instead of stdin
Once AFL++ has initialized, it will continue fuzzing the program with mutated input until you decide to stop it.
The important sections from the interface are ‘saved crashes’ and ‘exec speed’. ‘Exec Speed’ will show us how fast AFL++ is able to generate new input and fuzz the program. ‘Saved Crashes’ shows us the number of unique crashes the fuzzer was able produce.
It looks like AFL++ discovered a few crashes! Let’s investigate the input that was used to produce the crash. The output/default/crashes directory will contain a file for each unique crash that was generated.
There are plenty of crashes in the output folder to triage. Let’s take a look inside one of them:
It seems like one of the files that produced a crash was a massive buffer of ‘1’s.
Reproducing the Crash
To recreate the crash I created a markdown document with identical input to the crash file seen in the output/default/crashes directory:
I proceeded to execute the program and use the markdown file as input:
It looks like the program segfaults when trying to process our large buffer of ‘1’s. At a minimum, we have a denial of service condition. If the program is executed as a server or started as a service we could provide malicious input and force the program to crash for every user accessing the service. We can attach GDB to our program and run md2roff a second time to see if we have altered the control flow and overwritten the return address.
Success! The stack was successfully smashed by our buffer of ‘1’s. From this point forward we could put together an exploit using a binary exploitation technique such as ret2libc or ROP chaining.
Preventing buffer overflows can be achieved by replacing dangerous C functions, such as strcpy() and gets(), with newer implementations like strncpy() and fgets() that specify how many bytes should be read into the buffer.
For example, the following code is vulnerable because the user input could be significantly larger than the available buffer space:
The following code snippet is an example of how to securely copy data using strncpy(). Instead of reading an undefined amount of bytes into ‘buf’, we can limit the copy operation to the size of our buffer:
In this edition of Zero-Day Research, I happen to come across a DOM-based Cross Site Scripting Vulnerability in ‘Mechanical Keyboard’s (MK’s) Famous Mechanical Keyboard Finder (Version 4.31)’ and helped their team verify the issue upon request. I have to give lots of kudos to the awesome security team at MK. They quickly responded and patched the issue within a day of disclosure. If more vendors were as serious as MK about security, our nation’s overall cyber posture would be in much better shape. MK is an industry-leading mechanical keyboard vendor with unique varieties of mechanical keyboards for sale. You can check them out here.
Disclosure and Disclaimer
The Cross Site Scripting vulnerability was responsibly disclosed and verified (upon request) to the MK security team. This post was intended for web developers who are interested in keeping their applications secure and is for EDUCATIONAL PURPOSES ONLY. I do not condone illegal activity and cannot be held responsible for the misuse of this information.
Cross Site Scripting
DOM Based XSS
OWASP refers to DOM Based XSS as “an XSS attack wherein the attack payload is executed as a result of modifying the DOM “environment”. The DOM in this context is the “Document Object Model”, or the tree structure and programming interface that is used to construct HTML web pages:
DOM-based XSS can be more difficult to discover than other forms of XSS because it requires a detailed review of how and where the user input is stored within the DOM. Context is the most important aspect when searching for DOM XSS because the location where user input is stored will almost certainly be different in each scenario and application.
Identifying the Vulnerability
The overall process for identifying DOM XSS bugs is simple:
See if the application stores user input somewhere in the DOM
If the application stores user input without sanitization, you can guarantee some extent of XSS is possible. Even with a Web Application Firewall (WAF) in play, there is an infinite amount of XSS filter bypasses that can be applied to the payload. Only upon request with full permission from the vendor should you every POC (or verify) the vulnerability on a live application. Given that we have permission to verify, we can then start crafting an attack based on where the input is stored in the DOM.
Let’s start with a basic request like so:
We can then search for our unique ‘xss’ term in the DOM after the request has been made:
In Firefox (or any browser), right-click on the results page and select ‘View Page Source’:
On the HTML source page, select Control/Command+f the find a term
After verifying the location and presence of our search term in the DOM we can add a few special characters to the end of the term like so:
Repeating the previous few steps we can verify if our new search term is stored in the DOM without being converted to an HTML entity. A basic list of basic HTML entities is shown below:
In this particular situation, the special characters were not converted to HTML entities. That being said, we can close off the encompassing attribute or tag as a part of our search term and effectively add our code to the DOM.
In this context we want to craft a payload that closes off the preceding h3 tag, continues to execute some code, and adds a trailing h3 tag to achieve a correct number of matching tags:
This XSS bug not only modifies the DOM but is reflected in the URL. This means we could carry out the XSS attack by providing a simple link in a phishing campaign. Collecting user cookies at this point is trivial:
DOM XSS can be hard for automated scanners to find at times because of its dynamic nature. This type of bug is quite common across the Internet but can be prevented by treating all user input as malicious and sanitizing the data in question.
PHP (the language used by this site) offers useful functions to achieve sanitization, such as htmlspecialchars() and htmlentities(). These functions will automatically convert special characters to HTML entities. Most languages offer these types of libraries and functions to make sanitizing user input quite easy. One mistake developers make is attempting to implement filtering and sanitization using client-side controls. Each user has complete control over the client, rendering client-side sanitization efforts useless.
We made modifications to the DEFCON27 Badge and turned it into a ‘Jackp0t’ badge that will complete other attendee’s badge challenge/trigger rick roll when held within a few inches of each other.
Click the image below to watch the video.
Geancarlo Palavicini Jr
This year’s DEFCON Badge challenge involved social interactions with an RF Badge. A regular attendee is challenged to find and touch badges with 10 different badge types (including Sponsors, Vendors, Goons, and even Press). This becomes super challenging when you have to find one of the 20 individuals out of a 30,000 person conference with a Black “UBER” badge (an exciting but non-trivial task). It was much easier for us to figure out how to flash the DEFCON27 badge to do three things:
Automatically complete the “touch 10 different badge types” challenge
Easily help our fellow attendees by unlocking their badges with one that can act as a chameleon, emulating all other badge types.
That’s what the Jackp0t badge does. It automatically puts you in a “COMPLETE” (or win) state on boot and emulates all the different badge types to complete other attendee’s badges in a matter of seconds.
Plug in the Black Magic Probe into your computer via USB.
Update the firmware on the Black Magic Probe.We initially ran into a lot of issues with the default firmware on the Black Magic Probe. If you update the firmware using the master branch of the wiki, flashing the device was becomes far more consistent. Check out Ross’ instructions on how to upgrade the firmware on the Black Magic Probe:To update your black magic probe, clone the firmware repo from Github build it with make and then perform a DFU update on your probe with the following command:
If your scan doesn’t return KL27x64 M0+, and instead returns ‘Generic Cortex-M’, close GDB and retry. This seems to be a race condition of some sort. — Ross Schlaiker
Attach to the KL27 Microcontroller.
$ (gdb) attach 1
Allow GDB to allow access to memory outside of the device’s known memory map. This is useful to allow access to memory mapped IO from GDB.
$ (gdb) set mem inaccessible-by-default off
Set the binary file. Make sure the binary is in the current directory.
$ (gdb) file jackp0t.bin
Load the binary onto the board.
$ (gdb) load
Figuring out how to edit the source code and successfully flash these badges opens the door to tons of different future hacks. Feel free to use these instructions as a jumping point to create complex hacks like turning the badge into a custom clock!
As technology continues to advance and more devices become networked together, new vulnerabilities will inevitably rise to the surface that security teams will have to deal with. The critical infrastructure sector is no exception to this phenomenon, where common web technologies are being found more frequently in Programmable Logic Controllers (PLCs), a keystone piece of any industrial network. During our SCADA (Supervisory Control and Data Acquisition)/ICS (Industrial Control System) research over the years, we have seen this trend firsthand, which lead us to examine whether the introduction of web technologies would also introduce many of the vulnerabilities that have plagued websites for decades. This post will cover an Open Redirect Zero Day vulnerability we discovered in Rockwell Automation controllers and provide a POC python exploit to help demonstrate our findings.
This post is for education purposes ONLY. Exploiting a live PLC is illegal. We do not condone illegal activity and cannot be held responsible for any misuse of the given information.
The following Rockwell Automation products are affected:
MicroLogix 1400 Controllers
Series A, All Versions
Series B, v15.002 and earlier
MicroLogix 1100 Controllers v14.00 and earlier
CompactLogix 5370 L1 controllers v30.014 and earlier
CompactLogix 5370 L2 controllers v30.014 and earlier
An Open Redirect vulnerability occurs when a web application accepts user-supplied input in the URL that contains a link to an external website, and consequently uses that link to redirect the user’s browser, providing a mechanism for attackers to install malicious software on the user’s machine. The Open Redirect vulnerability we discovered in various Rockwell Controllers is no exception to this rule. Each controller runs a web server that displays diagnostics about that specific PLC. There also exists a URL parameter that enables the PLC to redirect the user’s browser like so:
The redirect parameter intends to send users to another page located on the PLCs website. Under normal circumstances, the PLC would filter out redirects to an external website, so if you tried the following:
From the browser’s perspective, the second ‘/’ character will be ignored, making it a valid URL yet bypassing the PLCs filter. The browser will then be redirected to the website provided after the second ‘/’. This type of client-side attack can aid in phishing campaigns to setup browser exploits or install malware.
Proof of Concept Exploit
Consider the following scenario:
A user with access to the controller receives an email disguised as the Support Center or Help Desk (Figure Below):
Upon following the link, you can see the user is prompted to save the executable being served on the external site:
This basic example demonstrates how the browser is redirected to an external page, setting up the stage for far more complex browser attacks. This attack could indirectly pose a real threat to the control system if the attacker manages to get direct access to a machine that has access to the controller. The following POC code will generate a redirect link for you to replicate the attack in a controlled environment:
The vulnerabilities were immediately reported to the National Cybersecurity and Communications Integration Center (NCCIC) by security researchers Josiah Bryan and Geancarlo Palavicini. You can find the full advisory here.
Rockwell Automation has released an update for each of the affected devices. Rockwell also recommends users take defensive measures to minimize the risk of exploitation of this vulnerability. Specifically, users should:
Update to the latest available firmware revision that addresses the associated risk.
Use trusted software, software patches, anti-virus/anti-malware programs, and interact only with trusted websites and attachments.
Minimize network exposure for all control system devices and/or systems, and ensure that they are not accessible from the Internet.
Locate control system networks and devices behind firewalls and isolate them from the business network.
When remote access is required, use secure methods such as virtual private networks (VPNs), recognizing that VPNs may have vulnerabilities and should be updated to the most current version available. VPN is only as secure as the connected devices.
Employ training and awareness programs to educate users on the warning signs of a phishing or social engineering attack.