4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2022-25640.ipynb IPYNB
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CVE-2022-25640\n",
    "\n",
    "In WolfSSL v5.2.0 the following vulnerability was fixed:\n",
    "\n",
    "> [High] A TLS v1.3 server who requires mutual authentication can be bypassed. If a malicious client **does not send the certificate_verify message** a client can connect **without presenting a certificate** even if the server requires one. Thank you to Aina Toky Rasoamanana and Olivier Levillain of Télécom SudParis. CVE-2022-25640\n",
    "\n",
    "\n",
    "This vulnerability affects mutual authentication, where a server expects the client to present a certificate signed by a CA the server trusts. From the description it seems like a pretty easy attack, because you just have to omit sending the certificate_verify  and the certificate message from the TLS 1.3 handshake.\n",
    "\n",
    "## WolfSSL Library\n",
    "WolfSSL is available on [GitHub](https://github.com/wolfSSL/wolfssl). The following code compiles two versions (v5.1.1, and v5.2) statically, so that we can create a statically compiled TLS server for each library version later:\n",
    "\n",
    "* 5.1.1 < Vulnerable\n",
    "* 5.2 < Not Vulnerable\n",
    "\n",
    "The next few commands will compile wolfSSL in version 5.1.1 and 5.2 statically and copy the compiled libraries to ../libs/511 and ../libs/52 respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!git clone https://github.com/wolfSSL/wolfssl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "working_directory = os.path.abspath('') # store CWD for later\n",
    "os.chdir('wolfssl')\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!git checkout tags/v5.1.1-stable\n",
    "!./autogen.sh\n",
    "!./configure --enable-static\n",
    "!make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "!mkdir -p ../libs/511 ../libs/52\n",
    "!cp src/.libs/* ../libs/511\n",
    "!git checkout --"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we compiled 511 statically. Next step is to do the same for 5.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!git checkout tags/v5.2.0-stable\n",
    "!./autogen.sh\n",
    "!./configure --enable-static\n",
    "!make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "!cp src/.libs/* ../libs/52\n",
    "!git checkout --"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## TLS Server\n",
    "WolfSSL provides a TLS 1.3 Server which requires mutual authentication: [server-tls13.c](https://github.com/wolfSSL/wolfssl-examples/blob/05dc1cf88bb0262d0e78754c32f8034f97d5433a/tls/server-tls13.c). We will use this server and create static binaries, one for each version of the wolfSSL libraries."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.chdir(working_directory)\n",
    "os.getcwd()\n",
    "!git clone https://github.com/wolfSSL/wolfssl-examples\n",
    "os.chdir('wolfssl-examples')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `certs` directory contains certificates and keys, which the example servers use. They have the path statically compiled in (eg. `../certs/cert.pem`). \n",
    "`../servers/` will contain our compiled servers, `../certs/` the example certificates.\n",
    "\n",
    "* `../servers/server-51`: A statically compiled TLS server using **wolfSSL v5.1.1**, requiring mututal authentication.\n",
    "* `../servers/server-52`: A statically compiled TLS server using **wolfSSL v5.2**, requiring mututal authentication.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "!mkdir ../servers\n",
    "!gcc -static -L../libs/511 tls/server-tls13.c  -lwolfssl -lpthread -lm -o ../servers/server-51\n",
    "!gcc -static -L../libs/52 tls/server-tls13.c  -lwolfssl -lpthread -lm -o ../servers/server-52\n",
    "!cp -r certs/ ../"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can now run the servers from a terminal. Change into the directory `servers` and run \n",
    "`./server-51`\n",
    "or \n",
    "`./server-52`\n",
    "Both servers will listen on port 1111. Try to connect to the servers via openssl.\n",
    "\n",
    "`openssl s_client -connect 127.0.0.1:11111 -tls1_3 -cert certs/client-cert.pem -key certs/client-key.pem`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scapy\n",
    "Next we need to setup Scapy. I adjusted Scapy to have an NSS key dump option. You can check out my scapy fork from my Github."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.chdir(working_directory)\n",
    "!git clone https://github.com/dim0x69/scapy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Prepare the Scapy environment:\n",
    "```\n",
    "python -m venv .venv\n",
    "source .venv/bin/activate\n",
    "pip install -r requirements.txt\n",
    "cd scapy\n",
    "pip install -e .\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Scapy includes a TLS Automation under `scapy.layers.tls.automaton_cli`. You will find a slightly modified TLS automaton, which does **not** \n",
    "* add a ClientCertificate mesage\n",
    "* add a Client CertificateVerify message\n",
    "\n",
    "Along with this repository you will find a file [client13_keylog.py](client13_keylog.py), which uses the modified TLS Automaton ([automaton_cli.py](automaton_cli.py)). This TLS client will connect to previously compiled wolfSSL servers.\n",
    "\n",
    "You will need to run the following commands as root, because the Scapy TLS Automaton uses RAW sockets, which require root."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exploit\n",
    "\n",
    "Start the server. This server has mututal authentication enabled.\n",
    "```\n",
    "./server-51\n",
    "```\n",
    "\n",
    "Start the Client\n",
    "```\n",
    "su\n",
    "python client13_.py\n",
    "```\n",
    "\n",
    "This will connect the mutual authentication client."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analysis\n",
    "\n",
    "### Certificate Request\n",
    "The server requests a Certificate via [Certificate Request](https://datatracker.ietf.org/doc/html/rfc8446#section-4.3.2) message from the client. This request is ignored by the client. \n",
    "\n",
    "Note: The *Certificate* message in the trace is the Certificate, which is send from the Server to the Client. From the RfC:\n",
    "\n",
    "> A server which is authenticating with a certificate MAY optionally request a certificate from the client.  This message, if sent, MUST follow EncryptedExtensions.\n",
    "\n",
    "![](img/cert_request.png)\n",
    "\n",
    "[Screenshot](img/cert_request.png)\n",
    "\n",
    "### Certificate Verify\n",
    "\n",
    "The [Certificate Verify](https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.3) message is required to be send by the client, if there was a *Certificate* message. From the RfC:\n",
    "\n",
    "> This message is used to provide explicit proof that an endpoint possesses the private key corresponding to its certificate. The CertificateVerify message also provides integrity for the handshake up to this point. Servers MUST send this message when authenticating via a certificate. **Clients MUST send this message whenever\n",
    " authenticating via a certificate (i.e., when the Certificate message is non-empty).**  When sent, this message MUST appear immediately after the Certificate message and immediately prior to the Finished message."
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
  },
  "kernelspec": {
   "display_name": "Python 3.10.2 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}