アプリ開発のセキュリティについて備忘録。Java前提。
まずはIPAのサイトを見るべき
要約
- ユーザの入力を信用するな
- ユーザが入力できる部分を信用するな
- ブラウザが実行するイメージを持とう
- JSON使え
- 同一オリジンポリシーえらい(過去記事)
XSS
Cross-Site Scripting。
同一オリジンポリシーがあるならそのサイト自体に悪意あるスクリプトを発行させればいいじゃない、な攻撃。
掲示板にスクリプトを書き込み、ロードした他人のブラウザで実行させるイメージだったが、それ(Stored)以外にもある。
Reflected, Stored, DOM-basedの3種で、どうやってそのサイトが発行したことにするかが異なる。
Reflected, DOM-basedの説明を読んで、自身のブラウザが送信した/持っているスクリプトが自身のブラウザで実行されるだけなので何が問題か分からなかった。
以下のサイトで、リンクを踏ませる時に?q=
や#paragraph
で意図しない情報を付加させるイメージが掴め、理解できた。
Open Redirection
要はXSSと同じで、?q=
とかの手打ちできる部分を元に動的に処理すると、攻撃者によって意図しないリダイレクト先のリンク作られちゃうよという話。
(ページが)リダイレクト先の情報を動的に決めていると、(攻撃者が作成した)変なリンクによって、(善意のユーザが)変なページにリダイレクトされてしまう、という感じで主語がたくさんある手法なのでイメージを整理しておきたい。
「外部ページだけど大丈夫?」という確認ページ挟むが対策の一つ。
Javaの場合はURLクラスを使ってURLの検証が可能。
Click Jacking
<iframe>
で他のページを埋め込んで誤クリックさせる。
意図しない埋め込まれ方をしないよう、HTTPヘッダで以下の制御を行う。
- X-Frame-Options
- Content-Security-Policy: frame-ancestors
一瞬悪意があるならヘッダを無視して埋め込まれてしまうのでは?と思ったが、
埋め込まれるかではなく、善意のユーザのブラウザ上でそれが描画されるかがポイントだと理解した。
Insecure Deserialization
📞😾<どうしてシリアイズデータをユーザ側に渡したんですか?
シリアライズデータは改竄されうるからJSON使おうね。
XXE攻撃
XML External Entity攻撃。なんでXEEじゃないんだと最初思った。
XMLがデータ構造を定義(DTD: Document Type Definition)できるのは基本情報でやった記憶があるが、定義中で外部リソースを読み込める仕様であるらしい。
そのためDirectory Traversalのような機密情報へのアクセスや、再帰参照によるDoS攻撃の恐れがある。
DTDを無効化して対策できる。
結論:JSON使おう
Directory Traversal
Javaの場合、Path#normalizeでキレイにできる。
String BASE = "/app/files/";
String fileName = getInput();
// Path#normalize によって /app/files/.././hoge は /app/hogeになる
Path filePath = Paths.get(BASE, fileName).normalize();
// パスがBASE以下であるかをPath#startsWithでチェック
boolean isValid = filePath.startsWith(BASE);
OS Command Injection
シェルに引数を渡すときに攻撃者が余計なコマンドをくっつけて実行させる攻撃。
JavaのRuntime.getRuntime().exec({"ls"});
ではシェルを呼び出さず、指定した実行ファイルを直接実行するので安全だが、.exec({"sh", "-c", "ls"})
のようにシェルに渡すのは危険。
シェルに慣れていなければ必然アプリでなんとかするので安心
SSRF
Server Side Request Forgery。Open Redirection、XXE攻撃、OS Command Injectionなどにより、外部公開されていないサーバにアクセスすること。
CSRF
Spring Securityを使う場合CSRFトークンを埋めこんでくれるらしい。
手動でやるなら都度UUIDで遷移の正当性確認。
メモ
-
Forgery:偽造(物)。 CSRF、SSRFのF。
-
(非Stored)XSSもOpen Redirectionも、攻撃者は変なリンク作ってるだけだから攻撃感ないなと思った。ユーザがいじれる値は信用しちゃだめということに加えて、リンクは攻撃者がいじった上でユーザに渡せるというイメージを膨らませておくのが重要そう。
-
重要な操作は確認画面入れるとユーザの意図に反した挙動を防げがち。
-
Springの@CookieValueアノテーションを知ったのでCookieが使えるようになった。もともとイメージはあったけど、改めてこれ勝手に送られてきてるのか...と思ったし、ClickJacking対策のオプションもだけどHTTPヘッダについて深堀りしたい。新人研修でSessionはやるけどそれが可能になってる仕組みについてはやらないんだよね。
-
JavaのURLクラスは「ポート番号が無い」も「ポート番号に-1を指定した」も-1になるらしい...(参考)。
-
JSONはセキュリティ上のメリット大きいんだなと思った。AjaxがxmlじゃなくJSON使うようになったのもそういうこと?
-
OS Command Injectionで、Javaのファイル操作使って安全にしようとして、Java Gold取ったことでファイルIO周りの知識が整理されてるのを実感した。