Headline
CVE-2019-5148: TALOS-2019-0938 || Cisco Talos Intelligence Group
An exploitable denial-of-service vulnerability exists in ServiceAgent functionality of the Moxa AWK-3131A, firmware version 1.13. A specially crafted packet can cause an integer underflow, triggering a large memcpy that will access unmapped or out-of-bounds memory. An attacker can send this packet while unauthenticated to trigger this vulnerability.
Summary
An exploitable denial-of-service vulnerability exists in ServiceAgent functionality of the Moxa AWK-3131A, firmware version 1.13. A specially crafted packet can cause an integer underflow, triggering a large memcpy that will access unmapped or out-of-bounds memory. An attacker can send this packet while unauthenticated to trigger this vulnerability.
Tested Versions
Moxa AWK-3131A Firmware version 1.13
Product URLs
http://www.moxa.com/product/AWK-3131A.htm
CVSSv3 Score
7.5 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE
CWE-125: Out-of-bounds Read
Details
The Moxa AWK-3131A Industrial IEEE 802.11a/b/g/n wireless AP/bridge/client is a wireless networking appliance intended for use in industrial environments. It is designed to provide wireless communication capabilities to the environments in which it is deployed. Communication with the device is possible using HTTP, Telnet and SSH.
This denial-of-service vulnerability is caused by an out-of-bounds memory access which causes the ServiceAgent binary to crash. This out-of-bounds memory access can be a SIGSEGV (out-of-bounds access) or a SIGBUS (unmapped memory), but the root cause is the same. When a packet is sent to the ServiceAgent, a single ServiceAgent bundle is removed via the parseRecvData function. This function types byte 4-7 (the length of the bundle) and adds 0x24 (length of header). Once that is parsed, if it has not reached the end of the packet, it will attempt to copy the remaining data to a structure to be processed later, the length of the copy is directly taken from the packet, exactly where the next ServiceAgent bundle’s length field would be, add 0x24 for header length, and then copy to a buffer for later processing. The total length of the packet received is not checked when the length of the bundle is calculated which causes an integer underflow making for a very long memcpy, finally resulting in a src out-of-bounds read, causing a SIGSEGV.
00404e94 8fc20030 lw $v0, 0x30($fp) {var_18}
00404e98 2442000c addiu $v0, $v0, 0xc {Session::sockAddr}
00404e9c 8fc30024 lw $v1, 0x24($fp) {var_24}
00404ea0 afa30010 sw $v1, 0x10($sp) {var_38_2}
00404ea4 8fc40048 lw $a0, 0x48($fp) {arg_0}
00404ea8 00402821 move $a1, $v0
00404eac 8f8680f8 lw $a2, -0x7f08($gp) {dispatchServiceHandle} {0x439828}
00404eb0 8fc70020 lw $a3, 0x20($fp) {var_28}
00404eb4 8f8280fc lw $v0, -0x7f04($gp) {parseRecvData} {0x43982c}
00404eb8 0040c821 move $t9, $v0 {parseRecvData}
00404ebc 04114729 bal parseRecvData // Parse out a single package from the received packet
00404ec0 00000000 nop
00404ec4 8fdc0018 lw $gp, 0x18($fp) {var_30} {0x441730}
00404ec8 8fc20038 lw $v0, 0x38($fp) {var_10_4}
00404ecc 1040000f beqz $v0, 0x404f0c
00404ed0 00000000 nop
00404ed4 8fc30028 lw $v1, 0x28($fp) {remainingData_underflowBug}
00404ed8 8fc20024 lw $v0, 0x24($fp) {var_24}
00404edc 00621023 subu $v0, $v1, $v0 // Underflow occurs here due to lack of checks
00404ee0 afc20028 sw $v0, 0x28($fp) {remainingData_underflowBug}
00404ee4 00000000 nop
...
00404f0c 00000000 nop
00404f10 8fc40030 lw $a0, 0x30($fp) {var_18}
00404f14 8fc50020 lw $a1, 0x20($fp) {var_28}
00404f18 8fc60028 lw $a2, 0x28($fp) {remainingData_underflowBug} // This is the bug
00404f1c 0c1012d4 jal copyRemainingData // This is essentially a memcpy where $a2 is the length of the copy
00404f20 00000000 nop
00404f24 8fdc0018 lw $gp, 0x18($fp) {var_30} {0x441730}
00404f28 0810145a j 0x405168
00404f2c 00000000 nop
Crash Information
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────── registers ────
$zero: 0x0
$at : 0x1
$v0 : 0x2cc00008 → 0x00000000
$v1 : 0x2cc00008 → 0x00000000
$a0 : 0x2d281248 → 0x00000000
$a1 : 0x2c2fffca → 0x00000000
$a2 : 0xe7e8ff
$a3 : 0x2da7e8c8 → 0x00000000
$t0 : 0x0
$t1 : 0x0
$t2 : 0x0
$t3 : 0x0
$t4 : 0x0
$t5 : 0x0
$t6 : 0x0
$t7 : 0x0
$s0 : 0x0
$s1 : 0x2caff4b0 → 0x00000001
$s2 : 0x0
$s3 : 0x2acf97e4 → 0x00000000
$s4 : 0xffffffff
$s5 : 0x1000
$s6 : 0x2ba00608 → 0x00000000
$s7 : 0xf
$t8 : 0x3f
$t9 : 0x2ae82ee0 → <memcpy+0> slti t2, a2, 8
$k0 : 0x802
$k1 : 0x0
$s8 : 0x2cafd490 → 0x2bc7ed8a → 0x00000000
$pc : 0x2ae83160 → <memcpy+640> lwr t5, 55(a1)
$sp : 0x2cafd490 → 0x2bc7ed8a → 0x00000000
$hi : 0x6
$lo : 0x1c
$fir : 0x0
$ra : 0x00404c78 → lw gp, 16(s8)
$gp : 0x00441730 → 0x00000000
───────────────────────────────────────────── stack ────
0x2cafd490│+0x0000: 0x2bc7ed8a → 0x00000000 ← $s8, $sp
0x2cafd494│+0x0004: 0x00000000
0x2cafd498│+0x0008: 0x00000000
0x2cafd49c│+0x000c: 0x00400000 → 0x7f454c46
0x2cafd4a0│+0x0010: 0x00441730 → 0x00000000
0x2cafd4a4│+0x0014: 0x00000000
0x2cafd4a8│+0x0018: 0x2cafd4b0 → 0x2ba00468 → 0x00000005
0x2cafd4ac│+0x001c: 0x00404f24 → lw gp, 24(s8)
────────────────────────────────── code:mips:MIPS32 ────
0x2ae83154 <memcpy+628> lwl t4, 48(a1)
0x2ae83158 <memcpy+632> lwr t4, 51(a1)
0x2ae8315c <memcpy+636> lwl t5, 52(a1)
→ 0x2ae83160 <memcpy+640> lwr t5, 55(a1)
0x2ae83164 <memcpy+644> lwl t6, 56(a1)
0x2ae83168 <memcpy+648> lwr t6, 59(a1)
0x2ae8316c <memcpy+652> lwl t7, 60(a1)
0x2ae83170 <memcpy+656> lwr t7, 63(a1)
0x2ae83174 <memcpy+660> pref 0x4, 160(a1)
─────────────────────────────────────────── threads ────
[#0] Id 1, Name: "", stopped, reason: SIGSEGV
[#1] Id 2, Name: "", stopped, reason: SIGSEGV
[#2] Id 4, Name: "", stopped, reason: SIGSEGV
───────────────────────────────────────────── trace ────
[#0] 0x2ae83160 → memcpy()
[#1] 0x404c78 → lw gp, 16(s8)
────────────────────────────────────────────────────────
Timeline
2019-10-23 - Vendor Disclosure
2020-02-24 - Public Release
Discovered by Carl Hurd of Cisco Talos.