picoCTF2019 Client-side-again [Web Exploitation]
Can you break into this super secure portal? https://2019shell1.picoctf.com/problem/21886/ (link) or http://2019shell1.picoctf.com:21886
(適当な訳)この非常に安全なポータルサイトに侵入することはできますか?
Hints: What is obfuscation?
(適当な訳)難読化とはなんですか?
リンク先のページソースを確認すると、JavaScriptで書かれた見にくいプログラムが確認できる。
このままでは読みにくいので、改行やインデント等を調整する。自分でやるのは少々面倒なので、JavaScriptのコード整形ツールなどを使用するといいだろう。
< script type = "text/javascript" >
var _0x5a46 = ['9f266}', '_again_1', 'this', 'Password Verified', 'Incorrect password', 'getElementById', 'value', 'substring', 'picoCTF{', 'not_this'];
(function (_0x4bd822, _0x2bd6f7) {
var _0xb4bdb3 = function (_0x1d68f6) {
while (--_0x1d68f6) {
_0x4bd822['push'](_0x4bd822['shift']());
}
};
_0xb4bdb3(++_0x2bd6f7);
}(_0x5a46, 0x1b3));
var _0x4b5b = function (_0x2d8f05, _0x4b81bb) {
_0x2d8f05 = _0x2d8f05 - 0x0;
var _0x4d74cb = _0x5a46[_0x2d8f05];
return _0x4d74cb;
};
function verify() {
checkpass = document[_0x4b5b('0x0')]('pass')[_0x4b5b('0x1')];
split = 0x4;
if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) {
if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') {
if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) {
if (checkpass[_0x4b5b('0x2')](0x3, 0x6) == 'oCT') {
if (checkpass[_0x4b5b('0x2')](split * 0x3 * 0x2, split * 0x4 * 0x2) == _0x4b5b('0x5')) {
if (checkpass['substring'](0x6, 0xb) == 'F{not') {
if (checkpass[_0x4b5b('0x2')](split * 0x2 * 0x2, split * 0x3 * 0x2) == _0x4b5b('0x6')) {
if (checkpass[_0x4b5b('0x2')](0xc, 0x10) == _0x4b5b('0x7')) {
alert(_0x4b5b('0x8'));
}
}
}
}
}
}
}
} else {
alert(_0x4b5b('0x9'));
}
} < /script>
function veryfi内でパスワードの確認を行っているようだ。if文の最初の1行目は
if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3'))
パスワードの0x0〜0x8 (= 0x4 * 0x2)文字目が 「_0x4b5b('0x3')」と等しいかチェックしている。「_0x4b5b('0x3')」は表示させると「picoCTF{」であることがわかる。他の部分も表示させると、
var _0x5a46 = ['9f266}', '_again_1', 'this', 'Password Verified', 'Incorrect password', 'getElementById', 'value', 'substring', 'picoCTF{', 'not_this'];
(function (_0x4bd822, _0x2bd6f7) {
var _0xb4bdb3 = function (_0x1d68f6) {
while (--_0x1d68f6) {
_0x4bd822['push'](_0x4bd822['shift']());
}
};
_0xb4bdb3(++_0x2bd6f7);
}(_0x5a46, 0x1b3));
var _0x4b5b = function (_0x2d8f05, _0x4b81bb) {
_0x2d8f05 = _0x2d8f05 - 0x0;
var _0x4d74cb = _0x5a46[_0x2d8f05];
return _0x4d74cb;
};
console.log(_0x4b5b('0x3')) // -> picoCTF{
console.log(_0x4b5b('0x4')) // -> not_this
console.log(_0x4b5b('0x5')) // -> 9f266}
console.log(_0x4b5b('0x6')) // -> _again_1
console.log(_0x4b5b('0x7')) // -> this
console.log(_0x4b5b('0x8')) // -> Password Verified
console.log(_0x4b5b('0x9')) // -> Incorrect password
並べ替えるとパスワードがゲットできる。オーバーラップしているところもあるので見やすいように整理すると、
012345678901234567890123456789
(0-8) == picoCTF{
(7-9) == {n
(8-16) == not_this
(3-6) == oCT
(24-32) == 9f266}
(6-11) == F{not
(16-24) == _again_1
(12-16) == this
picoCTF{not_this_again_19f266}
答え:picoCTF{not_this_again_19f266}