セキュリティコードレビューとは
セキュリティコードレビューとは、他の人が書いたコードを、安全の目で読んで、弱点を見つけることです。機能のテストが通るコードにも弱点は残るので、読んで見つける人が要ります。
履修登録サービスに、新しい変更が出されました。画面は動いています。でも、この変更を、そのまま取り込んでよいでしょうか。
このレッスンのゴール
メモ
チェックリストを使って差分を読み、危ない行に重大度を付けて指摘できる。
今日のキーワード
| ことば | いみ | れい |
|---|---|---|
| コードレビュー | 書いた人とは別の人が、コードを読んで確かめることです。 | |
| 差分 | 変更前と変更後の違いだけを並べたものです。 | + 増えた行 |
| チェックリスト | 見落とさないために、確かめる項目を並べた表です。 | |
| 重大度 | 見つけた問題が、どれだけ急ぎで危ないかの段階です。 | |
| 指摘 | レビューで書く、問題と直し方の連絡です。 |
学生が入力するセルは、このプレビューでは空白です。
たった1つのルール
注意
見てよいのは、自分専用のラボのコピーだけです。このラボは、わざと弱く作った店で、インターネットにはつながっていません。許可のない他人のシステムに同じことをするのは、不正アクセス禁止法に触れる犯罪です。
チェックリストで読めば見落としが減る
コードを何となく読むと、動くかどうかばかり見てしまいます。そこで チェックリスト(checklist)を使います。確かめる項目を決めておき、1つずつ、コードに問いかけます。
これまでの5回に出てきた弱点が、そのまま項目になります。
セキュリティの確認項目
| 項目 | 問うこと | 危ない印 |
|---|---|---|
| 入力 | 使う前に検証しているか | 検証なしで計算や保存に使う |
| SQL | 値はパラメータで渡しているか | 文を + や f文字列でつなぐ |
| 秘密 | 鍵やパスワードがコードにないか | password = "..." と直に書く |
| 実行 | 入力を命令として動かしていないか | eval( や os.system( を使う |
| 認証 | パスワードをソルト付きの遅いハッシュにしているか | 平文や md5( を使う |
| 通信 | 相手の証明を確かめているか | verify=False と書く |
| エラー | 内部の作りを見せていないか | 例外の文字をそのまま返す |
学生が入力するセルは、このプレビューでは空白です。
差分は増えた行と消えた行を読む
差分(diff)は、変更前と変更後の違いだけを並べたものです。- で始まる行は消えた行、+ で始まる行は増えた行です。
増えた行を中心に読みます。同時に、消えた行も見ます。消えた行が守りだったら、その変更は守りを外しています。
例: 守りを外す差分
| 差分の行 | 印 | 読んでわかること |
|---|---|---|
| rows = db.execute("... WHERE id = ?", (sid,)) | - 消えた | パラメータで渡す、守りの行だった |
| rows = db.execute("... WHERE id = " + sid) | + 増えた | 値を連結していて、守りが外れた |
| print("debug", password) | + 増えた | 秘密を記録に出してしまう |
学生が入力するセルは、このプレビューでは空白です。
指摘は行、問題、直し方を書く
指摘には、どの行か、何が危ないか、どう直すかの3つを書きます。人ではなく、コードの話をします。
見つけた問題には 重大度(severity)を付けます。攻撃されやすいか、被害が大きいかで決めて、急ぐものから直します。
重大度の付け方の例
| 重大度 | 例 | 直す時期 |
|---|---|---|
| 高 | 値を連結したSQL文。認証なしで全員のデータが読める | 取り込む前に必ず |
| 中 | エラーに内部の作りが出る | 今回か、次の変更で |
| 低 | コメントに古い担当者の名前が残る | 手が空いたとき |
学生が入力するセルは、このプレビューでは空白です。
店のプログラムで、検索を数える
レビューする人は、最初に検索で、危なそうな場所の数を数えます。ラボを起動して、店のプログラムに3つの検索をかけましょう。どれも数を見るだけです。
1つ目は、データベースを動かす行の数です。2つ目は、入力を命令として動かす eval( の数です。3つ目は、エラーを受ける所の数です。
データベースを動かす行
docker exec app grep -c execute /tmp/app/app.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
入力を命令にする eval(
docker exec app grep -c "eval(" /tmp/app/app.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
エラーを受ける所
docker exec app grep -c except /tmp/app/app.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3つの答えを読む
ラボを変えていなければ、6、0、1 と表示します。execute を含む行は6つあるので、6か所を読めばよいとわかります。eval( は0なので、この項目は心配が要りません。
数は、読む場所を絞る道具です。数が0でも、別の書き方が隠れていないかは、人が読んで確かめます。
よくある間違い
注意
「検索で何も出なかったから、安全だ」と考える人がいます。それは違います。検索は、決まった書き方しか見つけられません。文を変数に分けて作れば、検索をすり抜けます。検索で絞り、最後は人が読みます。