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で書かれた見にくいプログラムが確認できる。

スクリーンショット 2020-03-19 8.43.51

このままでは読みにくいので、改行やインデント等を調整する。自分でやるのは少々面倒なので、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}

picoCTF2019 write-upまとめ

いいなと思ったら応援しよう!