Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SmartDNS Vulnerability Report #1378

Closed
htejeda opened this issue Apr 22, 2023 · 2 comments
Closed

SmartDNS Vulnerability Report #1378

htejeda opened this issue Apr 22, 2023 · 2 comments

Comments

@htejeda
Copy link

htejeda commented Apr 22, 2023

Hello,

I'm writing to report a security vulnerability I've discovered, which affects all releases of SmartDNS. This vulnerability can be exploited by an attacker to cause a denial of service (crash) or remotely execute arbitrary code (RCE) on the server by crafting a special DNS request.

Tested on:
Ubuntu 22.04.2 LTS
gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)
clang version 15.0.7

Technical Details:

A stack buffer overflow vulnerability exists in the _dns_encode_domain function in the dns.c file, which can be triggered by crafting a DNS request that causes the program to write outside the bounds of the packet_buff variable.

You can find the AddressSanitizer (ASAN) output and the GDB backtrace from a production server below for your reference. If it helps confirm if the patches to your code fix the vulnerability, I can also share a trigger file containing a DNS payload that causes a crash with the project maintainer, and to ensure the security of this sensitive information, I will share the trigger file via a secure method, so it is not exposed publicly.

ASAN Output:

=================================================================
==2457317==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffffffdd8e at pc 0x000000305a31 bp 0x7fffffffaf00 sp 0x7fffffffaef8
WRITE of size 1 at 0x7fffffffdd8e thread T0
    #0 0x305a30 in _dns_encode_domain /opt/smartdns/src/dns.c:298:11
    #1 0x30bdea in _dns_add_qr_head /opt/smartdns/src/dns.c:461:12
    #2 0x30bdea in _dns_add_rr_head /opt/smartdns/src/dns.c:509:8
    #3 0x30bdea in dns_add_rr_nested_start /opt/smartdns/src/dns.c:568:8
    #4 0x30bdea in dns_add_HTTPS_start /opt/smartdns/src/dns.c:1074:20
    #5 0x30bdea in _dns_decode_HTTPS /opt/smartdns/src/dns.c:2007:2
    #6 0x30bdea in _dns_decode_an /opt/smartdns/src/dns.c:2192:9
    #7 0x30954d in _dns_decode_body /opt/smartdns/src/dns.c:2329:9
    #8 0x30954d in dns_decode /opt/smartdns/src/dns.c:2469:8
    #9 0x31750d in main /opt/smartdns/src/smartdns.c:49:13
    #10 0x7ffff7c29d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #11 0x7ffff7c29e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #12 0x2558d4 in _start (/opt/smartdns/src/smartdns+0x2558d4)

Address 0x7fffffffdd8e is located in stack of thread T0 at offset 6190 in frame
    #0 0x316cdf in main /opt/smartdns/src/smartdns.c

  This frame has 5 object(s):
    [32, 6176) 'packet_buff' (line 45) <== Memory access at offset 6190 overflows this variable
    [6432, 6436) 'rr_count' (line 53)
    [6448, 6452) 'qtype' (line 54)
    [6464, 6468) 'qclass' (line 55)
    [6480, 6736) 'domain' (line 56)
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /opt/smartdns/src/dns.c:298:11 in _dns_encode_domain
Shadow bytes around the buggy address:
  0x10007fff7b60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007fff7ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007fff7bb0: f2[f2]f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x10007fff7bc0: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
  0x10007fff7bd0: f8 f2 f8 f2 f8 f2 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x10007fff7be0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x10007fff7bf0: f8 f8 f8 f8 f8 f8 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3
  0x10007fff7c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==2457317==ABORTING

GDB Backtrace:

#0  __pthread_kill_implementation (no_tid=0x0, signo=0x6, threadid=0x7ffff7ee1000) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=0x6, threadid=0x7ffff7ee1000) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=0x7ffff7ee1000, signo=signo@entry=0x6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7642476 in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff76287f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff76896f6 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff77db943 "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:155
#6  0x00007ffff773676a in __GI___fortify_fail (msg=msg@entry=0x7ffff77db92b "stack smashing detected") at ./debug/fortify_fail.c:26
#7  0x00007ffff7736736 in __stack_chk_fail () at ./debug/stack_chk_fail.c:24
#8  0x0000555555576b19 in _dns_server_recv (conn=conn@entry=0x55555575a3e0, inpacket=inpacket@entry=0x7fffffff3500 "0000", inpacket_len=<optimized out>, local=local@entry=0x7fffffff2870, local_len=0x10, from=from@entry=0x7fffffff27f0, from_len=0x1c) at dns_server.c:5308
#9  0x0000555555577dfe in _dns_server_process_udp_one (event=<optimized out>, now=<optimized out>, udpconn=<optimized out>) at dns_server.c:5441
#10 _dns_server_process_udp (event=<optimized out>, now=<optimized out>, udpconn=<optimized out>) at dns_server.c:5448
#11 _dns_server_process (now=0x1504f191, event=0x7fffffff28f0, conn=<optimized out>) at dns_server.c:6056
#12 dns_server_run () at dns_server.c:6429
#13 0x000055555555d837 in _smartdns_run () at smartdns.c:536
#14 main (argc=<optimized out>, argv=<optimized out>) at smartdns.c:776

The issue appears to be caused by insufficient bounds checking in the _dns_encode_domain function. I added the following code to the beginning of the function, which appears to prevent the overflow to happen for this specific payload:

if (_dns_left_len(context) <= 0) {
    return -1;
}

However, I'm not certain if this is the best solution to address the vulnerability.

Suggested Fix:

I recommend reviewing the _dns_encode_domain function in the dns.c file to ensure proper bounds checking is in place. You may also want to review the _dns_left_len function, as it is used in the problematic function to calculate the remaining buffer length.

I will be requesting a CVE ID for this vulnerability to ensure proper tracking and handling of the issue.

Please let me know if you require any additional information or assistance in addressing this vulnerability. I'm looking forward to your prompt response and action to ensure the security of SmartDNS users.

Regards,
Huáscar

@pymumu
Copy link
Owner

pymumu commented Apr 22, 2023

Thanks for the report, I modified the code according to your description.
Please check it out and let me know if there is still a problem.

@htejeda
Copy link
Author

htejeda commented Apr 22, 2023

Thanks for the quick response and action in addressing the reported vulnerability! I've tested the patched version with multiple trigger files that used to cause the issue in different ways, and I can confirm that the patch you implemented has successfully resolved the problem.

@htejeda htejeda closed this as completed Apr 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants