生存報告

主に情報セキュリティ関連のエントリをたまに書いて、存命であることを報告するページ。

Webページ上のパーセント値を1000%に変更するChrome拡張「ZAIA Percent」

いやー唐突ですが仮面ライダーゼロワン面白いですね。僕は毎週楽しみにしています。

登場人物では或人君や不破さんも好きなんですが、1000パーセント1000パーセント連呼するZAIAの天津垓社長も好きです。毎回大活躍で見てるだけで楽しいです。特に必殺技JACKING BREAKを放つ際のカットインに「© ZAIA エンタープライズ」が入るのは何回見ても笑ってしまう。考えた人天才じゃなかろうか。

一方で、大企業の嫌な社長という位置づけでもあるので、倒したときのカタルシスもあるし。

いくつか画像を引用。

(進捗率1000パーセントは、計画を見直したほうがいいのでは…)

そんなこんなで毎週楽しんでいる中でふと思い立ったのが、普段見ているWebページで見かける各種のパーセント表記、これを全部1000パーセントに変えるとZAIAの社長の気分になれて楽しいんじゃないかと。なので作ってみました。

作ったもの

ZAIA PercentというGoogle Chromeの拡張です。公開済なのでChrome Web Storeからダウンロードできます。

chrome.google.com

ソースコードGithubで公開しています。

github.com

機能

ページのDOMを検索して、パーセント表記(例:50パーセント, 70%など)があれば一律1000%に置き換えます。

アドレスバー横にある拡張のアイコンをクリックすると発動します。でもこれだと変わったタイミングが分かりづらいので、JACKING BREAKのカットインを入れて同時にDOMを更新するようにしました。もちろん、「© ZAIA エンタープライズ」も入ります。

デモ

ZAIA Percent demo

ただこれだけの機能なんですが、置き換えたあとの文章を改めて読むとシュールでけっこう楽しいです。特に算数の問題の解説をしているページとかいいですね。こんな感じになります。

例1

https://yosemi-7.com/post-34700

【変更前(引用)】

クラスの男子の人数は20人で、男子の割合は50パーセントです。クラスは全部で何人ですか?

【変更後】

クラスの男子の人数は20人で、男子の割合は1000パーセントです。クラスは全部で何人ですか?

例2

https://oshiete.goo.ne.jp/qa/4854114.html

【変更前(引用)】

お店のバーゲンセールなどでよく「50%オフ」「45%オフ」といった表示を見ます。50%は半分ということは「感覚」でわかるので、定価が2000円ならその50%オフは1000円ですし、1500円なら750円と計算が出来ます。 ですが、たとえば75%オフだとか、44%オフだとか、80%オフだとか、そういう中途半端(?)な数の場合、さっぱりわからないのです。テレビなんかでバーゲンセールを取材している様子を見るとリポーターの女性なんかが「定価が○○円で、65%オフ!?ということは○○円ですね!?」などとパッと暗算で計算しているのを見るととても驚きます。

【変更後】

お店のバーゲンセールなどでよく「1000%オフ」「1000%オフ」といった表示を見ます。1000%は半分ということは「感覚」でわかるので、定価が2000円ならその1000%オフは1000円ですし、1500円なら750円と計算が出来ます。 ですが、たとえば1000%オフだとか、1000%オフだとか、1000%オフだとか、そういう中途半端(?)な数の場合、さっぱりわからないのです。テレビなんかでバーゲンセールを取材している様子を見るとリポーターの女性なんかが「定価が○○円で、1000%オフ!?ということは○○円ですね!?」などとパッと暗算で計算しているのを見るととても驚きます。

うわー楽しい。

仕様の補足

まあソースコード見れば全部書いてあるんですが自分の整理も兼ねて。

DOMの書き換えはjQueryでやりました。filterでTextNodeのみ抽出し、その後Node単位でパーセント表記を置換したTextNodeを生成し、既存のTextNodeと置き換え。既存のDOM構造を保ったままテキストだけ変えるのって意外と面倒。

仕様上、任意のWebページのDOMにアクセスする必要があるので、httpおよびhttpsスキームのURIで動作できるよう拡張のmanifestを記述しています。

Chrome拡張は非常に強力で、やろうと思えばDOMを悪意のある内容に変えたり、外部との通信などもできるのですが、この拡張ではもちろんしていません。

まとめ(またはニチアサの話)

1000パーセント社長、やはり悪役が立っているのは良いです。こんなのを作ろうと思い立ったきっかけとモチベーションにもなったし。これからも活躍してほしいです。

さて前回の予告でもあったように、今週末はついに唯阿さんが社長にラッシングブラストフィーバーで退職届を叩きつける回ですね。どんな展開になるか、今からワクワクしています。

でも、今後はどうなっちゃうんでしょうね。キラメイはレッドの小宮君がCOVID-19で陽性、ゼロワンだってこの緊急事態のもとでずっと続けられるか分からない。その前にやっているプリキュアは今週末(2020/4/26)から新規を中断して過去の放映分から厳選して放映するとか。

この厳戒態勢がいつまで続くか先行きが見えなくて不安ですが、東映さんにはここをしのいでもらって今後も良い作品を作り続けてほしいです、応援しています。なおTTFCは課金してます。

DOM Based XSS対策のChromeの新機能「Trusted Types」を試してみた

先日、Goole Chromeの新機能としてTrusted Typesという機能がアナウンスされました。これは、DOM Based XSSを防ぐために実装された機能です。

https://developers.google.com/web/updates/2019/02/trusted-types

本エントリでは、Trusted Types実際に試して、使い勝手や効果のほどを見てみようと思います。

DOM Based XSS

「DOM Based XSSとは」的な説明は割愛。DOMを更新するときに発生するXSSです。 上のリンクやIPA、OWASPのページなどを見てください。ここではIPAのレポートを紹介しておきます。

https://www.ipa.go.jp/files/000024729.pdf

DOM Based XSSの例

DOM Based XSSでalertを上げてみます。以下を参考に、脆弱性のあるHTMLファイルを用意します。

https://github.com/masatokinugawa/filterbypass/wiki/Browser's-XSS-Filter-Bypass-Cheat-Sheet#%E5%85%A8%E3%81%A6%E3%81%AEdom-based-xss

index.html

<html>
<head>
  <title>DOM test</title>
</head>
<body>
<script>
hash=location.hash.slice(1);
document.body.innerHTML=decodeURIComponent(hash);
</script>
</body>
</html>

このHTMLでは、location.hash(URL内の#以降)を用いてDOMツリー(body要素のinnerHTML)を更新しています。以下のようなURLにアクセスすることでalertが上がります。

https://example.com/#%3Cimg%20src=x%20onerror=alert(1)%3E

f:id:tosebro:20190220012205p:plain

hashに指定したimg要素がDOMツリーに追加されています。

f:id:tosebro:20190220012221p:plain

DOM Based XSSの厄介なところ

脆弱性があるのか、チェックしづらいのが厄介です。上記はシンプルな例なのですぐわかりますが、実際にはjsライブラリ等も使うでしょうし、処理を追っていくのも一苦労。 動的に動かして確認するには腕とかに限界が来る。コードレビューとかで見つけようにも目とかに限界が来る。 個人的にはコードレビューした上で怪しいところを動的確認が現実的かなと思っています。

Trusted Types

DOM Based XSS対策のため、Google ChromeにTrusted Typesという機能が搭載されました。これを使うと、以下のコンセプトによりDOMの更新に制約がかかります。

  • stringを使用してDOMを更新できなくなる
  • 個別に定義したTrusted Type Policiesから生成されるTrusted Typesオブジェクトでのみ、DOMを更新できる

これにより、DOM Based XSSの入り込む余地をTrusted Type Policies内に限定できます。DOM Based XSS対策のためのコードレビューが楽になり、かつコードの品質が上がることが期待されます。

実際に例を見てみましょう。

準備

Trusted TypesはGoogle Chrome 73以降の機能なので、2019/02/20時点の安定版では使用できません。 いくつか準備が必要になります。

  • 最新開発版をインストールする。僕はChrome Canary https://www.google.com/chrome/canary/ を使いました。
  • Trusted Typesを有効にする。いくつか方法がありますが、僕は chrome://flags で設定しました。
chrome://flags/#enable-experimental-web-platform-features
  • Webサーバ側で、Content-Security-Policyレスポンスヘッダを出力する。
Content-Security-Policy: trusted-types *

Trusted Typesの動作確認

これで、さきほどのHTMLにもう一度アクセスしてみます。

f:id:tosebro:20190220012223p:plain

今度は実行されませんでした。Consoleログを見ると、innerHTMLの更新でTypeErrorとなっていることがわかります。

f:id:tosebro:20190220012225p:plain

Uncaught TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires `TrustedHTML` assignment.
    at (index):8

Trusted Type Policiesを使って書き換え

Trusted Type Policiesを使って元のHTMLを書き換え、以前のようにDOMを更新できるようにしてみます。1

index2.html

<html>
<head>
  <title>DOM test</title>
</head>
<body>
<script>
// define Trusted Type Policies
const templatePolicy = TrustedTypes.createPolicy('template', {
  createHTML: (hash) => {
    if(hash) {
      return decodeURIComponent(hash.slice(1));
    }
    throw new TypeError();
  }
});

// obtain Trusted Types object
const htmlcode = templatePolicy.createHTML(location.hash);
// htmlcode instanceof TrustedHTML
document.body.innerHTML=htmlcode;
</script>
</body>
</html>

簡単に言うと、templatePolicyポリシーを定義して、その中のcreateHTMLでDOMを更新するためのstringを作成しています。戻り値はTrustedHTMLオブジェクトになっていて、これでならDOMの更新が許可されているという形です。 2

変更したindex2.htmlにアクセスします。

https://example.com/index2.html#%3Cimg%20src=x%20onerror=alert(1)%3E

f:id:tosebro:20190220012237p:plain

alertが上がりました。

DOM Based XSSをコードレビューで確認するにはTrusted Type Policiesを定義する部分だけをレビューすればいいので、レビュー工数の削減、コードの品質向上(チェック漏れを防ぐ)などが期待されます。

Trusted Typesは使えそうか

興味深いコンセプトですし、効果もある。個人的には期待しています。あるべき論でいうとDOMをHTMLで更新するなってところになると思うのですが、まあ動的にHTMLを変えたいニーズもあるでしょうし、そのときに効果的に対策できる機能があるのは良いことだと思います。 一方で、実用にはまだ課題もありそうです。僕の考える課題はこんなところです。

  • 既存のプロダクトに取り入れるには、改修工数の面で難しそう
  • モダンなjsフレームワークをバリバリ使っている場合でも、無理なく実装できるんだろうか 3
  • 現状はChrome限定、かつ正式版でのリリース前なので、まだ対策として普及するには時間がかかりそう。すなわち人に推奨するのも難しい。 4

まとめ

DOM Based XSS対策としてTrusted Typesを紹介しました。Trusted Typesが、どのようにDOM更新を制限し、XSSが入り込む余地を制限しているかを、実際に動作させることにより確認しました。普及にはまだ時間がかかりそうですが、今後対応ブラウザが増えていけば有用な対策ツールになるのではないかと期待しています。


  1. 意味のある処理は何もしてないけど、書き換えの例として。

  2. templateはサンプルそのまま使っちゃった。hashとかに変えておくべきだった。

  3. このへん、知見のある方に聞いてみたい

  4. ここはメジャーなブラウザの対応待ちかな

CMSの脆弱性スキャナをいくつか試した

これまで、CMSってWordPressくらいしか触ったことない&脆弱性スキャナもWPScanくらいしか知らなかったので、情報収集がてら検証してみた。

昨年末に検証したログを記録として残しておく。1

対象のCMS脆弱性スキャナ

選定基準は以下のとおり。

  • CMS製品はシェアの大きいものを対象とする
  • 脆弱性の検証ということで、CMSはある程度、脆弱性の存在するバージョンとする。検証時点(2017年12月)から1年前時点の最新版とする
  • 脆弱性スキャナはKitPloitでヒットしたものから選定する

シェアは以下を参考にした。 Usage Statistics and Market Share of Content Management Systems for Websites, January 2018

選定の結果、以下の表のようになった。2

CMS Scanner Known Vulnerability
WordPress 4.7 WPScan 2.9.3 NVD - CVE-2017-5487
etc.
Joomla! 3.6.5 JoomScan 0.0.4
joomlavs
CMSsc4n 2.0
NVD - CVE-2017-9933
etc.
Drupal 8.2.4 Dropescan 1.40.1
CMSsc4n 2.0
NVD - CVE-2017-6919
etc.

CMSUbuntu Server、攻撃側はKali Linuxを使用。(一部例外あり)

実行結果とセットアップ時のメモ

セットアップ時のメモは主に自分用。

WordPress

公式サイトと5分間インストールを参考にインストールした。

WordPress のインストール - WordPress Codex 日本語版

Joomla!

インストールがうまくいかず調べたらPHPのモジュールが足りない模様。以下でインストール。

sudo apt-get install php7.0-xml

Drupal

こちらもモジュールが必要。 そのあとwgetで持ってきて、展開→公開ディレクトリにシンボリックリンク

sudo apt-get install php-gd
sudo apt-get install php-xml
wget https://ftp.drupal.org/files/projects/drupal-8.2.4.tar.gz

WPScan

https://wpscan.org/

Kali Linuxに入っている。メジャーなスキャナなだけあって色々検出してくる。

実行結果:

# wpscan --url http://192.168.112.135/wordpress/ --enumerate
_______________________________________________________________
        __          _______   _____                  
        \ \        / /  __ \ / ____|                 
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \ 
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|

        WordPress Security Scanner by the WPScan Team 
                       Version 2.9.3
          Sponsored by Sucuri - https://sucuri.net
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_
_______________________________________________________________

[+] URL: http://192.168.112.135/wordpress/
[+] Started: Fri Dec 29 10:01:22 2017

[!] The WordPress 'http://192.168.112.135/wordpress/readme.html' file exists exposing a version number
[+] Interesting header: LINK: <http://192.168.112.135/wordpress/wp-json/>; rel="https://api.w.org/"
[+] Interesting header: SERVER: Apache/2.4.18 (Ubuntu)
[+] XML-RPC Interface available under: http://192.168.112.135/wordpress/xmlrpc.php
[!] Includes directory has directory listing enabled: http://192.168.112.135/wordpress/wp-includes/

(snip)

[!] Title: WordPress 4.7 - User Information Disclosure via REST API
    Reference: https://wpvulndb.com/vulnerabilities/8715
    Reference: https://www.wordfence.com/blog/2016/12/wordfence-blocks-username-harvesting-via-new-rest-api-wp-4-7/
    Reference: https://github.com/WordPress/WordPress/commit/daf358983cc1ce0c77bf6d2de2ebbb43df2add60
    Reference: https://wordpress.org/news/2017/01/wordpress-4-7-1-security-and-maintenance-release/
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5487
[i] Fixed in: 4.7.1

(snip)

[+] Enumerating usernames ...
[+] Identified the following 1 user/s:
    +----+-------+---------+
    | Id | Login | Name    |
    +----+-------+---------+
    | 1  | admin | 404 Not |
    +----+-------+---------+
[!] Default first WordPress username 'admin' is still used

JoomScan

Category:OWASP Joomla Vulnerability Scanner Project - OWASP

github.com

OWASPのプロジェクトになっている。バージョン判定のほか、既知の脆弱性の判定もやってくれる。 スキャナの更新が2012年で止まっている?ので、現行の脆弱性には対応しなさそう。

git cloneしてインストール、URL指定して実行する。

git clone https://github.com/rezasp/joomscan.git
joomscan -u http://192.168.112.135/joomla/

実行結果:

 ..|''||   '|| '||'  '|'     |      .|'''.|  '||''|.  
.|'    ||   '|. '|.  .'     |||     ||..  '   ||   || 
||      ||   ||  ||  |     |  ||     ''|||.   ||...|' 
'|.     ||    ||| |||     .''''|.  .     '||  ||      
 ''|...|'      |   |     .|.  .||. |'....|'  .||.     
    
(snip)

Target: http://192.168.112.135/joomla
Server: Apache/2.4.18 (Ubuntu)

## Checking if the target has deployed an Anti-Scanner measure

[!] Scanning Passed ..... OK 

## Detecting Joomla! based Firewall ...

[!] No known firewall detected!

## Fingerprinting in progress ...

~Unable to detect the version. Is it sure a Joomla? 

## Fingerprinting done.

Vulnerabilities Discovered
==========================

# 1
Info -> Generic: htaccess.txt has not been renamed. 
Versions Affected: Any
Check: /htaccess.txt
Exploit: Generic defenses implemented in .htaccess are not available, so exploiting is more likely to succeed.

Vulnerable? Yes

# 2
Info -> Generic: Unprotected Administrator directory 
Versions Affected: Any
Check: /administrator/
Exploit: The default /administrator directory is detected. Attackers can bruteforce administrator accounts. Read: http://yehg.net/lab/pr0js/view.php/MULTIPLE%20TRICKY%20WAYS%20TO%20PROTECT.pdf

Vulnerable? Yes

# 3
Info -> Core: Multiple XSS/CSRF Vulnerability 
Versions Affected: 1.5.9 <= 
Check: /?1.5.9-x
Exploit: A series of XSS and CSRF faults exist in the administrator application.  Affected administrator components include com_admin, com_media, com_search.  Both com_admin and com_search contain XSS vulnerabilities, and com_media contains 2 CSRF vulnerabilities.  

Vulnerable? N/A

(snip)

joomlavs

github.com

バージョンチェックはやってくれる。脆弱性の検出はなかった。

実行にあたり、Ubunturubyではrubyモジュールの追加インストールが必要だった。スキャナを走らせてエラーメッセージを眺めつつ、必要なモジュールをがしがしインストール。 gemでのインストールがrootでできなかったので、攻撃側もUbuntu Serverで実行。

インストール用:

ruby -v
sudo gem install bundler && bundle instal
sudo apt-get install build-essential patch
sudo apt-get install ruby-dev zlib1g-dev liblzma-dev libcurl4-openssl-dev
sudo gem install slop
sudo gem install typhoeus
sudo gem install nokogiri
sudo gem install colorize

実行結果:

./joomlavs.rb -u http://192.168.112.135/joomla/ --scan-all

----------------------------------------------------------------------

     ██╗ ██████╗  ██████╗ ███╗   ███╗██╗      █████╗ ██╗   ██╗███████╗
     ██║██╔═══██╗██╔═══██╗████╗ ████║██║     ██╔══██╗██║   ██║██╔════╝
     ██║██║   ██║██║   ██║██╔████╔██║██║     ███████║██║   ██║███████╗
██   ██║██║   ██║██║   ██║██║╚██╔╝██║██║     ██╔══██║╚██╗ ██╔╝╚════██║
╚█████╔╝╚██████╔╝╚██████╔╝██║ ╚═╝ ██║███████╗██║  ██║ ╚████╔╝ ███████║
 ╚════╝  ╚═════╝  ╚═════╝ ╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝  ╚═══╝  ╚══════╝

----------------------------------------------------------------------

[+]URL: http://192.168.112.135/joomla/

[+]Started: Fri Dec 29 09:20:02 2017

[+]Found 1 interesting headers.

| Server: Apache/2.4.18 (Ubuntu)

[!]Listing enabled: http://192.168.112.135/joomla/administrator/components/

[!]Listing enabled: http://192.168.112.135/joomla/administrator/modules/

[!]Listing enabled: http://192.168.112.135/joomla/administrator/templates/

[+]Joomla version 3.6.5 identified from admin manifest

[!]Found 0 vulnerabilities affecting this version of Joomla!

[+]Scanning for vulnerable components...

[!]Found 0 vulnerable components.

------------------------------------------------------------------

[+]Scanning for vulnerable modules...

[!]Found 0 vulnerable modules.

------------------------------------------------------------------

[+]Scanning for vulnerable templates...

[!]Found 0 vulnerable templates.

------------------------------------------------------------------

Dropescan

github.com

バージョンチェックはやってくれる。脆弱性の検出はなかった。

git cloneとモジュールのインストールで完了。URLを指定して実行。

# droopescan scan drupal -u http://192.168.112.135/drupal/

実行結果:

[+] No themes found.

[+] No interesting urls found.

[+] Possible version(s):
    8.2.3

[+] No plugins found.

出力が素っ気ない。(悪いというわけではない)

CMSsc4n

github.com

CMSの使用有無とバージョンを判定してくれる。既知の脆弱性などは見ない。あとJSONExcelかで出力できるというちょっと変わった仕様。

Joomla!をスキャンする際、ローカルの環境では/joomla/まで指定しないといけなかった。手動で見るより少しマシくらいか。

スキャン対象の情報をJSONで指定する。JSONの書式が分からなかったので、ソースコードを読みつつトライ・アンド・エラーで実行。

JSONファイル:

# cat testsite.json 
{"192.168.112.135/joomla/": "text"}

実行コマンド:

python ./cmssc4n.py -e 2 -i testsite.json

実行結果:

  / ____|  \/  |/ ____|        | || |      
 | |    | \  / | (___  ___  ___| || |_ _ __  
 | |    | |\/| |\___ \/ __|/ __|__   _| '_ \ 
 | |____| |  | |____) \__ \ (__   | | | | | |
  \_____|_|  |_|_____/|___/\___|  |_| |_| |_|

** Tool to scan if a domain is a CMS (Wordpress , Drupal, Joomla, Prestashop or Moodle) and return the version
    ** Author: Ignacio Brihuega Rodriguez a.k.a N4xh4ck5
    ** Version 1.0
    ** DISCLAMER This tool was developed for educational goals. 
    ** The author is not responsible for using to others goals.
    ** A high power, carries a high responsibility!

192.168.112.135/joomla/

*****Checking if the CMS is a Wordpress*****
The CMS is not a Wordpress

*****Checking if the CMS is a Moodle*****
The CMS is not a Moodle

*****Checking if the CMS is a Drupal*****
The CMS is not a Drupal

*****Checking if the CMS is a Joomla*****
The CMS is a Joomla! => /language/en-GB/en-GB.xml file found. Trying to detect the version
Version Joomla detected in /language/en-GB/en-GB.xml ==> Joomla 3.6.5
The version Joomla is outdated

192.168.112.135/joomla/  is joomla
Exporting the results in a json

DrupalはJoomlaのときと同じ書式で実行できず。原因不明。

所感

  • 実用的なのはWPScanくらい。他のツールは環境あればやっておくか、くらい。
  • JoomScanも良いんだけどメンテされていないのがネック。3
  • どのツールも、Hack用ツールらしくアスキーアートでロゴ作っててすごい。自分もツールを作る際は見習いたい。

まとめ

シェアの大きいCMSを対象に、いくつかスキャナを試した。結論としてはやはりWPScanが実用レベル、他は無いより良いくらいだった。

が、シェアがWordPress一強なのであまり問題ないでしょう。4


  1. 残しておかないと自分も覚えていないお蔵入りになりそうなので。

  2. MovableTypeはシェアなさそうだし、とりあえず対象外。今回は種類を試すのが主旨なのでWordPressスキャナはWPScanのみ。

  3. プルリクしろという話だろうか……

  4. そのとき考えよう、の意

VirtualBoxでゲストOS同士を通信させる方法

最近やった検証で、VirtualBoxのゲストOS同士で通信させる必要があったので調べて設定したのでそのメモ。
なんか調べたら内部ネットワークに設定するとか色々出てきて、どれが目的に合うか分からなかったので、今回やった方法を残しておく。

ゲストOSは2台で、WindowsLinuxが各1台。
目的としてはゲストOS同士が通信できればそれで良い。インターネット接続は必須でない。

設定方法は、各ゲストOSのネットワーク設定で、それぞれ以下に設定する。

  • 割り当て:ホストオンリーアダプタ
  • 名前:VirtualBox Host-Only Ethernet Adapter
  • プロミスキャスモード:許可


あとはDHCPIPアドレスが割り振られた。

VirtualBoxVMWareよりもネットワークの設定項目が多くてややこしく感じた。でも慣れの問題かもしれない。