We were given a [website](http://5a7f02d0.quals2018.oooverflow.io) with two PHP files: `sign.php` and `execute.php`, as well as two example PDF files.
Looking at the source code, which was available, the `sign.php` endpoint received a PDF file, extracted the text using `ocrad`, an OCR software, signed it using `openssl_sign` with a private key that, of course, we could not access, and returned the signature. The server signed only files containing the text `ECHO` (but not `EXECUTE`).
The `execute.php` endpoint received via a `POST` request a file, `userfile`, and a signature, `signature`, verified the signature using `openssl_verify`, and extracted the text using the same `pdf_to_text` function used in `sign.php`. Then, if the text starts with `ECHO`, it just prints the OCRed text; instead, if the text starts with `EXECUTE`, it passes the OCRed text to `shell_exec`.
Clearly, we must find a way to sign a PDF file containing an image of a text that starts with `EXECUTE`, but our signing endpoint refuses to sign files that start with `EXECUTE`.
Looking at the PHP documentation for `openssl_sign()`, we observe that the default algorithm (the one it's used) is SHA1. Thus, we immediately thought of the (not-so-recently-discovered-anymore) SHA-1 collision technique (https://shattered.io/static/shattered.pdf). Indeed, if we could create two different PDF files that hash to the same SHA1 value, we could execute arbitrary commands and cat our flag.
To create colliding PDFs, we used this online SHA collider: https://alf.nu/SHA1 to obtain two files `echo.pdf` and `execute.pdf`, one with a harmless `ECHO /bin/cat flag;` command, and the other one with `EXECUTE /bin/cat flag;`, both with the same SHA1 hash.
Once we have the two colliding files, it is only a matter of:
curl -F "email@example.com" http://5a7f02d0.quals2018.oooverflow.io/sign.php
to sign the harmless file:
Executing 'convert -depth 8 /tmp/phpMWWbFu.pdf /tmp/phpMWWbFu.ppm'
Executing 'ocrad /tmp/phpMWWbFu.ppm'
Extracted text: "ECHO /bin/cat flag;"
I'm OK with ECHO commands. Here is the signature:
At this point,
curl -F "firstname.lastname@example.org" -F "signature=`cat signature.txt`" http://5a7f02d0.quals2018.oooverflow.io/execute.php
leads to the flag:
Signature is OK.
Executing 'convert -depth 8 /tmp/php2dqia6.pdf /tmp/php2dqia6.ppm'
Executing 'ocrad /tmp/php2dqia6.ppm'
Text: "EXECUTE /bin/cat flag;"
About to execute: "/bin/cat flag;".