xebd / accel-ppp

High performance PPTP/L2TP/PPPoE/IPoE server for Linux
GNU General Public License v2.0
296 stars 108 forks source link

The stack-buffer-underflow bug can be triggered even by remote client #156

Open GoldBinocle opened 2 years ago

GoldBinocle commented 2 years ago

Using version accel-ppp version 1.12.0-149-gff91c73. The issue #154 can be triggered even by remote client.

Steps to reproduce

  1. Build access-ppp:
mkdir build && cd build
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="-fsanitize=address -g" -DCMAKE_CXX_FLAGS="-fsanitize=address -g" -DBUILD_DRIVER=false -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug -DLOG_PGSQL=TRUE -DSHAPER=TRUE -DRADIUS=TRUE -DNETSNMP=TRUE ..
CC=clang CXX=clang++ CFLAGS="-fsanitize=address -g" CXXFLAGS="-fsanitize=address -g" make -j
  1. Run access-pppd, use pptp server:
accel-pppd -c /etc/accel-ppp.conf

The running configuration /etc/accel-ppp.conf is:

[modules]
 log_file
 #log_syslog
 #log_tcp
 #log_pgsql

 pptp
 l2tp
 #sstp
 #pppoe
 #ipoe

 auth_mschap_v2
 auth_mschap_v1
 auth_chap_md5
 auth_pap

 #radius
 chap-secrets

 ippool

 pppd_compat

 #shaper
 #net-snmp
 #logwtmp
 #connlimit

 #ipv6_nd
 #ipv6_dhcp
 #ipv6pool

 [core]
 log-error=/var/log/accel-ppp/core.log
 thread-count=4

 [common]
 #single-session=replace
 #single-session-ignore-case=0
 #sid-case=upper
 #sid-source=seq
 #max-sessions=1000
 #max-starting=0
 #check-ip=0

 [ppp]
 verbose=1
 min-mtu=1280
 mtu=1400
 mru=1400
 #accomp=deny
 #pcomp=deny
 #ccp=0
 #mppe=require
 ipv4=require
 ipv6=deny
 ipv6-intf-id=0:0:0:1
 ipv6-peer-intf-id=0:0:0:2
 ipv6-accept-peer-intf-id=1
 lcp-echo-interval=20
 #lcp-echo-failure=3
 lcp-echo-timeout=120
 unit-cache=1
 #unit-preallocate=1

 [auth]
 #any-login=0
 #noauth=0

 [pptp]
 verbose=1
 #echo-interval=30
 ip-pool=pool1
 #ipv6-pool=pptp
 #ipv6-pool-delegate=pptp
 ifname=pptp%d
 #port=9300
 #mppe=prefer

 [pppoe]
 verbose=1
 #ac-name=xxx
 #service-name=yyy
 #pado-delay=0
 #pado-delay=0,100:100,200:200,-1:500
 called-sid=mac
 #tr101=1
 #padi-limit=0
 #ip-pool=pppoe
 #ipv6-pool=pppoe
 #ipv6-pool-delegate=pppoe
 #ifname=pppoe%d
 #sid-uppercase=0
 #vlan-mon=eth0,10-200
 #vlan-timeout=60
 #vlan-name=%I.%N
 #interface=eth1,padi-limit=1000
 interface=ens18

 [l2tp]
 verbose=1
 #dictionary=/usr/local/share/accel-ppp/l2tp/dictionary
 #hello-interval=60
 #timeout=60
 #rtimeout=1
 #rtimeout-cap=16
 #retransmit=5
 #recv-window=16
 #host-name=accel-ppp
 #dir300_quirk=0
 #secret=
 #dataseq=allow
 #reorder-timeout=0
 #ip-pool=l2tp
 #ipv6-pool=l2tp
 #ipv6-pool-delegate=l2tp
 #ifname=l2tp%d

 [sstp]
 verbose=1
 #cert-hash-proto=sha1,sha256
 #cert-hash-sha1=
 #cert-hash-sha256=
 #accept=ssl,proxy
 #ssl-protocol=tls1,tls1.1,tls1.2,tls1.3
 #ssl-dhparam=/etc/ssl/dhparam.pem
 #ssl-ecdh-curve=prime256v1
 #ssl-ciphers=DEFAULT
 #ssl-prefer-server-ciphers=0
 #ssl-ca-file=/etc/ssl/sstp-ca.crt
 #ssl-pemfile=/etc/ssl/sstp-cert.pem
 #ssl-keyfile=/etc/ssl/sstp-key.pem
 #host-name=domain.tld
 #http-error=allow
 #timeout=60
 #hello-interval=60
 #ip-pool=sstp
 #ipv6-pool=sstp
 #ipv6-pool-delegate=sstp
 #ifname=sstp%d

 [ipoe]
 verbose=1
 username=ifname
 #password=username
 lease-time=600
 #renew-time=300
 #rebind-time=525
 max-lease-time=3600
 #unit-cache=1000
 #l4-redirect-table=4
 #l4-redirect-ipset=l4
 #l4-redirect-on-reject=300
 #l4-redirect-ip-pool=pool1
 shared=0
 ifcfg=1
 mode=L2
 start=dhcpv4
 #start=up
 #ip-unnumbered=1
 #proxy-arp=0
 #nat=0
 #proto=100
 #relay=10.10.10.10
 #vendor=Custom
 #weight=0
 #attr-dhcp-client-ip=DHCP-Client-IP-Address
 #attr-dhcp-router-ip=DHCP-Router-IP-Address
 #attr-dhcp-mask=DHCP-Mask
 #attr-dhcp-lease-time=DHCP-Lease-Time
 #attr-dhcp-renew-time=DHCP-Renewal-Time
 #attr-dhcp-rebind-time=DHCP-Rebinding-Time
 #attr-dhcp-opt82=DHCP-Option82
 #attr-dhcp-opt82-remote-id=DHCP-Agent-Remote-Id
 #attr-dhcp-opt82-circuit-id=DHCP-Agent-Circuit-Id
 #attr-l4-redirect=L4-Redirect
 #attr-l4-redirect-table=4
 #attr-l4-redirect-ipset=l4-redirect
 #lua-file=/etc/accel-ppp.lua
 #offer-delay=0,100:100,200:200,-1:1000
 #vlan-mon=eth0,10-200
 #vlan-timeout=60
 #vlan-name=%I.%N
 #ip-pool=ipoe
 #ipv6-pool=ipoe
 #ipv6-pool-delegate=ipoe
 #idle-timeout=0
 #session-timeout=0
 #soft-terminate=0
 #check-mac-change=1
 #calling-sid=mac
 #local-net=192.168.0.0/16
 interface=eth0

 [dns]
 #dns1=172.16.0.1
 #dns2=172.16.1.1

 [wins]
 #wins1=172.16.0.1
 #wins2=172.16.1.1

 [radius]
 #dictionary=/usr/local/share/accel-ppp/radius/dictionary
 nas-identifier=accel-ppp
 nas-ip-address=127.0.0.1
 gw-ip-address=192.168.100.1
 server=127.0.0.1,testing123,auth-port=1812,acct-port=1813,req-limit=50,fail-timeout=0,max-fail=10,weight=1
 dae-server=127.0.0.1:3799,testing123
 verbose=1
 #timeout=3
 #max-try=3
 #acct-timeout=120
 #acct-delay-time=0
 #acct-on=0
 #acct-interim-interval=0
 #acct-interim-jitter=0
 #default-realm=
 #strip-realm=0
 #attr-tunnel-type=My-Tunnel-Type

 [client-ip-range]
 0.0.0.0/0

 [ip-pool]
 gw-ip-address=192.168.0.1
 #vendor=Cisco
 #attr=Cisco-AVPair
 attr=Framed-Pool
 192.168.0.2-255
 192.168.1.1-255,name=pool1
 192.168.2.1-255,name=pool2
 192.168.3.1-255,name=pool3
 192.168.4.1-255,name=pool4,next=pool1
 192.168.4.0/24

 [log]
 log-file=/var/log/accel-ppp/accel-ppp.log
 log-emerg=/var/log/accel-ppp/emerg.log
 log-fail-file=/var/log/accel-ppp/auth-fail.log
 log-debug=/dev/stdout
 syslog=accel-pppd,daemon
 #log-tcp=127.0.0.1:3000
 copy=1
 color=1
 #per-user-dir=per_user
 #per-session-dir=per_session
 #per-session=1
 level=5

 [log-pgsql]
 conninfo=user=log
 log-table=log

 [pppd-compat]
 verbose=1
 #ip-pre-up=/etc/ppp/ip-pre-up
 ip-up=/etc/ppp/ip-up
 ip-down=/etc/ppp/ip-down
 #ip-change=/etc/ppp/ip-change
 radattr-prefix=/var/run/radattr
 #fork-limit=16

 [chap-secrets]
 gw-ip-address=192.168.100.1
 chap-secrets=/etc/ppp/chap-secrets.ppp
 #encrypted=0
 #username-hash=md5

 [shaper]
 #attr=Filter-Id
 #down-burst-factor=0.1
 #up-burst-factor=1.0
 #latency=50
 #mpu=0
 #mtu=0
 #r2q=10
 #quantum=1500
 #moderate-quantum=1
 #cburst=1534
 #ifb=ifb0
 up-limiter=police
 down-limiter=tbf
 #leaf-qdisc=sfq perturb 10
 #leaf-qdisc=fq_codel [limit PACKETS] [flows NUMBER] [target TIME] [interval TIME] [quantum BYTES] [[no]ecn]
 #rate-multiplier=1
 #fwmark=1
 #rate-limit=2048/1024
 verbose=1

 [cli]
 verbose=1
 telnet=127.0.0.1:2000
 tcp=127.0.0.1:2001
 #password=123
 #sessions-columns=ifname,username,ip,ip6,ip6-dp,type,state,uptime,uptime-raw,calling-sid,called-sid,sid,comp,rx-bytes,tx-bytes,rx-bytes-raw,tx-bytes-raw,rx-pkts,tx-pkts

 [snmp]
 master=0
 agent-name=accel-ppp

 [connlimit]
 limit=10/min
 burst=3
 timeout=60

 [ipv6-pool]
 #gw-ip6-address=fc00:0:1::1
 #vendor=
 #attr-prefix=Delegated-IPv6-Prefix-Pool
 #attr-address=Stateful-IPv6-Address-Pool
 fc00:0:1::/48,64
 fc00:0:2::/48,64,name=pool1
 fc00:0:3::/48,64,name=pool2,next=pool1
 delegate=fc00:1::/36,48
 delegate=fc00:2::/36,48,name=pool3
 delegate=fc00:3::/36,48,name=pool4,next=pool3

 [ipv6-dns]
 #fc00:1::1
 #fc00:1::2
 #fc00:1::3
 #dnssl=suffix1.local.net
 #dnssl=suffix2.local.net.

 [ipv6-dhcp]
 verbose=1
 pref-lifetime=604800
 valid-lifetime=2592000
 route-via-gw=1

use chap-secrets and the /etc/ppp/chap-secrets.ppp is as follows:

# Secrets for authentication using CHAP
# client    server  secret          IP addresses
fouzhe * 123 *
  1. Install pptp client:

    apt-get update && apt-get install -y ppp pptp-linux inetutils-ping net-tools iproute2
  2. Run the client:

    strace -f pptpsetup --create pptpd --server 127.0.0.1 --username fouzhe --password 123 --start

    (Hint: we need to follow the forked subprocesses and control them, therefore we used the strace -f to execute the pptp client instead of simply using pptpsetup --create pptpd --server 127.0.0.1 --username fouzhe --password 123 --start.)

  3. Kill (Ctrl^C) the client after authentication succeeded. Then the accel-pppd will crash due to stack-buffer-underflow.

    
    =================================================================
    ==1340656==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7feb635ecc40 at pc 0x000000499d97 bp 0x7feb635ecbd0 sp 0x7feb635ec398
    READ of size 8512 at 0x7feb635ecc40 thread T4
    [2021-10-06 16:54:44.230] pptp0: 78a9b1ca73485bca: pppd_compat: ip-down finished (0)
    #0 0x499d96 in __asan_memcpy /home/brian/src/llvm_releases/llvm-project/llvm/utils/release/final/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3
    #1 0x7feb6e4bf3be in alloc_context /root/projects/accel-ppp/accel-pppd/triton/triton.c:485:2
    #2 0x7feb6e4bc17d in triton_context_schedule /root/projects/accel-ppp/accel-pppd/triton/triton.c:497:12
    #3 0x7feb65600dab in ev_ses_finished /root/projects/accel-ppp/accel-pppd/extra/pppd_compat.c:380:4
    #4 0x7feb6e4c6f9e in triton_event_fire /root/projects/accel-ppp/accel-pppd/triton/event.c:103:3
    #5 0x4cfb09 in ap_session_finished /root/projects/accel-ppp/accel-pppd/session.c:183:2
    #6 0x4e06d9 in destablish_ppp /root/projects/accel-ppp/accel-pppd/ppp/ppp.c:307:2
    #7 0x4e0b42 in ppp_terminate /root/projects/accel-ppp/accel-pppd/ppp/ppp.c
    #8 0x4d148d in ap_session_terminate /root/projects/accel-ppp/accel-pppd/session.c:297:6
    #9 0x7feb696e1380 in pptp_call_clear_rqst /root/projects/accel-ppp/accel-pppd/ctrl/pptp/pptp.c:401:3
    #10 0x7feb696e1380 in process_packet /root/projects/accel-ppp/accel-pppd/ctrl/pptp/pptp.c:478:11
    #11 0x7feb696e1380 in pptp_read /root/projects/accel-ppp/accel-pppd/ctrl/pptp/pptp.c:527:9
    #12 0x7feb6e4b91c1 in ctx_thread /root/projects/accel-ppp/accel-pppd/triton/triton.c:252:10
    #13 0x7feb6e4b91c1 in triton_thread /root/projects/accel-ppp/accel-pppd/triton/triton.c:192:5
    #14 0x7feb6e476608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477:8
    #15 0x7feb6de4f292 in clone /build/glibc-eX1tMB/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Address 0x7feb635ecc40 is located in stack of thread T4 at offset 0 in frame

0 0x7feb656005df in ev_ses_finished /root/projects/accel-ppp/accel-pppd/extra/pppd_compat.c:340

This frame has 7 object(s): [32, 4128) 'fname.i' (line 497) <== Memory access at offset 0 partially underflows this variable [4256, 4320) 'argv' (line 342) <== Memory access at offset 0 partially underflows this variable [4352, 4480) 'env' (line 343) <== Memory access at offset 0 partially underflows this variable [4512, 5536) 'env_mem' (line 344) <== Memory access at offset 0 partially underflows this variable [5664, 5681) 'ipaddr' (line 345) <== Memory access at offset 0 partially underflows this variable [5728, 5745) 'peer_ipaddr' (line 346) <== Memory access at offset 0 partially underflows this variable [5792, 5920) 'set' (line 385) <== Memory access at offset 0 partially underflows this variable 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) Thread T4 created by T0 here:

0 0x484d4c in pthread_create /home/brian/src/llvm_releases/llvm-project/llvm/utils/release/final/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:205:3

#1 0x7feb6e4b7eee in create_thread /root/projects/accel-ppp/accel-pppd/triton/triton.c:320:9
#2 0x7feb6e4bec17 in triton_run /root/projects/accel-ppp/accel-pppd/triton/triton.c:744:7
#3 0x559603 in main /root/projects/accel-ppp/accel-pppd/main.c:415:2
#4 0x7feb6dd540b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: stack-buffer-underflow /home/brian/src/llvm_releases/llvm-project/llvm/utils/release/final/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy Shadow bytes around the buggy address: 0x0ffdec6b5930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ffdec6b5940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ffdec6b5950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ffdec6b5960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0ffdec6b5970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0ffdec6b5980: 00 00 00 00 00 00 00 00[f1]f1 f1 f1 f8 f8 f8 f8 0x0ffdec6b5990: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x0ffdec6b59a0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x0ffdec6b59b0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x0ffdec6b59c0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 0x0ffdec6b59d0: f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 f8 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 ==1340656==ABORTING



The detailed log of `accel-pppd` is shown in [accel-ppp.log](https://github.com/xebd/accel-ppp/files/7292498/accel-ppp.log).
DmitriyEshenko commented 2 years ago

Hello @GoldBinocle , I'm worried this message "HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork" Did you try to reproduce this behavior without a debugger?

GoldBinocle commented 2 years ago

Hi, @DmitriyEshenko. Actually, any ASAN (Google Address Sanitizer) report associated with buffer-overflow/underflow has this message "HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork", but that's very likely a bug. I can't reproduce the crash without ASAN. Actually, many real buffer-overflow/underflow bugs do not crash the program without ASAN support. ASAN is used to detected this kind of behavior and abort the program so that we can locate the bug and fix it.

GoldBinocle commented 2 years ago

Hello @GoldBinocle , I'm worried this message "HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork" Did you try to reproduce this behavior without a debugger?

For example, this bug has the message but it's a real bug.

nuclearcat commented 2 years ago

I did tested accel-ppp for same conditions (disable clang sanitizer) with valgrind and didnt got any alert.

Also as ASAN says it might be false positive on swapcontext, and we have exactly context switching in call trace: `

2 0x7fcc641a83da in triton_context_schedule /root/accel-ppp/accel-pppd/triton/triton.c:497:12

` I dont say bug exist or not, but on my opinion this is looks more like false positive.