Learn what's new in MISRA C:2012 AMD3 & how to get the MOST EXTENSIVE coverage with C/C++test 2022.2! Watch on Demand >>

Analyzing OpenSSL Punycode Vulnerability (CVE-2022-3602)

By Anthony Mendez

December 8, 2022

4  min read

Punycode attacks are phishing attacks that use domains to imitate popular brands. In this post, we analyze the high-severity Punycode vulnerability, CVE-2022-3602.

On November 1, 2022, the OpenSSL project announced two high-severity vulnerabilities in the OpenSSL. Since both of these vulnerabilities were related to Punycode parsing, they have been colloquially known as the Punycode vulnerabilities. In this post, we’ll analyze CVE-2022-3602.

OpenSSL is a library for creating and maintaining the identity and secure communication between computers by providing a secure sockets layer and related tools. It is widely deployed on both Windows and Linux/Unix systems along with a wide variety of embedded platforms.

These vulnerabilities affected OpenSSL v3.0.0 through v3.0.6.

Punycode Vulnerability Overview

Understanding Punycode is a critical prerequisite to understanding these related OpenSSL vulnerabilities. As defined in RFC 3492, Punycode is a way of using an ASCII character string to encode a Unicode character string. These Punycode strings are used internally when resolving domains containing Unicode characters.

In OpenSSL v3.0.6’s crypto/punycode.c there exists an off by one error on line 184 where if (written_out > max_out) should instead be if (written_out >=max_out). When OpenSSL tries to process a certificate containing a crafted email address with a Punycode domain, the resulting buffer overflow can result in a program crash or remote code execution.

Proof of Concept Overview

To demonstrate the vulnerability in OpenSSL using Insure++, we use the publicly available proof of concept created by Data Dog Security Labs. This proof of concept is limited in that it does not always generate a crash but it always generates a memory corruption issue that Insure++ can detect. If you’re interested in a detailed dive into both the vulnerability and the proof of concept, check out their blog post.

Demo Setup

For our demonstration, we have two virtual machines connected on the same LAN. The “victim” virtual machine will be running Windows 10 and the vulnerable version of OpenSSL instrumented with Insure++. The “attacker” virtual machine will be running Ubuntu and use the Data Dog Security Labs proof of concept. For this demo, the “victim” IP address will be 192.168.1.10 and the “attacker” IP address will be 192.168.1.20.

First, we’ll set up our Windows 10 “victim” virtual machine. In order to build OpenSSL from the source we need to install Visual Studio 2022 and Parasoft Insure++. Additional prerequisites include ‘Strawberry Perl’, NASM and ‘Git for Windows’ should also be installed and included on the Windows PATH.

Next, we’ll clone the OpenSSL git repository from github.com/openssl/openssl.git and check out the vulnerable version tag using the following command.

git checkout -b v3.0.6 tags/openssl-3.0.6

After this, we need to modify the build configurations to create a build profile that will use Insure++ to instrument OpenSSL as it builds. To do this, we’ll inherit from the Visual C Windows 64-bit build profile making a few small modifications for Insure++. Open Configurations/10-main.conf and insert the following after line 1421.

"VC-WIN64A-INSURE" => {
inherit_from => [ "VC-WIN64A" ],
CC => "insure",
LD => "inslink",
},

Now launch an “x64 Native Tools Command Prompt for VS 2022” and navigate to where you cloned the OpenSSL source git repository. Run the following command to configure the source for our Insure++ build profile.

perl Configure VC-WIN64A-INSURE

If the previous command succeeded, we’re ready to build using the next command. This will build OpenSSL using Visual Studio while Insure++ instruments the generated code.

nmake

You’ll be able to see the code being compiled in the Insure++ GUI as seen in the following picture.

Screenshot showing Parasoft Insure++ compiling code.

If the build succeeded we are done configuring our “victim” virtual machine. For the “attacker” virtual machine, simply install Ubuntu and clone the proof of concept git repository from github.com/DataDog/security-labs-pocs.git.

Running Proof of Concept in Demo Environment

On the “attacker” virtual machine, from the root of the Data Dog Security Labs Proof of Concepts repository we cloned, navigate to proof-of-concept-exploits/openssl-punycode-vulnerability/vagrant/WindowsCrash. In this directory, there are crafted certificates and keys that will reproduce the vulnerability when a OpenSSL server is launched with them. It’s not required to have a vulnerable version of OpenSSL to use these files so we’ll launch an OpenSSL server using the version that comes with Ubuntu. The following command will launch an OpenSSL server with the proof of concept keys and certificates.

openssl s_server -accept 3000 -CAfile ca.crt -cert test.crt -key test.key.pem -state

With the OpenSSL server running on our “attacker” virtual machine, we’re ready to use our Insure++ instrumented OpenSSL client on the “victim” virtual machine to reproduce and analyze the vulnerability. On the “victim” virtual machine, from the root of the OpenSSL repository we cloned navigate to =apps= and run the following command.

openssl.exe s_client -connect 10.10.10.7:3000

When the “victim” client connects to the “attacker” server, Insure++ will detect the memory write overflow and display it in the GUI as seen in the following image.

Screenshot showing Parasoft Insure++ detecting the memory write overflow and displaying it in the GUI.

Analyzing the Vulnerability With Insure++

As seen in the previous image, Insure++ detected a variety of memory issues from this run of OpenSSL. Let’s focus in particular on the defect related to this Punycode vulnerability. In the Insure++ GUI, click on the WRITE_OVERFLOW= in=punycode.c on like 187. You should see something similar to the following.

Screenshot of Parasoft Insure++ GUI showing detected Punycode vulnerability.

You can see that Insure++ has properly identified the weakness as CWE-120, which matches the entry for CVE-2022-3602 in the NIST entry. Beneath this, we can see a graph showing that of our original 2048 byte buffer, the call to memmove() writes 12 bytes to the end of the buffer of which 8 bytes are within the buffer and the last 4 bytes overflow. This finding agrees with the results published in the aforementioned Data Dogs Security Labs blog. The exact address ranges involved are shown below this. Finally, you can see a stack trace and code snippet in the window.

Conclusion

I hope I have demonstrated some of Insure++’s unique features and abilities along with our new GUI. These features make Insure++ a great addition to a security researcher’s tools, especially when working with fuzzing, vulnerability research, and memory-based attacks.

Want to see how to automatically detect memory write overflows using Insure++?

By Anthony Mendez

Anthony is a senior software engineer at Parasoft, focusing on runtime error detection, static analysis, reverse engineering, vulnerability analysis, and exploitation.

Get the latest software testing news and resources delivered to your inbox.