mz-automation / lib60870

Official repository for lib60870 an implementation of the IEC 60870-5-101/104 protocol
https://www.mz-automation.de/communication-protocols/iec-60870-5-101-104-c-source-code-library/
GNU General Public License v3.0
430 stars 223 forks source link

NULL Pointer Dereference in CS104_IPAddress_setFromString #100

Open AiDaiP opened 2 years ago

AiDaiP commented 2 years ago

NULL Pointer Dereference in CS104_IPAddress_setFromString

Description

A NULL Pointer Dereference was discovered in CS104_IPAddress_setFromString at src/iec60870/cs104/cs104_slave.c:785. The vulnerability causes a segmentation fault and application crash.

If the ipAddrStr is NULL, strchr() will crash. Should there be a check?

version

0d5e76e

System information Ubuntu 20.04 focal, AMD EPYC 7742 64-Core @ 16x 2.25GHz

gdb

LD_PRELOAD="/root/tools/preeny-master/build/lib/libdesock.so" ./cs104_redundancy_server
New connection request from (null)
[1]    128322 segmentation fault  LD_PRELOAD="/root/tools/preeny-master/build/lib/libdesock.so"
pwndbg>
0x0000555555568557      785         if (strchr(ipAddrStr, '.') != NULL) {
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
 RAX  0x0
 RBX  0x0
 RCX  0x7ffff7e9739b (getpeername+11) ◂— cmp    rax, -0xfff
 RDX  0x0
*RDI  0x0
 RSI  0x2e
 R8   0x0
 R9   0x23
 R10  0x55555557110e ◂— 0x63656e6e6f43000a /* '\n' */
 R11  0x246
 R12  0x7fffffffde9e ◂— 0x5555555a60600000
 R13  0x7fffffffde9f ◂— 0x5555555a606000
 R14  0x7fffffffdea0 —▸ 0x5555555a6060 ◂— 0x0
 R15  0x7ffff7d6afc0 ◂— 0x0
 RBP  0x7ffff7d6ade0 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
 RSP  0x7ffff7d6adc0 ◂— 0x0
*RIP  0x555555568557 (CS104_IPAddress_setFromString+32) ◂— call   0x5555555574e0
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
   0x555555568543 <CS104_IPAddress_setFromString+12>    mov    qword ptr [rbp - 0x18], rdi
   0x555555568547 <CS104_IPAddress_setFromString+16>    mov    qword ptr [rbp - 0x20], rsi
   0x55555556854b <CS104_IPAddress_setFromString+20>    mov    rax, qword ptr [rbp - 0x20]
   0x55555556854f <CS104_IPAddress_setFromString+24>    mov    esi, 0x2e
   0x555555568554 <CS104_IPAddress_setFromString+29>    mov    rdi, rax
 ► 0x555555568557 <CS104_IPAddress_setFromString+32>    call   strchr@plt                <strchr@plt>
        s: 0x0
        c: 0x2e

   0x55555556855c <CS104_IPAddress_setFromString+37>    test   rax, rax
   0x55555556855f <CS104_IPAddress_setFromString+40>    je     CS104_IPAddress_setFromString+165                <CS104_IPAddress_setFromString+165>

   0x555555568561 <CS104_IPAddress_setFromString+42>    mov    rax, qword ptr [rbp - 0x18]
   0x555555568565 <CS104_IPAddress_setFromString+46>    mov    dword ptr [rax + 0x10], 0
   0x55555556856c <CS104_IPAddress_setFromString+53>    mov    dword ptr [rbp - 0xc], 0
──────────────────────────────────────────[ SOURCE (CODE) ]───────────────────────────────────────────
In file: /root/disk2/fuzzing/lib60870/test/lib60870/lib60870-C/src/iec60870/cs104/cs104_slave.c
   780 };
   781
   782 static void
   783 CS104_IPAddress_setFromString(CS104_IPAddress self, const char* ipAddrStr)
   784 {
 ► 785     if (strchr(ipAddrStr, '.') != NULL) {
   786         /* parse IPv4 string */
   787         self->type = IP_ADDRESS_TYPE_IPV4;
   788
   789         int i;
   790
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7ffff7d6adc0 ◂— 0x0
01:0008│     0x7ffff7d6adc8 —▸ 0x7ffff7d6ae20 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
02:0010│     0x7ffff7d6add0 —▸ 0x7ffff0000ef0 ◂— 0x4
03:0018│     0x7ffff7d6add8 —▸ 0x55555557d2d0 —▸ 0x5555555579ed (interrogationHandler) ◂— endbr64
04:0020│ rbp 0x7ffff7d6ade0 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
05:0028│     0x7ffff7d6ade8 —▸ 0x55555556c0c1 (getMatchingRedundancyGroup+54) ◂— mov    qword ptr [rbp - 0x40], 0
06:0030│     0x7ffff7d6adf0 ◂— 0x0
07:0038│     0x7ffff7d6adf8 —▸ 0x55555557d2d0 —▸ 0x5555555579ed (interrogationHandler) ◂— endbr64
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
 ► f 0   0x555555568557 CS104_IPAddress_setFromString+32
   f 1   0x55555556c0c1 getMatchingRedundancyGroup+54
   f 2   0x55555556c64f serverThread+523
   f 3   0x7ffff7f6f609 start_thread+217
──────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> c
Continuing.

Thread 2 "cs104_redundanc" received signal SIGSEGV, Segmentation fault.
__strchr_avx2 () at ../sysdeps/x86_64/multiarch/strchr-avx2.S:57
57      ../sysdeps/x86_64/multiarch/strchr-avx2.S: No such file or directory.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────
 RAX  0x0
 RBX  0x0
*RCX  0x0
 RDX  0x0
 RDI  0x0
 RSI  0x2e
 R8   0x0
 R9   0x23
 R10  0x55555557110e ◂— 0x63656e6e6f43000a /* '\n' */
 R11  0x246
 R12  0x7fffffffde9e ◂— 0x5555555a60600000
 R13  0x7fffffffde9f ◂— 0x5555555a606000
 R14  0x7fffffffdea0 —▸ 0x5555555a6060 ◂— 0x0
 R15  0x7ffff7d6afc0 ◂— 0x0
 RBP  0x7ffff7d6ade0 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
*RSP  0x7ffff7d6adb8 —▸ 0x55555556855c (CS104_IPAddress_setFromString+37) ◂— test   rax, rax
*RIP  0x7ffff7eff08c (__strchr_avx2+28) ◂— vmovdqu ymm8, ymmword ptr [rdi]
──────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────
 ► 0x7ffff7eff08c <__strchr_avx2+28>     vmovdqu ymm8, ymmword ptr [rdi]
   0x7ffff7eff090 <__strchr_avx2+32>     vpcmpeqb ymm1, ymm0, ymm8
   0x7ffff7eff095 <__strchr_avx2+37>     vpcmpeqb ymm2, ymm9, ymm8
   0x7ffff7eff09a <__strchr_avx2+42>     vpor   ymm1, ymm2, ymm1
   0x7ffff7eff09e <__strchr_avx2+46>     vpmovmskb eax, ymm1
   0x7ffff7eff0a2 <__strchr_avx2+50>     test   eax, eax
   0x7ffff7eff0a4 <__strchr_avx2+52>     jne    __strchr_avx2+400                <__strchr_avx2+400>
    ↓
   0x7ffff7eff200 <__strchr_avx2+400>    tzcnt  eax, eax
   0x7ffff7eff204 <__strchr_avx2+404>    xor    edx, edx
   0x7ffff7eff206 <__strchr_avx2+406>    lea    rax, [rdi + rax]
   0x7ffff7eff20a <__strchr_avx2+410>    cmp    sil, byte ptr [rax]
──────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────
00:0000│ rsp 0x7ffff7d6adb8 —▸ 0x55555556855c (CS104_IPAddress_setFromString+37) ◂— test   rax, rax
01:0008│     0x7ffff7d6adc0 ◂— 0x0
02:0010│     0x7ffff7d6adc8 —▸ 0x7ffff7d6ae20 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
03:0018│     0x7ffff7d6add0 —▸ 0x7ffff0000ef0 ◂— 0x4
04:0020│     0x7ffff7d6add8 —▸ 0x55555557d2d0 —▸ 0x5555555579ed (interrogationHandler) ◂— endbr64
05:0028│ rbp 0x7ffff7d6ade0 —▸ 0x7ffff7d6ae40 —▸ 0x7ffff7d6aef0 ◂— 0x0
06:0030│     0x7ffff7d6ade8 —▸ 0x55555556c0c1 (getMatchingRedundancyGroup+54) ◂— mov    qword ptr [rbp - 0x40], 0
07:0038│     0x7ffff7d6adf0 ◂— 0x0
────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────
 ► f 0   0x7ffff7eff08c __strchr_avx2+28
   f 1   0x55555556855c CS104_IPAddress_setFromString+37
   f 2   0x55555556c0c1 getMatchingRedundancyGroup+54
   f 3   0x55555556c64f serverThread+523
   f 4   0x7ffff7f6f609 start_thread+217
──────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg>
mzillgith commented 2 years ago

Yes, I will add a check. But the question is why is ipAddrStr == NULL? Seems that can only happen when the getpeername socket function doesn't return a valid address.