狠狠撸
Submit Search
PyCon APAC 2013 Web Secure Coding
?
1 like
?
2,058 views
Gouji Ochiai
Follow
Basics of Web Secure Coding on Python
Read less
Read more
1 of 81
Download now
Download to read offline
More Related Content
PyCon APAC 2013 Web Secure Coding
1.
Webセキュア コーディングの基本 on 2013-09-15 13:00-13:50JST at
PyCON APAC 2013 Room A0765 (Ja2) by OCHIAI, Gouji (@gjo)
2.
Abstract ? セキュアコーディングとは何か? ? Webシステムにおけるセキュリティ ?
コード解説中心 ? 基本的な内容しかやりません ? 「お前が言うな」は重々承知
3.
お前誰よ? ? 落合 豪史 @gjo ?
一応職業プログラマー セキュリティの専門家 とかではないです ? twitter.com/gjo github.com/gjo
4.
本セッションおよび本稿の内 容は私個人の見解であり、私 の所属する企業、団体等とは 一切の関わりはありません。
5.
TheYear of Python
6.
Year of the
Dragon
7.
心を入れ替えるよ その方法を教えてくれ
8.
セキュアコーディングとは 何か? ? 脆弱性に対して堅固な コーディング ? 脆弱性? ?
堅固? http://www.?ickr.com/photos/nene9/4444657449/
9.
セキュアな状態? ? 一般的にセキュリティ は非機能要件 ? 「セキュリティが保た れていること」 ?
実装に依存する要件 ? 実装に依存しない要件 http://www.?ickr.com/photos/jermainejustice/3352100979/
10.
実装に依存しない セキュリティ要件 ? 「必要でない情報」を ? 「必要でない対象」に ?
「流通しない」
11.
実装に依存しない セキュリティ要件 (Cont.) ? 「必要な情報」を ?
「必要な対象」に ? 「流通する」 ? 一般的な機能要件の逆
12.
相互作用を持たないアクターに ユースケースが提供されないこと
13.
情報?対象?流通? ? 概念データモデリングの段階である程度明らかに なっているはず ? システムの外側に何をみせるか? ?
プログラムは何を永続化するか? ? 平文のパスワードとか ? クレジットカードのセキュリティコードとか
14.
実装に依存する セキュリティ要件 ? 攻撃手法が刻々編み出 される ? 既知の攻撃方法につい て対処されている、と いうことしか証明でき ない http://www.?ickr.com/photos/danorth1/315489224/
15.
脆弱性は時系列上で 固定ではない
16.
堅固? ? 現時点で既知の脆弱性が存在しない、 ではセキュアコーディング足り得ない ? 脆弱性のあるコードが存在しないこと が自明な状態であることが、容易に測 定出来ること ?
考えたら负け
17.
考えたら负け Don’t Think...Feel!
18.
考えたら负け ? 脆弱性有無の計測は何度も行われるこ とになる ? その都度、考えなければ脆弱性有無を 判定できないものは「堅固」ではない
19.
安全性を型に嵌める いちいち考えないために
20.
このコードは セキュアですか? https://gist.github.com/gjo/6473557
21.
--- is_this_safe.py2013-09-14 17:42:19.000000000
+0900 +++ is_this_safe2.py 2013-09-13 21:07:16.000000000 +0900 @@ -40,8 +40,12 @@ sql = 'SELECT {} FROM page'.format(','.join(COLUMNS)) params = [] if None not in (field, value): + if field not in COLUMNS: + raise NotFound(field) sql += ' WHERE {} LIKE ?'.format(field) - params.append(value) + params.append('%{}%'.format( + value.replace(r'', r').replace(r'%', r'%').replace(r'_', r'_')) + ) cursor = db.cursor() cursor.execute(sql, params) pages = [dict(zip(COLUMNS, row)) for row in cursor] @@ -62,7 +66,7 @@ <tr><td>No maches. {% endfor %} </table> -""") +""", autoescape=True) return template.render(context) if __name__ == '__main__': - app.run(debug=True) + app.run()
22.
プログラム内部に 起因する脆弱性 ? メモリ管理、ランタイム関係 ? バッファオーバーフロー ?
不正なシステム特権取得など ? 自爆 ? デバッグモード、メンテナンスモード ? エラーメッセージ
23.
プログラムの外部 インタフェースに起因する脆弱性 ? HTTP Request,
HTTP Response ? Database ? MessageQueue, Cache, SMTP ? ...etc
24.
古式ゆかしき何とやら ? SQL Injection ?
Directory Traversal OS Command Injection ? Response Header Injection Response Header Spliting E-mail Header Injection
25.
SQL Injection def some_view(req): sql
= 'SELECT * FROM {}'.format( req.GET['some_param'], ) cursor = req.db.cursor() cursor.execute(sql) for row in cursor: some_action(row)
26.
Directory Traversal def some_view(req,
filename): path = os.path.join(ROOT, filename) content = open(path).read() resp = Response( content=content, content_type='', ) return resp
27.
OS Command Injection def
some_view(req, cmdopt): resp = Response(content_type='') subprocess.call( 'some_command ' + cmdopt, shell=True, stdout=resp, stderr=subprocess.STDOUT, ) return resp
28.
Response Header Injection Response
Header Spliting HTTP/1.0 200 OK Content-Type: text/html Date: Sun, 15 Sep 2013 04:00:00 GMT Set-Cookie: HOGEHOGE; expires=Sun, 15-Jul-2013 15:00:00 GMT Connection: Close <html> ... </html>
29.
E-Mail Header Injection Date:
Sun, 15 Sep 2013 04:00:00 GMT From: "FOO" <foo@example.org> To: "BAR" <bar@example.org> Subject: Hello BAR: Thank you for your registration Hi all, foo bar baz .
30.
共通する危険性 ? テキストベースのプロトコル ? 構造が存在する ?
構造を実現するためにメタキャラクタが 存在する ? メタキャラクタを使用することで、 誤動作を誘発する
31.
解法 ? 入力のバリデーション ? 出力のエスケープ
32.
入力のバリデーション ? "すべての"入力を検査すべき ? QueryString,
FormDataはライブラリが 充実している ? それゆえPATH_INFOを忘れがち ? Cookie他ヘッダーも忘れがち
33.
出力のエスケープ ? 出力先毎に異なるエスケープルール ? HTTPレスポンス ?
ヘッダー: Cookie, Content-Type, Location etc... ? 本文: HTML, JSON/JSONP, CSV, etc... ? インタフェース ? 永続化等: データベース, ファイルシステム, キャッシュ ? 外部接続: SMTP,Web-API Request, etc...
34.
なぜ両方必要か? AppINPUT OUTPUTValidate Escape 入力をAppで使用できる形式に (Byte
strem to Python type) OUTPUTをプロトコルに合わせる (Python type to Byte strem)
35.
つまらない结论を
36.
フレームワークの ルールに従って コーディング しましょう
37.
なぜ? ? ひとつの問題を解決する手法は ひとつであるべき ? 同じことを何度も書かない
38.
どこかで見たような ?Zen of Python ?DRY原則
39.
チュートリアルの罠 ? https://gist.github.com/gjo/6558690 ? https://gist.github.com/gjo/6558691
40.
# -*- coding:
utf-8 -*- # http://flask.pocoo.org/docs/quickstart/#a-minimal-application # から # http://flask.pocoo.org/docs/quickstart/#variable-rules # までを写経していくと from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Index Page' @app.route('/hello') def hello(): return 'Hello World' @app.route('/user/<username>') def show_user_profile(username): # show the user profile for that user return 'User %s' % username if __name__ == '__main__': app.run()
41.
# -*- coding:
utf-8 -*- # http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/ # から抜粋 from wsgiref.simple_server import make_server from pyramid.config import Configurator from pyramid.response import Response def hello_world(request): return Response('Hello %(name)s!' % request.matchdict) if __name__ == '__main__': config = Configurator() config.add_route('hello', '/hello/{name}') config.add_view(hello_world, route_name='hello') app = config.make_wsgi_app() server = make_server('0.0.0.0', 8080, app) server.serve_forever()
42.
フレームワークの選択 ? 必要な外部インタフェースが実装され ているか? ? フレームワークへのアドオン追加 (新規作成
or グルーコードのみ作成) ? 個別のコードでバリデートやエスケー プを実装しない
43.
では本题
44.
Against SQL Injection ?
SQLを動的に組み立てるな ORM使え ? どうしても必要であれば、置換箇所は完 全一致で確認して、特殊文字を追い出せ ? Prepared Statementの場合も、値の箇所 で評価される特殊文字はハンドルしろ
45.
SQL LIKE or
REGEX # LIKEのエスケープはORMに任せる query.filter(MyModel.myfield.endswith( myparam, )) # REGEXのエスケープはまともに書ける # レベルを超えてしまう。。。
46.
Against Directory Traversal def safe_path(*args): return
os.path.join( [PRE_DEFINED_ROOT] + [os.path.basename(p) for p in args]) def some_view(req, module_, file_): path = safe_path(module_, file_)
47.
Response Header Injection Response
Header Spliting ? WSGIサーバーでのResponseHeaderの扱 いは単なるByte (!Unicode) http://www.python.org/dev/peps/pep-3333/#the-start-response-callable http://www.python.org/dev/peps/pep-3333/#unicode-issues
48.
? フレームワークごとで動作が違う ? django
(convert) https://docs.djangoproject.com/en/1.5/ref/request-response/#setting-headers ? ?ask (Exception on NL) http://?ask.pocoo.org/docs/quickstart/#about-responses ? pyramid (Exception on NL in Key) http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/api/ response.html#pyramid.response.Response.headers
49.
? Cookieはたいてい特別扱いだが、動作そ のものは、通常のヘッダの場合とほぼ同 じ ? django https://docs.djangoproject.com/en/1.5/ref/request-response/#django.http.HttpResponse.set_cookie ?
?ask http://?ask.pocoo.org/docs/quickstart/#cookies ? pyramid http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/api/ response.html#pyramid.response.Response.set_cookie
50.
E-mail Header Injection ?
標準ライブラリemailでも問題なくエス ケープを捌ける http://docs.python.jp/2/library/email.header.html#email.header.Header
51.
(おまけ) 流通しない情報は 取得しない
52.
Script Injection 大事なものを忘れていないかい?
53.
Script Injection <html> {{ unchecked_var|safe
}} </html>
54.
Script Injection <script> var x
= {{ unchecked }}; </script>
55.
Script Injection <style> .some-class { color:
{{ unchecked }}; } </style>
56.
Script Injection <script src=/slideshow/pycon-apac-2013-web-secure-coding/26201565/"{{ unchecked
}}"> </script>
57.
スクリプト実行が問題にな るのは何故か ? DOMを操作できる ? 新しくHTTP
Requestを発生させられる ? iframe, img, link, script ? イベントを発生させられる ? a.click, form.submit
58.
Some Server Attack
Servers Browser Some Document Attack Documents
59.
何が問題か ? 同意していないリクエストが送信され る ? パーソナライズされている情報が外部 に送信される
60.
問題が複雑になってしまう 背景 ? クライアントはサーバーを信用してはならない ? クライアントはサーバーを信用せざるを得ない ?
サーバーはクライアントを信用してはならない ? サーバーはクライアントを信用せざるを得ない
61.
クライアントはサーバーを 信用してはならない ? 正しいサーバーに接続しているのか ? サーバーに送信した情報は妥当に取り 扱われているのか ?
サーバーから受信した情報は信用に足 りるのか?
62.
クライアントはサーバーを 信用せざるを得ない ? ひとまず正しいサーバーに接続してい ると仮定するに足る手法を使う ? ひとまずプライバシーポリシー等のデ ータハンドリングを信じる ?
ひとまずレスポンスは正しいと信じる
63.
サーバーはクライアントを 信用してはならない ? 接続元クライアントが正しいユーザー であるか見分けることは困難 ? クライアントから受信した情報が妥当 であるか保証できない ?
クライアントに送信した情報が適切に 扱われるか保証できない
64.
サーバーはクライアントを 信用せざるを得ない ? ひとまず接続元が悪意あるユーザーでない ことを証明するに足るチェックを行う ? ひとまずクライアントから受信した入力に 虚偽はないと信じるに足るチェックを行う ?
ひとまずレスポンスデータが想定しない外 部に流出していないことを信じる
65.
送信してしまったデータの来 方行末を保証するものはない ? クライアントはサーバーのセキュリテ ィが保たれていることを信じるしかな い ? サーバーはクライアントのセキュリテ ィが保たれていることを信じるしかな い
66.
Same Origin Policy The
Great Wall
67.
Same Origin Policy ?
“scheme://host:port” の組み合わせが一致 するものを信じる ? Ajax Requestの範囲を制限する ? (類似の話題: 1st-party Cookie)
68.
[横道] Cookie ? 適切な範囲のCookieか domain,
path, secure, httpOnly, expire ? (セッション値がhttpOnlyでないのは...) ? 3rd-Party Cookie ? DNT, EU Cookie法
69.
Browsing Context ? (超省略形)
JavaScriptが、どのページで動 作するか ? 通常は表示しているページ ? script要素で読み込んだ外部Originの JavaScriptも、表示しているページの Contextで動作する
70.
Browsing Context (Cont.) ? iframe配下のdocumentは別のContext ?
Context間でのデータ流通にもSame Origin Policyが適用される
71.
本当に信じていいの? ? Ajax Requestにしか作用しない ?
iframe, img, link, script要素の挿入による Requestは送信される ? hostsファイル汚染/DNS汚染 ? 中間のネットワーク汚染 [New!]
72.
[横道] Content Security Policy ?
HTTP Response Headerで指定 ? サーバーが返却するリソースに何を使 えるかを厳密に指定できる ? 対応ブラウザーでないと効果なし (Firefox-23, Chrome-25, IE-10 (experimental))
73.
モダンな何とやら ? XSS (cross
site scripting) ? CSRF (cross site request forgery) ? Click-jacking ? Mitigation, BEAST, CRIME, BREACH
74.
XSS ? Script injection等によって攻撃用のJavaScriptをscript 要素で挿入する ?
挿入手段による多くのバリエーション ? HTTP Response Header Spliting ? Response Content-Type誤認バグの利用 ? script要素の代わりにimg要素やlink要素を利用 ? とにかく意図しないScript実行を抑止するしかない
75.
CSRF ? 直接POST Requestを送りつける ?
通常はXSSとの併用で踏み台ページを経由する ? すべてのFormにtokenパラメータを付与し、同 時にCookieやSessionでもtokenを保持してPOST 受付時に、外部から割り込んだPOSTを抑止す る
76.
Click-jacking ? iframe等を利用して攻撃対象ページを操作する ? 通常はSame
Origin Policyによって別Contextの Documentは操作できない ? 攻撃対象ページにXSS脆弱性があると、踏み台 ページのSameOriginでiframeが作成されやりた い放題に
77.
BEAST, CRIME, BREACH ?
SSL保護下にあるデータを総当り的な計 算を使用して盗む ? ルーター等でのパケット観測が必要 (カンファレンスの無線LANとか) ? 総当り的計算を行うためのRequestを XSSに生成する
78.
モダンな何とやら (再訪) ? モダンな攻撃の多くはXSSとの組み合わせ ?
HTTP Response以外のインタフェースへ のエスケープは多くの場合対処済み ? HTTP Response以外では攻撃するための シーケンスが長くなりがち ? 今更SQL injectionとか恥ずかしいだけ
79.
まとめ ? 日々新しい攻撃方法を考えている人がいます ? 多くは既知の攻撃方法の巧妙な組み合わせ にエッセンスを加えたものです ?
セキュアであるということは、時系列にお けるスナップショットです ? よって何度も確認するハメになります
80.
間違えようのないやり方が ひとつだけあるのがいいね ― Zen of
Python
81.
EOF
Download