Sunday, April 28, 2013

PlaidCTF secure_reader

Target: Linux box with a flag

Secure_reader was the easiest pwning challenge, at 150 points. As I no longer have access to the box, terminal I/O will be fake.

Situation

When you ssh into the box, you find 3 files inside /home/securereader: reader(ELF) secure_reader(ELF) and flag(plaintext). The flag was only readable by the securereader user, secure_reader was a setuid executable, and reader was just a plain ol' executable.

I ran secure_reader and reader to see what would happen.

>./reader
Syntax: ./reader <file>

>./reader flag
File is not in a whitelisted directory!

>./secure_reader flag
Must be run by /home/securereader/reader!

Pwning

So I opened up reader in my favorite disassembler, and found out the only whitelisted directories are /tmp. After looking around /tmp, I see /tmp/flag with the same filesize and permissions as /home/securereader/flag. I'm unsure as to whether it was inside /tmp from the start, or if previous solvers had managed to get it there, but that didn't matter, I was there to read the flag, not worry about how it got there.

>/home/securereader/reader /tmp/flag
Must be run by /home/securereader/reader!

How strange, even though secure_reader is getting called by reader it is still saying it is not. After looking at the disassembly of secure_reader and reader, I figured out that it was because reader invokes secure_reader via system(). This causes the parent process of secure_reader to be a shell, and not reader. Since it's a setuid process, we can't use GDB to patch the call to system with a call to exec, but what we can do is inject commands into the spawned shell. The exec command will do nicely, it runs an executable with the parent process of the shell. The parent process of the shell is reader, so secure_reader's check should pass. To inject commands into the shell, all we have to do is add a semicolon somewhere in the filename, after which will be new commands to run. I don't remember why I used the environment variables, but it worked, didn't it?

teamXXX@securereader:/tmp$ PATH="/home/securereader:$PATH" flag="/tmp/flag" /home/securereader/reader "/tmp/234;exec secure_reader \$flag"
This may only be called by /home/securereader/reader
that_was_totally_a_good_idea
 
Yay! Got the flag!

No comments:

Post a Comment