SQLインジェクション対策
午後問でSQLインジェクションに対する防御プログラミングの問題が出ていたのでまとめてみました。
- SQLインジェクションとは何か?
ユーザーの入力データをもとにSQL文を編集してDBにクエリを発行し、その結果を反映させるというwebページにおいて、不正なSQL文を入力することでDBを操作したり、DBに登録された情報を不正に取得、変更するといった攻撃手法です。XSS同様にユーザーの入力データのチェック不備から成立する可能性がりあます。
今回はjavaのソースを基にSQLインジェクションを成立させてしまうコードとそれを防ぐコードを簡単にまとめました。
String sqlString = "SELECT * FROM db_user WHERE username = '" + username + "' AND password = '" + pwd + "'"; Statement stmt = connection.createStatement(); ResultSet rs = stmt.executeQuery(sqlString);if (!rs.next()) { throw new SecurityException( "User name or password incorrect" ); }
これは脆弱性のあるコードを一部抜粋したものです。このコードは入力された文字列を結合してSQL文としてクエリしています。 例として、入力部分のusername pwd に 次の様な入力を与えたとします。
username = katsuya , pwd = ' OR 'A' = 'A
メジャーなSQLインジェクションです。上記のような入力の場合実行されるSQL文は以下のようになります。
SELECT * FROM db_user WHERE username = 'katsuya' AND password = '' OR 'A' = 'A'
入力したOR文があります。この入力によってパスワードは特に値を与えていないのですがその後ろにあるOR文の条件は常に真なので db_userのレコードが全て選択されることになります
恐ろしいです。しかし、しっかりと対策をすることで防ぐことはできます。以下が対策を施したソースです。
String sqlString = "select * from db_user where username=? and password=?"; PreparedStatement stmt = connection.prepareStatement(sqlString); stmt.setString(1, username); stmt.setString(2, pwd); ResultSet rs = stmt.executeQuery(); if (!rs.next()) { throw new SecurityException("User name or password incorrect"); }
これprepareStatementメソッドを使った対策です。これを使用することによってユーザーの入力は特別な文字列( $ ^ ' " 等)が含まれていても自動でエスケープ処理されてただの文字列として扱われます。
他の対策としては、そもそものRDBMSのアクセス権限を最小にするといったものがあります。
似たような攻撃としてはOSコマンドインジェクションやディレクトリバーサル攻撃が挙げられます。どちらもユーザーが悪意のあるスクリプトを送信して本来は権限のない行為を実行しようとするものです。
しかし、最近のwebアプリケーションフレームワークはデフォルトで対策されているものが殆どなので超個人用のアプリでもない限り実現できる攻撃ではないのかなと思っています。
SCの過去問ではセキュアプログラミングの題材として何回か出題実績があったのでまとめてみました。 今回はこのあたりで失礼します。
暇つぶしのプログラミング
今日は暇だったので CodeIQ で解いた問題について書いてみます。
どういう問題かというと…
2つの整数値N, Mが与えられます。 0からNまでの各整数(10進数)について、2進表記したときに1の数がM個になるものを数えてください。 たとえば、9を2進表記すると1001ですので、1の数は2ということになります。 【入力】 標準入力から、半角スペースで区切られた2つの整数値N(0≦N≦100000)、M(0≦M≦17)が与えられます。 【出力】 0からNまでの整数の中で、2進表記したときに1の数がM個あるものの個数を出力してください。
例としては、入力に 10 2 と与えたとしましょう。
その場合の出力は5になります なぜなら 0 から 10 までの数を全て2進数に変換してその中で1が二つ含まれるのは 「11, 101, 110, 1001, 1010」の5つだからです。
とまぁこんな感じなんですがこの問題言語に指定はありません。最初はCで書こうかなって思ったんですが2ビットのカウント方法を1から書かなければならなさそうなのでjavaの方がいいかな~と思いjavaにしました。
というわけでソースを張ります
import java.io.*; import java.util.Scanner; public class codeIQtest { public static void main(String args[]){ Scanner scan = new Scanner(System.in); int N = Integer.valueOf(scan.next()); int M = Integer.valueOf(scan.next()); if(0>N || 100000<N){System.out.println("error"); return;} if(M<0 || 17<M){System.out.println("error"); return;} bitCount(N,M); } static void bitCount(int N,int M){ int counter; int Tcounter=0; for(int i=0;i<=N;i++){ counter = Integer.bitCount(i); if(counter == M) Tcounter = Tcounter+1; } System.out.println(Tcounter); } }
なんでMarkdown上手く表示されないんだろう… コードが見づらい…
これで正解が貰えました。 で、上記のソースの最後らへんに counter = Intger.bitCount(i); という部分があるんですがこのbitCountメソッドがなんとint型の数字を渡すとその数字を2進数に変換し1の数をカウントしてくれるという便利なものです。 これのおかげで後は入力条件の設定とメソッドの定義、出力処理ぐらいだけで済みました。超便利ですね。
ちょっと調べてみた結果、RubyとかCだとbitCountっぽいやつは自作しなきゃなさそう? Cでは一応有名な美しいアルゴリズムとして存在してるっぽいですね 一応載せておきます
int numofbits3(int bits) { int num = 0; for( ; bits != 0 ; bits &= bits - 1 ){ num++ ; } return num; }
綺麗ですね… もう少し冗長なものになるのかと思ってましたがここまで簡潔に書けるとは…
では今日はここら辺で
また気が向いたらこういう暇つぶしについても書いてみようかなと思います。
情報セキュリティポリシ
情報セキュリティスペシャリストの過去問を解いていて、午前問題に関しては割と正答できるようになったと感じて6割も不可能ではないなと思っているんですが、午後問の長文問題全般をどう攻略するかが最近の悩みです。
さて、今回は情報セキュリティポリシについてです。
情報セキュリティポリシの概要
組織の情報資産を守るための方針や基準を明文化したものです。組織のリーダーによる明確な方針と、リスクアセスメント(前回記事参照)結果に基づいて対策基準が必要であると記されています。
基本方針
情報セキュリティに対する組織としての一貫した考え方を示すもので、目的、対象範囲、維持管理体制、義務、罰則などがあります。
情報セキュリティ対策基準
基本方針を実践し、適切な情報セキュリティレベルを維持・確保するための具体的な遵守事項や基準を記述しています。
セキュリティポリシの位置づけとしては企業の社訓、経営理念、就業規則といった既存の方針や規則などと何らかのかかわりをもつことは必至です。
企業としては有効性を高めるためにはその位置づけや、他の規則や規定との関係を明確にしておかなければならないのです。そうしなければ資産を守るためのポリシが他の規則と衝突してしまう可能性があるからです。
情報セキュリティポリシ策定・運用による効果
1.セキュリティレベルの向上
既にセキュリティ対策が施されていても、それぞれを総合的に管理・運用するための方針、知識がないため、十分な効果が得られていないというケースはよくあるらしいです。セキュリティポリシによって組織の求めるセキュリティレベルを明確にし、それを目指して問題箇所を改善していくことができます。あやふやなまま改善するより圧倒的に有効です。
2.セキュリティ対策の費用対効果の向上
リスクに応じた適切なセキュリティ対策を施すことで、限られた予算で最大限の効果を得ることが可能になります。セキュリティポリシを策定しないままだとどのリスクに対して、どれだけの費用をかけるかもわからずに対策することになるので下手をすれば大きな損益を被ることになりません。
2.対外的な信頼性の向上
セキュリティポリシを策定・実施することでよそから見たときの組織の信頼性を高めることができます。
ひとまずこんな感じでしょうか。最近の社会では企業の資産として 1、人 2、金 3、設備 4、情報 と言われるぐらい情報は価値を持っています。企業としてそれを守るのは当然ですが全部紙におこしてファイルに挟んで金庫で保管!なんてやってたらいつまでたっても終わりませんし引き出すときにも面倒くさいです。ほぼPCに情報を保管する現代において情報を守るための手法、基準、リスクの対応などは確実に必須となるものなんでしょう(働いてないのでわかりませんが…)。技術的な知識だけでなくこういった経営についてや倫理、法律的な知識も必要となるのが情報セキュリティという分野なので面白いですね。まだまだ知らないことが沢山あるのでもっと色々調べていきたいと思います。
逆に一番乏しいのは技術的な知識なのでそこをどうするかが今後の課題です… 誰か先生みたいな人いませんかね…
リスク対応
前回はリスクマネジメントについてかるーく触れたので今回はリスクマネジメントの中で実施するリスクアセスメント、その後に行うリスク対応について調べてみました。
- リスク対応の概要
リスクアセスメントでリスクを分析、評価しました。けどその後の対応が間違ってたら意味がない。
そのリスク対応については大きく分けて二つ、リスクコントロールとリスクファイナンスがあります。
- リスクコントロール
これは潜在的なリスクに対して、物理的対策、技術的対策、運用管理的対策によって、発生を防止したり、損失を低減させてりすることですね。 例としては機密データのあるデータセンターを免震構造にしたり、入退室の履歴をしっかり取ったりすることが挙げられるかも。
こっちはリスクを抑えるのではなく、リスクが顕在化して損失を負うこと前提でその時に備えて損失の補填や対応費用などの確保をしておくことらしい。損失を負うこと前提って考え方はなんとなくフェールセーフやフェールソフトを思い出しますね。
リスクはどれだけしっかりリスクコントロールしても顕在化の可能性を0にすることはできない。そのために資金面での対策を講じておくことも非常に重要らしいです。
具体例としては 保険を利用して不測事態発生時の対応費用を組織外に転嫁 不測事態発生時に備え、準備金・積立金などの名目で組織に対応費用を確保
難しいですね… ここら辺は実務を経験してる人でないと理解しずらいかもしれません。
さて、二つの対応を行いましたがそれでもリスクは残ります。こういったリスクの事を「残留リスク、残余リスク」なんて呼ぶそうです
じゃあ残りはどうするのか。難しいところですがその場合はリスクの強度や予算などとの兼ね合いによりあえて対処を行わないことがあります。それがリスクの受容です。リスクの受容については組織としての判断基準を予め明確に決めておかないといけません。
ちなみにこのリスク対応等諸々含むリスクマネジメントに関する規格は ISO 31000:2009/JIS Q 31000:2010 で定義されています。 気になる人は調べてみるといいかもしれません。
では今回はここら辺で失礼します
ドラクエのせいで暫く記事書くテンションにならなかったなんて言えない…
リスクマネジメント
ソフトウェアやサービスの開発、運用をしていく中でリスクというものは切っても切り離せないものだと浅学ながら自分では考えています。
そんなリスクを大きなフローの中で分析し、対応することが昨今では必須となっていますが今回はその中でリスクマネジメントについてまとめてみました。
- リスクマネジメント
リスクマネジメントには
2.リスク対応方法の洗い出し
3.リスク対応の実施
4.リスク及びリスク対応の洗い出し
の4つのプロセスがある。これらのプロセスは一過性のものではなく継続的に繰り返していく必要がある。
一つ一つ見ていくと、
①リスクアセスメント(リスクの分析、評価)
これは実際にその計画(運用や開発)の中にあるリスクが顕在化した場合もたらすものを対象としている。リスクマネジメントの対象となる組織や情報システムのどこに、どのように潜在しているのかを発見・確認し、その大きさを測定・評価する。
②リスク対応方法の洗い出し
リスクアセスメントの結果を受け、損失を最小限に抑える適切なリスク対応方法を洗い出す。
③リスク対応の実施 洗い出されたリスク対応と、 予算や組織などの兼ね合いによって、実際に実施するリスク対応策(大体セキュリティ対策?)を決定、実施する。ちなみに、この時決定されたリスク対応方法は情報セキュリティポリシにも確実に反映させる必要がある。
④リスク及びリスク対応方法の見直し
リスクそのもの及び、実施済みのリスク対応方法を定期的に見直し、必要に応じて改善することで、リスク対応の効果を維持する。
今日は眠いのでここまで。明日リスク対応についてまとめます
公開鍵暗号と共通鍵暗号
簡単に言うと暗号化と復号化を同じ鍵で行う方式。つまり送信者と受信者で一つのカギを使うので、別の通信相手の場合には別のカギを用意しなくてはいけません。代表的な共通鍵暗号方式としてAESがあります。
鍵の数は n(n-1)/2 です。
- 公開鍵暗号
公開鍵暗号は多対多のインターネットにおいて優れた暗号化方式ですが暗号化と復号化に共通鍵暗号のおよそ数千倍の時間がかかり、CPUにも負荷がかかります。
公開鍵暗号のカギは二つ存在し、秘密鍵と公開鍵にわかれます。サーバーなどが多数のクライアントと通信をしたい時、データを秘密鍵で暗号化して公開鍵を各クライアントに配ることで復号化してもらいます。この時データの暗号化は秘密鍵でしかできません。なので秘密鍵は絶対に秘匿しておく必要があります。
- RSAの安全性
暗号技術分野の知識ですがRSAの安全性の根拠は桁数の大きな整数を素因数分解するのが困難だということを根拠にしています。
例として、 1. 二つの素数を挙げる a=523,b=613
数字の桁数が大きくなればなるほど素因数分解は困難になります。つまり数字の桁数がそのまま鍵の安全強度に繋がります。実際のRSAではもとの素数に150~300以上もの桁の数字を使用しているそうです。
暗号技術についての雑記
そもそも暗号ってなんぞや?という時が自分にあったのでまとめておこうかなと思います
一番原始的とも言える暗号を例に紹介します。それはシーザー暗号です。
シーザー暗号は簡単に言うとアルファベットをずらすことによって文字列を暗号化します
・例 Hello ⇒ ifmmp 例は1文字ずらしただけです。それでも平文の原型を残さず別の文字列にすることができました。
では例の場合のカギは? それは 1 です。
この暗号は確かポケモンBW2の海底遺跡か何かでも使われていたと思います。
この他にもデータの場合は全て2進数になおして鍵とXORを演算することで暗号化するというような方式もあります
暗号技術の書籍は結構あって面白いので是非興味があったら読んでみることをお勧めします
そもそもどうして暗号化のアルゴリズムと鍵を分ける必要があるのか。それは毎回データを暗号化するのに新しいアルゴリズムを生み出すのはめんどくさい。何回も同じの繰り返して使いたい。だけど同じアルゴリズムを使っていると解読されるリスクが高くなってしまう。だから、暗号化アルゴリズムに「変更可能な部分」を残しておいて通信ごとにそこを変えればなんとかなるだろう。その変更可能な部分というのが鍵のことですね。 先人たちの偉大な努力の結晶ですね。
もし今度時間があったら色々な暗号化アルゴリズムについてもまとめてみようかなと思います
なんというか暗号化アルゴリズムについての方がつい熱が入ってしまいました。次回は何についてまとめておきましょうか…
夏休みにも入ったのでじっくり勉強しながら考えようと思います。
では今日はここら辺で筆をおかせていただきます
ディジタル署名とディジタル証明書の違いって?
今回は情報セキュリティスペシャリストの試験勉強中にディジタル証明書の問題で「ん?」っとなったので書いてみました
ディジタル署名って何?
ディジタル署名っていうのはいわゆる現実世界で言う印鑑。送られてきたデータが本当にその人(サーバとか)から送られてきたと証明するための技術。
いわゆるデータの 正当性 (完全性とごっちゃになることがある)を保証するためのものなんですね。
またディジタル署名は署名を作成できる鍵(公開鍵暗号のうちの秘密鍵)は送信者のみが保持しています。これが漏えいすると色々なところで鍵が勝手につくられちゃって大変!
その他にも「このデータは私が送ったよ!」ということを証明するので後で「私そんなデータ送ってないよ!あなたの思い違いでしょ!」といったことにならないような 否認防止 の役割もあります。
仕組みに関してはハッシュ関数と公開鍵暗号方式を組み合わせて電子的な署名を作成してます。ここでは面倒なので省きます。 色々としっかり者のディジタル署名ですがこの署名自体が偽造されたものだったら?データを正しいと証明はできますがディジタル署名自体が自信の正当性を証明することはありません。なのでここで登場するのがディジタル証明書です。
ディジタル証明書とは? 第三者機関である「認証局」によって発行される電子式の身分証明書です。SSLサーバー証明書などとも呼ばれます。
通信相手が送ってきた証明書を認証局の公開鍵で復号化することで通信相手の身元を確認することができます。
証明する内容としては認証局の情報、通信相手が発行した公開鍵、暗号化されたデジタル署名等があります。
ディジタル証明書はITU-T勧告の X.509 で定義されています。
しかし、悪意ある攻撃者は認証局になりすまして証明書を発行することがあります。それを防ぐために証明書の利用者情報を登録するRA(登録局)や 証明書の有効性を検証するVA(証明書有効性検証局)といったものがあります。
簡単にディジタル証明書の発行の手続きをまとめてみました。登場人物はwebサーバーとクライアントと認証局です。
- webサーバ「webサーバ側で公開鍵と秘密鍵を作成するよ!」
- webサーバ「公開鍵が正しいことを証明するための証明書が欲しい!じゃあ公開鍵とその他諸々の証明書送るから認証局にディジタル証明書発行してもらおう!」
- 認証局「ふむ。確かにwebサーバが発行したものだな(公開鍵と所有者情報を参照)。よし、秘密鍵で暗号化した署名付きでディジタル証明書にしてやるぞい」
- webサーバは証明書を受け取りインストールする
- クライアント「webサーバさん!接続要求です!」
- webサーバ「じゃあこれうちの証明書ね。保存しといてね」
- クライアント「証明書が届いたよ。じゃあこの認証局さんの公開鍵でデジタル署名部分をちょちょいと復号化して... よしハッシュ結果が同じだね!これは正しい署名だ!」
と多分大体こんな感じです。暗号化のところやCRLうんたらのところは複雑になるのですっ飛ばしました。
少し長くなってしまいましたが今回はここらへんで終わっておこうと思います。次は公開鍵暗号とかのまとめかな?
勉強中なので間違ったことを書いてあることが当然あると思うのでその際はご指摘お願いします