-====-====-====-====-====-====-====-====-====-====-====-====-====-====-====-====- 제목 : Lamagra의 Omega Project의 이해 및 분석 작 성 자 : ttongfly@realskulls.org2003. 10. 10 홈페이지 : http://ttongfly.realskulls.org 참고문서 : Lamagra의 오메가 프로젝트의 이해 -원재아빠 getuid시스템에서 OMEGA의 적용 -원재아빠 Project OMEGA by Lamagra OMEGA Project Summary -H41d53 -====-====-====-====-====-====-====-====-====-====-====-====-====-====-====-====- Lamagra라는 해커가 오메가 프로젝트라는 것을 만들었다. 오메가 프로젝트란 그동안의 해오던 해킹기법인 쉘코드를 메모리에 올려서, ret에 그 주소를 덮쳐 쉘을 따는 복잡한 절차를 매우 크게 개선한 기법이다. 오메가 프로젝트는 취약 프로그램의 ret주소에 system함수의 주소를 넣어 쉘을 실행시키는 방법이다. 그러면 구체적으로 오메가 프로젝트의 원리와 공격기법이 어떻게 이루어지는지 알아보도록 하겠다. 테스트 환경은 다음과 같다.
다음은 테스트할 bof버그가 있는 프로그램이다.
main() { char buf[20]; printf(“name :”); fgets(buf,100,stdin); //Overflow 조건 printf(“Hi %s”,buf); dumpcode(buf, 100); } 위의 예제를 컴팔하기 위해 필요한 오하라님의 dumpcode.h 화일
자 root의 setuid를 걸어주었다. 이제 ttongfly라는 계정을 이용하여 root의 쉘을 따보도록 하자. 이제 오메가 프로젝트에서 필요한 시스템함수의 주소값을 찾아보도록 하자. 주소값을 찾는 방법은 여러가지가 있다. 첫째로, 원재아빠님이 말씀하신 방법이다. 바로 gdb로 덤프를 따는 것이다.
만약 서버에서 ptrace 버그를 방지할 목적으로 소유권한이 있는 쉘이 아닐경우 gdb에서 프로그램을 실행시킬 수 없는 경우, cp로 사본을 만들어 시스템 함수 주소를 확인하도록 하자.
공격시에는 buf[20][dummy12][dummy8][sfp4][ret4][dummy4][문자열주소값][bin/sh] 이런식으로 공격하면 되며, 문자열주소값은 ret+12값을 넣으면된다. 고로 먼저 ret의 값을 덤프해서 찾아야 한다.
그럼 공격이 되는지 살펴보자.
쉘이떳다! ^^; 근데.. root의 setuid는 받질 못했다. 이것은 리눅스의 getuid 시스템 때문이다. getuid 시스템이란 리눅스 커널 2.4.x부터 적용받기 시작한 보안시스템으로써 setuid 프로그램이 실행됨에 있어 해당 프로그램이 변조되어 다른 프로그램을 실행하려 할 때 getuid를 실행하여 실행하는 유저의 쉘변수 안에 uid를 가져와서 변조된 프로그램을 실행시키도록 하는 시스템이다. 그래서 위의 예에서 shell이 떳음에도 불구하고, 실행한 유저의 uid를 이미 가져온후 변조된 프로그램을 실행시켰기 때문에 root의 uid를 가질수 없었다. 그럼 getuid를 회피하려면 어떻게 해야할까.
원재아빠님이 제안하신 공격기법은 system함수를 실행하기전에 setreuid를 먼저 실행하여 uid를 0으로 실행한 후 system함수를 실행하여, getuid 시스템을 우회하는 기법이다. 공격은 다음과 같이 들어간다. buf[20][dummy12][dummy8][sfp4][setreuid주소4][system주소4][root의 uid 0값4][문자열주소][/bin/sh] 이런식으로 공격을하면 root를 딸 수 있다.
루트를 획득했다^^ 아이 기분저아~ 이상은 fgets나 scanf같은 함수에서 bof가 났을경우에 적용되는 방법이다. 프로그램상에서 strcpy와 같은 함수로 bof 버그가 날경우에는 위와같이 공격을 할 수 없다. 메모리 상에서 setreuid를 통해 root의 uid를 지정해줬던 문자인 \\x00\\x00\\x00\\x00이 무시되기 때문이다. 자 그러면 strcpy함수로 bof버그간 난 프로그램에서 어떻게 root쉘을 획득할 수 있는지 알아보자 다음은 strcpy에 위한 bof버그 프로그램이다.
main(int argc, char *argv[]) { char buf[16]; if(argc 1) strcpy(buf,argv[1]); dumpcode(buf,64); }
원재아빠님께서 제안하신 방법은 다음과 같다. 연속된 메모리를 보면 00의 값으로 채워진 곳이 있다. 이것을 우리가 공격할 코드의 끝자락으로 맞춰 주는 것이다.
함수는 계속해서 실행이 됨으로 이렇게 공격코드를 맞춘후… 원재아빠님의 문서에서 나온거와 같이 라마그라가 만든 심볼릭 링크 프로그램을 이용해서 공격을 하겠다. 여담이지만 쉘의 버젼때문에 라마그라가 만든 심볼릭 링크 프로그램은 약간의 수정을 가해야 한다. 예전의 쉘은 system함수로 쉘 실행시 “sh: : command not found ” 라는 에러가 발생하였지만 현재의 쉘은 “sh: line 1: ? command not found ” 식으로 라인까지 표시해주기 때문이다. 암튼 bang1575님이 수정해주신 심볼릭링크 프로그램을 이용해야만 root를 딸 수 있다. 우선 PATH부터 맞추고
if (argc != 2) { printf(“usage: %s file\\n”, argv[0]); exit(-1); } fd = fopen(argv[1], “r”); fgets(buf, 512, fd); extract = strrchr(buf, \’:\’); *extract = 0x0; extract = strrchr(buf, \’:\’); /* 수정된 부분 */ strcpy(filename, extract + 2); printf(“filename = %s\\n”, filename); fclose(fd); symlink(“/bin/sh”, filename); }
메세지가 뜨는 것을 out이란 파일에 저장한 후
루트를 획득할 수 있었다. 이상으로 getuid 상태에서의 오메가 프로젝트 쉘따기를 마무리 짓겠다. 하이데스님의 쉘코드를 이용한 방법도 이해하고 분석해보고 싶었지만.. 머리가 딸려서 다음으로 미루고.. 이상 마무리하는 바이다.