Log Search[link]
들어가면 화면 아래 쪽에 “http://logsearch.pwn.seccon.jp/logsearch.php“링크가 있다.
해당 링크로 들어가면 현재 검색된 로그들이 주르륵 뜬다.
여기서 flag파일을 찾으란다.
우리가 원하는건 접근 경로에 flag가 들어가고 반응이 200인거니
flag 200
을 처보았지만 다른 로그들에 뭍혀 flag 로그가 나오지 않는다.
이걸 request:flag AND response:200
이렇게 쳐줘야 flag 200 접근이 되는 로그가 나오며 flag를 볼 수 있다.
아니 저걸 저렇게 검색하는 방법을 어찌 알라는건지 모르겟다..
SqlSRF[link]
#!/usr/bin/perl use CGI; my $q = new CGI; use CGI::Session; my $s = CGI::Session->new(undef, $q->cookie('CGISESSID')||undef, {Directory=>'/tmp'}); $s->expire('+1M'); require './.htcrypt.pl'; my $user = $q->param('user'); print $q->header(-charset=>'UTF-8', -cookie=> [ $q->cookie(-name=>'CGISESSID', -value=>$s->id), ($q->param('save') eq '1' ? $q->cookie(-name=>'remember', -value=>&encrypt($user), -expires=>'+1M') : undef) ]), $q->start_html(-lang=>'ja', -encoding=>'UTF-8', -title=>'SECCON 2017', -bgcolor=>'black'); $user = &decrypt($q->cookie('remember')) if($user eq '' && $q->cookie('remember') ne ''); my $errmsg = ''; if($q->param('login') ne '') { use DBI; my $dbh = DBI->connect('dbi:SQLite:dbname=./.htDB'); my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';"); $errmsg = '<h2 style="color:red">Login Error!</h2>'; eval { $sth->execute(); if(my @row = $sth->fetchrow_array) { if($row[0] ne '' && $q->param('pass') ne '' && $row[0] eq &encrypt($q->param('pass'))) { $s->param('autheduser', $q->param('user')); print "<scr"."ipt>document.location='./menu.cgi';</script>"; $errmsg = ''; } } }; if($@) { $errmsg = '<h2 style="color:red">Database Error!</h2>'; } $dbh->disconnect(); } $user = $q->escapeHTML($user); print <<"EOM"; <!-- The Kusomon by KeigoYAMAZAKI, 2017 --> <div style="background:#000 url(./bg-header.jpg) 50% 50% no-repeat;position:fixed;width:100%;height:300px;top:0;"> </div> <div style="position:relative;top:300px;color:white;text-align:center;"> <h1>Login</h1> <form action="?" method="post">$errmsg <table border="0" align="center" style="background:white;color:black;padding:50px;border:1px solid darkgray;"> <tr><td>Username:</td><td><input type="text" name="user" value="$user"></td></tr> <tr><td>Password:</td><td><input type="password" name="pass" value=""></td></tr> <tr><td colspan="2"><input type="checkbox" name="save" value="1">Remember Me</td></tr> <tr><td colspan="2" align="right"><input type="submit" name="login" value="Login"></td></tr> </table> </form> </div> </body> </html> EOM 1;
문제 제목에서도 알수 있다 싶이 SQL injection 문제이다.
my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");
부분을 보면 prepare을 하지만 문자열을 직접 쿼리에 넣고 있으므로 injection으로 부터 취약하다.
이를 통해 Time based SQL injection을 하면 된다.
SQL injection을 통해 알아낸 admin의 password 는 “d2f37e101c0e76bcc90b5634a5510f64” 온라인에 존재하는 md5 테이블에 없다.
하지만 “remember” 쿠키에 내용이 디크립트 되어 Username input tag의 value로 들어가게 된다.
이를 통해 알아낼 수 있는건 d2f37e101c0e76bcc90b5634a5510f64는 “Yes!Kusomon!!” 이다.
25, 22, 80 포트가 열려있다.
wget 실행시 wget 버전과 리퀘스트의 결과가 나온다.
ID: admin, PW: Yes!Kusomon!!
으로 로그인을 하게 되면 “netstat”와 wget을 실행 할 수 있는 페이지가 뜬다.
command injection은 안되니 다른 방법을 찾으면, wget가 버전이 낮다 즉 문제의 제목처럼 wget의 bug를 사용할 수 있다. (SSRF)
Payload : 127.0.0.1%0d%0aTest%3a %0aHELO 127.0.0.1%0aMAIL FROM%3a%3csilnex%40silnex.kr%3e%0aRCPT TO%3a%3croot%40localhost%3e%0aDATA%0aFrom%3a silnex%40silnex.kr%0aTo%3a root%40localhost%0aSubject%3a give me flag%0d%0a.%0d%0a%0aQUIT%0a:25
SMTP 포트가 열려있는 것을 확인 햇다면, 해당 취약점을 통해 메일을 보내자.
그러면 encrypt 된 37208e07f86ba78a7416ecd535fd874a3b98b964005a5503bcaa41a1c9b42a19 문자열이 오는데 ,
이를 admin의 password를 decrypt한 것처럼 “remember” 쿠키에 넣게 되면 SECCON{SSRFisMyFriend!}
flag가 나오게 된다.
automatic_door[link]
<?php $fail = str_repeat('fail', 100); $d = 'sandbox/FAIL_' . sha1($_SERVER['REMOTE_ADDR'] . '95aca804b832f4c329d8c0e7c789b02b') . '/'; @mkdir($d); function read_ok($f) { return strstr($f, 'FAIL_') === FALSE && strstr($f, '/proc/') === FALSE && strstr($f, '/dev/') === FALSE; } function write_ok($f) { return strstr($f, '..') === FALSE && read_ok($f); } function GetDirectorySize($path) { $bytestotal = 0; $path = realpath($path); if ($path !== false && $path != '' && file_exists($path)) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS)) as $object) { $bytestotal += $object->getSize(); } } return $bytestotal; } if (isset($_GET['action'])) { if ($_GET['action'] == 'pwd') { echo $d; exit; } else if ($_GET['action'] == 'phpinfo') { phpinfo(); exit; } else if ($_GET['action'] == 'read') { $f = $_GET['filename']; if (read_ok($f)) echo file_get_contents($d . $f); else echo $fail; exit; } else if ($_GET['action'] == 'write') { $f = $_GET['filename']; if (write_ok($f) && strstr($f, 'ph') === FALSE && $_FILES['file']['size'] < 10000) { print_r($_FILES['file']); print_r(move_uploaded_file($_FILES['file']['tmp_name'], $d . $f)); } else echo $fail; if (GetDirectorySize($d) > 10000) { rmdir($d); } exit; } else if ($_GET['action'] == 'delete') { $f = $_GET['filename']; if (write_ok($f)) print_r(unlink($d . $f)); else echo $fail; exit; } } highlight_file(__FILE__);
파라미터에 action=write과 filename을 보내면 action=pwd에 나오는 경로에 저장해준다.
- .htaccess 파일에 .html 등 다른 확장자에서도 php 코드가 실행 되게한다.
AddType application/x-httpd-php .html .htm
이렇게 하면 html파일과 htm파일에서도 php코드가 실행 된다. - 리버스쉘이든 웹쉘이든올린다.
- flag를 찾는다.