KASLR : 커널이 무작위 주소에 매핑되도록 만들어 커널 익스플로잇을 어렵게 하는 보호기법이다.
유저 공간의 ASLR 과 비슷한 개념이며 , 주로 커널이 실행되기 전 단계인 부트로더에서 세팅이 된다, 우회하기 위해 kerenl memroy address leak 과정이 필요하다.
commit_creds(prepare_kernel_cred(0) : 인자로 0 을 줄경우 루트로 자격증명을 준다.
commit_creds() 는 현재 태스크의 credentials를 인잘 받은 credentials 로 갱신 하는 역할이다. 즉 현재 태스크의 권한을 root 로 바꾸는 코드이다.
kaslr = -append "kaslr" 옵션으로 kaslr 보호기법 을 적용
/proc/kallsyms : /proc/kallsyms 파일은 커널의 모든 심볼의 주소를 담고 있는 파일이다.
KADR 보호기법에 의해 root 권한으로 주소을 확인할수 있다.
_text 심볼이 바로 kernel base주소
필요한 함수의 주소에서 _text 심볼주소 를 뺴면 offset 을 구할수있다.
/ $ head -3 proc/kallsyms
0000000000000000 T startup_64
0000000000000000 T _stext
0000000000000000 T _text
/ $ cat proc/kallsyms | grep commit_creds
0000000000000000 T commit_creds
/ $
이런 느낌으로 (?) 하면된다 .그럼 여기서 T_test 주소는 안나왔지만 T_test 주소 가 kernel base 이고 - commit_creds 주소 을 빼면 offset 을 구할수 있다.
information leak 취약점을 이용해 커널코드 주소 를 leak 한다 leak 한 주소와 offset 을 기밥은로 exploit 에 사용할 커널 함수들의 주소를 구한다
smep : 커널 공간에서 유저공간에 대한 실행권한을 제한 하는 보호기법
cr4 레지스터 에 smep 를 on/off 하는 제어 비트가 있음
우회 하기 위해서는 kernel rop 을 하는것이다.
ROP 을 하기 위해서는 gadget 들을 chaining 을 하여 프로그램의 흐름을 공격자가 원하는대로 바꾸는 방법이다.
현재 태스크의 권한을 root 로 바꾸는 코드 이다.
kernel panic : userapce code 을 커널 로 실행 시키는 공격을 방지한 행위을 kernel panic 이 발생됬다고 말한다..
SMEP 우회
kernel rop 을 작성을해서 우회한다. rop payload 는 commit_creds(prepare_kerenl_cred(0)) 코드를 구현한다.
gadget 을 구하듯이 objdump 등을 이용해 vmlinux 이미지 에서 kernelgadget 을 구하면됨
SMAP: 커널 공간에서 유저 공간에 대한 읽기/쓰기 구너한도 제한 하는 보호기법이다. 실행 권한만 제한하는 smep 에서 더 강화된 보호 기법이며 userspace 으로의 엑세스 자체를
제한한다.
smep 와 마찬가지로 cr4 레지스터에 smap 를 on/off 하는 제어 비트가 있다.
kerenlROP 만으로 우회할수 있는 smep 와 달리 우회 방법이 다양하며 다소 복잡하다.
qemu-system-x86_64 \
-m 512M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
-cpu qemu64,smep \
kernel@ubuntu:~/Desktop/smap_bypass$ cat smap.sh
qemu-system-x86_64 \
-m 512M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet nokaslr" \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
-cpu qemu64,smep,smap \
을 보면 smep , smap 을 추가 한것을 알수있다.
smap 는 stack based bof 취약점을 통해 kerenlROP를 작성하는 경우 익스플로잇이 진행 될때 유저 공간에 대한 액세스가 일어나지 않기때문에
smap 을 우회 할수 있다.
그다음은 원하는 slab 객체 크기의 UAF control 이 가능할경우 유저 공간에서 fork() 를 호출시 커널힙에 할당되는 cred 구조체의 멤버를 수정할수 있으며 이를 통해
smep 와 smap 우회가 가능하다.
그다음 우회하는 방법도 있다 kerenl heap pointer 을 leak 할수 있는 취약점이 있다면 kerenl heap spray 기법과 연계해서 수많은 공격
시나리오를 짤수 있다.
KADR 이 걸려져 있는 상화에서 디버깅을 할수 있는 tip
KADR : 커널 내부 정보와 관련된 파일들을 root 권한으로 만 확인 할수 있도록 하는 보호 기법이다.
user 권한에 /proc/kallsyms 파일은 커널의 모든 심볼들의 주소를 담고있다.
user 권한으로 /proc/kallsyms 를 확인하면 주소 대신 0000 을 출력 하는것이 확인 되었다.
/ $ cat proc/kallsyms | grep printk
0000000000000000 t umip_printk
0000000000000000 t umip_printk.cold
0000000000000000 T __warn_printk
0000000000000000 T __printk_ratelimit
0000000000000000 T vprintk
root 권한으로 수정 하는방법
/ $ ls
bin etc lib proc sbin tmp
dev init linuxrc root sys usr
/ $ mkdir rootfs
mkdir: can't create directory 'rootfs': Permission denied
/ $ mkdir rootfs
mkdir: can't create directory 'rootfs': Permission denied
/ $
[ 218.402223] reboot: Power down
kernel@ubuntu:~/Desktop/kadr_bypass$ ls
bzImage rootfs.cpio start.sh
kernel@ubuntu:~/Desktop/kadr_bypass$ clear
kernel@ubuntu:~/Desktop/kadr_bypass$ ls
bzImage rootfs.cpio start.sh
kernel@ubuntu:~/Desktop/kadr_bypass$ mkdir rootfs
kernel@ubuntu:~/Desktop/kadr_bypass$ cp rootfs.cpio rootfs
kernel@ubuntu:~/Desktop/kadr_bypass$ cd rootfs/
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ cpio -id -v < rootfs.cpio
.
lib
usr
usr/sbin
usr/sbin/chroot
usr/sbin/crond
usr/sbin/adduser
usr/sbin/killall5
usr/sbin/ntpd
usr/sbin/nologin
usr/sbin/add-shell
usr/sbin/rtcwake
usr/sbin/lpd
usr/sbin/setlogcons
usr/sbin/fakeidentd
usr/sbin/dnsd
usr/sbin/sendmail
usr/sbin/fdformat
usr/sbin/popmaildir
usr/sbin/loadfont
usr/sbin/tftpd
usr/sbin/svlogd
usr/sbin/nanddump
usr/sbin/fsfreeze
usr/sbin/ubidetach
usr/sbin/i2ctransfer
usr/sbin/ubirmvol
usr/sbin/i2cget
usr/sbin/rdate
usr/sbin/delgroup
usr/sbin/ubirename
usr/sbin/readahead
usr/sbin/ftpd
usr/sbin/nandwrite
usr/sbin/setfont
usr/sbin/mim
usr/sbin/udhcpd
usr/sbin/ifplugd
usr/sbin/i2cset
usr/sbin/arping
usr/sbin/dhcprelay
usr/sbin/i2cdetect
usr/sbin/chpasswd
usr/sbin/remove-shell
usr/sbin/deluser
usr/sbin/fbset
usr/sbin/ubimkvol
usr/sbin/ether-wake
usr/sbin/i2cdump
usr/sbin/ubiattach
usr/sbin/partprobe
usr/sbin/nbd-client
usr/sbin/addgroup
usr/sbin/ubiupdatevol
usr/sbin/powertop
usr/sbin/chat
usr/sbin/brctl
usr/sbin/readprofile
usr/sbin/telnetd
usr/sbin/rdev
usr/sbin/httpd
usr/sbin/ubirsvol
usr/bin
usr/bin/find
usr/bin/unexpand
usr/bin/uniq
usr/bin/free
usr/bin/dumpleases
usr/bin/timeout
usr/bin/bunzip2
usr/bin/telnet
usr/bin/rpm2cpio
usr/bin/shred
usr/bin/pmap
usr/bin/bc
usr/bin/hostid
usr/bin/yes
usr/bin/hexdump
usr/bin/ipcrm
usr/bin/pwdx
usr/bin/eject
usr/bin/uuencode
usr/bin/split
usr/bin/setkeycodes
usr/bin/sha3sum
usr/bin/[
usr/bin/bzcat
usr/bin/du
usr/bin/lspci
usr/bin/envdir
usr/bin/taskset
usr/bin/setuidgid
usr/bin/[[
usr/bin/lsof
usr/bin/rx
usr/bin/whois
usr/bin/truncate
usr/bin/cut
usr/bin/openvt
usr/bin/seq
usr/bin/sort
usr/bin/dpkg
usr/bin/uudecode
usr/bin/expand
usr/bin/tftp
usr/bin/sv
usr/bin/sha256sum
usr/bin/bzip2
usr/bin/flock
usr/bin/env
usr/bin/man
usr/bin/killall
usr/bin/lpq
usr/bin/mesg
usr/bin/resize
usr/bin/traceroute
usr/bin/lzma
usr/bin/fgconsole
usr/bin/nslookup
usr/bin/nproc
usr/bin/unlzma
usr/bin/ftpget
usr/bin/microcom
usr/bin/vlock
usr/bin/udhcpc6
usr/bin/printf
usr/bin/users
usr/bin/id
usr/bin/paste
usr/bin/less
usr/bin/strings
usr/bin/pstree
usr/bin/sha512sum
usr/bin/mkpasswd
usr/bin/wc
usr/bin/dpkg-deb
usr/bin/udpsvd
usr/bin/sha1sum
usr/bin/awk
usr/bin/unshare
usr/bin/unzip
usr/bin/logger
usr/bin/who
usr/bin/svc
usr/bin/expr
usr/bin/setsid
usr/bin/fold
usr/bin/top
usr/bin/test
usr/bin/fallocate
usr/bin/comm
usr/bin/reset
usr/bin/dos2unix
usr/bin/ts
usr/bin/pkill
usr/bin/smemcap
usr/bin/hexedit
usr/bin/xargs
usr/bin/chrt
usr/bin/tr
usr/bin/cksum
usr/bin/nc
usr/bin/last
usr/bin/factor
usr/bin/crontab
usr/bin/install
usr/bin/nmeter
usr/bin/pscan
usr/bin/clear
usr/bin/runsvdir
usr/bin/cmp
usr/bin/cryptpw
usr/bin/time
usr/bin/passwd
usr/bin/runsv
usr/bin/volname
usr/bin/which
usr/bin/cal
usr/bin/uptime
usr/bin/ipcs
usr/bin/xz
usr/bin/showkey
usr/bin/unlink
usr/bin/tty
usr/bin/basename
usr/bin/w
usr/bin/dirname
usr/bin/xzcat
usr/bin/envuidgid
usr/bin/logname
usr/bin/lzcat
usr/bin/chvt
usr/bin/tee
usr/bin/ttysize
usr/bin/pgrep
usr/bin/realpath
usr/bin/tcpsvd
usr/bin/nl
usr/bin/whoami
usr/bin/ftpput
usr/bin/deallocvt
usr/bin/tac
usr/bin/sum
usr/bin/od
usr/bin/setfattr
usr/bin/chpst
usr/bin/groups
usr/bin/patch
usr/bin/tail
usr/bin/lsscsi
usr/bin/readlink
usr/bin/softlimit
usr/bin/mkfifo
usr/bin/md5sum
usr/bin/wget
usr/bin/ssl_client
usr/bin/script
usr/bin/shuf
usr/bin/diff
usr/bin/nohup
usr/bin/unxz
usr/bin/wall
usr/bin/blkdiscard
usr/bin/lpr
usr/bin/dc
usr/bin/traceroute6
usr/bin/renice
usr/bin/lsusb
usr/bin/hd
usr/bin/svok
usr/bin/head
usr/bin/fuser
usr/bin/nsenter
usr/bin/unix2dos
usr/bin/beep
usr/bin/xxd
sbin
sbin/mkdosfs
sbin/watchdog
sbin/vconfig
sbin/pivot_root
sbin/fdisk
sbin/insmod
sbin/raidautorun
sbin/halt
sbin/route
sbin/slattach
sbin/hdparm
sbin/run-init
sbin/klogd
sbin/blkid
sbin/ifdown
sbin/zcip
sbin/reboot
sbin/ipneigh
sbin/mkfs.minix
sbin/swapoff
sbin/tunctl
sbin/lsmod
sbin/swapon
sbin/init
sbin/acpid
sbin/logread
sbin/blockdev
sbin/mkswap
sbin/rmmod
sbin/mke2fs
sbin/iplink
sbin/syslogd
sbin/makedevs
sbin/adjtimex
sbin/ipaddr
sbin/iprule
sbin/hwclock
sbin/tc
sbin/mkfs.vfat
sbin/fstrim
sbin/iptunnel
sbin/fbsplash
sbin/losetup
sbin/runlevel
sbin/loadkmap
sbin/switch_root
sbin/mkfs.ext2
sbin/poweroff
sbin/iproute
sbin/ip
sbin/udhcpc
sbin/devmem
sbin/bootchartd
sbin/findfs
sbin/mdev
sbin/ifup
sbin/start-stop-daemon
sbin/ifconfig
sbin/sysctl
sbin/nameif
sbin/uevent
sbin/fsck
sbin/modprobe
sbin/fsck.minix
sbin/arp
sbin/setconsole
sbin/depmod
sbin/freeramdisk
sbin/ifenslave
sbin/modinfo
sbin/getty
sbin/sulogin
linuxrc
proc
init
dev
sys
tmp
etc
etc/group
etc/passwd
bin
bin/nice
bin/iostat
bin/usleep
bin/base64
bin/uname
bin/mktemp
bin/ash
bin/ls
bin/resume
bin/zcat
bin/watch
bin/rpm
bin/date
bin/ed
bin/echo
bin/ionice
bin/dmesg
bin/hush
bin/tar
bin/setserial
bin/more
bin/cp
bin/arch
bin/setarch
bin/mpstat
bin/dumpkmap
bin/ping6
bin/linux32
bin/mknod
bin/egrep
bin/mv
bin/pidof
bin/umount
bin/login
bin/rev
bin/dd
bin/su
bin/setpriv
bin/link
bin/pipe_progress
bin/mountpoint
bin/printenv
bin/mkdir
bin/busybox
bin/fgrep
bin/fsync
bin/kbd_mode
bin/ps
bin/ipcalc
bin/lzop
bin/rmdir
bin/cpio
bin/kill
bin/chown
bin/rm
bin/grep
bin/chgrp
bin/chattr
bin/false
bin/cat
bin/sed
bin/run-parts
bin/dnsdomainname
bin/reformime
bin/fatattr
bin/vi
bin/sleep
bin/fdflush
bin/sh
bin/cttyhack
bin/scriptreplay
bin/stty
bin/chmod
bin/gzip
bin/touch
bin/stat
bin/mt
bin/linux64
bin/pwd
bin/ln
bin/mount
bin/nuke
bin/lsattr
bin/makemime
bin/sync
bin/netstat
bin/ping
bin/getopt
bin/hostname
bin/df
bin/gunzip
bin/true
bin/conspy
5990 blocks
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ ls
bin dev etc init lib linuxrc proc rootfs.cpio sbin sys tmp usr
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ cat init
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
poweroff -d 0 -f
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ vi init
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ cat init
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
setsid cttyhack setuidgid 0 sh
umount /proc
umount /sys
poweroff -d 0 -f
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ ls
bin dev etc init lib linuxrc proc rootfs.cpio sbin sys tmp usr
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ rm rootfs.cpio
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ find . | cpio -o --format=newc > ../rootfs.cpio
5990 blocks
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ ls
bin dev etc init lib linuxrc proc sbin sys tmp usr
kernel@ubuntu:~/Desktop/kadr_bypass/rootfs$ cd ..
kernel@ubuntu:~/Desktop/kadr_bypass$ ls
bzImage rootfs rootfs.cpio start.sh
kernel@ubuntu:~/Desktop/kadr_bypass$ ./start.sh
qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5]
/ # id
uid=0(root) gid=0(root) groups=0(root)
/ # cat proc/kallsyms | grep printk
ffffffff810530e0 t umip_printk
ffffffff8105368a t umip_printk.cold
ffffffff810673f1 T __warn_printk
ffffffff810bbe80 T __printk_ratelimit
ffffffff810bc470 T vprintk
ffffffff810bc640 T printk_timed_ratelimit
ffffffff810be220 T printk_percpu_data_ready
ffffffff810be3b0 T vprintk_store
ffffffff810be580 T vprintk_emit
ffffffff810be740 T vprintk_default
ffffffff810be890 T early_printk
ffffffff810beb80 T vprintk_deferred
ffffffff810bedb9 T printk
ffffffff810bf07f T printk_deferred
ffffffff810bf0f0 t printk_safe_log_store
ffffffff810bf1d0 t __printk_safe_flush
ffffffff810bf2f0 T printk_safe_flush
ffffffff810bf360 T printk_safe_flush_on_panic
ffffffff810bf390 T printk_nmi_direct_enter
ffffffff810bf3c0 T printk_nmi_direct_exit
ffffffff810bf3d0 T __printk_safe_enter
ffffffff810bf3e0 T __printk_safe_exit
ffffffff810bf3f0 T vprintk_func
ffffffff810bf49b t __printk_safe_flush.cold
ffffffff8112f140 T trace_vbprintk
ffffffff8112f600 t __trace_array_vprintk.part.0
ffffffff8112f7b0 T trace_vprintk
ffffffff8112f7e0 T trace_array_printk
ffffffff81131f00 T tracepoint_printk_sysctl
ffffffff81132590 T trace_printk_start_comm
ffffffff811325a0 T trace_array_vprintk
ffffffff811325c0 T trace_array_printk_buf
ffffffff81134ff0 T trace_printk_init_buffers
ffffffff811356b0 T trace_printk_seq
ffffffff81135d92 t trace_printk_init_buffers.cold
ffffffff81135eb3 t trace_printk_seq.cold
ffffffff81137160 T trace_print_bprintk_msg_only
ffffffff811371a0 T trace_print_printk_msg_only
ffffffff81138790 T __ftrace_vbprintk
ffffffff811387b0 T __trace_bprintk
ffffffff81138830 T __trace_printk
ffffffff811388a0 T __ftrace_vprintk
ffffffff811389a0 t module_trace_bprintk_format_notify
ffffffff81138c70 T trace_printk_control
ffffffff811538c0 W bpf_get_trace_printk_proto
ffffffff814529b0 T acpi_handle_printk
ffffffff81453222 t acpi_handle_printk.cold
ffffffff81535cd0 T drm_dev_printk
ffffffff81551540 T __i915_printk
ffffffff8155169b t __i915_printk.cold
ffffffff8166a63a T dev_vprintk_emit
ffffffff8166a806 T dev_printk_emit
ffffffff8166a866 t __dev_printk
ffffffff8166a8ab T dev_printk
ffffffff816a60f0 T sdev_prefix_printk
ffffffff816a6200 T scmd_printk
ffffffff816a6ae0 t sdev_prefix_printk.cold
ffffffff816a6ae7 t scmd_printk.cold
ffffffff816be013 T ata_port_printk
ffffffff816be08c T ata_link_printk
ffffffff816be12f T ata_dev_printk
ffffffff818c13f2 t __netdev_printk
ffffffff818c14f6 T netdev_printk
ffffffff81b26280 T printk_nmi_enter
ffffffff81b26290 T printk_nmi_exit
ffffffff82a1c31f t setup_early_printk
ffffffff82a2424a t printk_late_init
ffffffff82a245b4 T printk_safe_init
ffffffff82a27e6c t set_tracepoint_printk
ffffffff82a28731 t init_trace_printk_function_export
ffffffff82a2875e t init_trace_printk
ffffffff82a33e03 T printk_all_partitions
/ #
init 스크립트 을 수정해서 원하는 심볼 주소을 얻을수 잇었다. (bp 거는등 디버깅이 가능하다)
커널 디버깅을 할때 확인한 커널 주소가 바뀌지 않도록 qemu script 를 수정해 KASLR 을 끈 상태로 디버깅하는것을 추천한다.
만약 커널 힙과 관련된 취약점을 테스트 하는 경우 에는 suer 권한일때와 root 권하일때의 힙 풍수가 달라지기 떄문에 테스트중에는 user 권한으로 디버깅을 해야한다.
ssp : make 과정에서 사용되는 gcc 의 옵션으로 statck vased buffer overflow 를 방지 하는 보호기법이다.
스택에 랜덤한 cannary 값을 배치 하여 이 카나리 가 우회될 경우 overflow 가 발생된걸로 판단하여 커널 패닉이 발생 하는 보호 기법이다.
ssp 을 우회 하는 방법은 카나리 의 값을 넣어주며 payload 을 작성하면 된다 .
oob 등의 information leak 취약점을 이용해 canary 값을 leak 하면된다.
KPTI 란 : 커널공간 과 유저 공간의 전환이 일어날때 각각의 페이지 테이블을 사용하여 유저 공간 페이지 테이블을 사용하여 유저공간 페이지 테이블에 최소한의 커널 주소만 포함
하도록 하는 보호 기법이다.
커널공간 -> 유저공간으로 전환 할떄 호출되는 어셈블리 함수를 이용해서 우회 할수 있다.
cat start.sh 을 확인 해봤는데
-cpu kvm64,smep \ kpti 이적용 이 되어있다.
kpti 가 적용되지 않은것은 qemu64 로 되어있다.
기존에는 rop paylaod 에 swapgs 와 iretq 을 사용했었는데 여기에서 swapgs_resotre 어셈블리 함수가 추가 되었다는점이다 ( 코드 가젯이 추가 되었다는건가 싶다)
전체 적인 흐름은 rop 와 다를거는 없다.
swapgs_retore_regs_and_retrun_to_usermode 는 커널 공간 _> 유저공간으로 전활 될떄 호출되는 어셈블리 함수이다.
페이지 테이블을 분리 하는 역할을 한다.
'Pwnable 도서관 > Linux 스터디' 카테고리의 다른 글
| Kernel(3) (0) | 2024.01.25 |
|---|---|
| kernel(1) (1) | 2024.01.22 |
| ProtoStar (clear) (2) | 2023.11.28 |
| pwnable.kr [Toddler's Bottle] (0) | 2023.07.11 |
| pwntools (0) | 2023.05.19 |