- PMMプロダクトマーケティング
- ブリッジエンジニア
- ★東京・大阪/CS/MG
- 他77件の職種
-
開発
- ブリッジエンジニア
- オフショアPJマネージャー
- ブリッジSE/オフショア開発
- エンジニアオープンポジション
- Webエンジニア(大阪PHP)
- フロントエンドエンジニア
- Javaエンジニア(楽楽明細)
- ブリッジSE(大阪)
- PM(楽楽シリーズ)
- テックリード(大阪/PHP)
- フロントエンドマネージャー候補
- プロジェクトマネージャー
- エンジニアリングマネージャ
- AI導入エンジニア
- プロダクト開発部長
- Webエンジニア
- Webエンジニア
- フロントエンド(リーダー)
- モバイルエンジニア
- Android/iOSアプリ
- 社内SE(大阪/セキュリティ)
- インフラエンジニア
- インフラエンジニア/マネージャ
- インフラエンジニア
- 社内SE(データエンジニア)
- 戦略企画・データマネジメント
- QAリーダー/マネージャー
- システム企画
- 品質管理/技術支援チーム
- AI/機械学習エンジニア
- データ基盤エンジニア
- エンジニアリング
- UIデザイナー(リーダー)
- コーポレートデザイナー
- UIデザイナー
-
ビジネス
- PMMプロダクトマーケティング
- プロダクトマネージャー(AI)
- 導入支援/導入コンサルタント
- 開発マネージャー
- プロダクトマネージャー
- PdM(楽楽シリーズ)
- プロジェクトマネージャ(大阪)
- プロダクトセキュリティ
- 技術推進部長
- IR
- 総務
- 労務
- データマネジメント・マーケ戦略
- 経営企画
- コーポレート広報
- 内部監査(業務監査)
- フィールドセールス
- ITセールス(広島)
- フィールドセールス(法人営業)
- 営業企画(イネーブルメント)
- ITセールス(名古屋)
- セールスマネージャー
- 法人営業/カスタマーサクセス
- フィールドセールス(名古屋)
- 法人営業
- フィールドセールス(東京)
- 営業企画(戦略立案)
- ITセールス
- ビジネスオープン
- ITセールス経験者
- オフラインマーケティング
- オンラインマーケティング
- 製品企画/プロダクトマーケ
- 製品企画/法要件(楽楽明細)
- ブランド企画
- 営業推進リーダー(楽楽精算)
- マーケティングリーダー
- CSマーケティング
- マーケティング担当
- ブランド企画・ブランディング
- その他
はじめに
記事をご覧のみなさん、はじめまして。エンジニアのkasuke18と申します。ブラウザは圧倒的にChrome派です。
今回の記事では私が作ってしまった2大脆弱性のXSSとSQLインジェクションについて、ソース例を踏まえて原因を追及します。なお、ソースの言語についてはPHPを利用しています。
この記事が初めてのブログ投稿ですので、「この書き方はヘンだな」と感じるときがあると思いますが、そこは温かい目で見守ってくださると幸いです。。
もくじ
この記事の想定する読者
新人エンジニアの方々
「2大脆弱性は知ってるけど、具体的にダメな実装例が実感できない」という方が読まれた際に、理解の手助けとなれば幸いです。
つきましては「XSSとは」「SQLインジェクションとは」ということは今回はさらっと流します。それらをお探しの方は他のサイトをご覧ください。IPAのサイトは国の機関なので信頼できると思われます。
「こんなパターンで脆弱性が発生するのか」や「ここの実装するときは気を付けないと!」などと感じていただくのが目的です。とはいっても実際のソースは大人の事情で載せられないので、実際のソースとは少しズレてしまいますが、そこはご容赦ください。。
XSS
XSSとは
いきなりですが、新人エンジニアの私から見てもわかりやすくまとまっていると感じた記事があるので引用します。「XSSとは何か」ということをお探しの方はこちらをご確認ください。
XSS(Cross Site Scripting)は、あるWebページにアクセスした標的のブラウザ上で、攻撃者が任意のコードを実行し得るバグ、あるいはそれを用いた攻撃手法のこと
XSSが発生したソース例
XSSが発生した原因などは次で説明するとして、まずはXSSが発生してしまったソース例を示します。
新人エンジニアの方々
「2大脆弱性は知ってるけど、具体的にダメな実装例が実感できない」という方が読まれた際に、理解の手助けとなれば幸いです。
つきましては「XSSとは」「SQLインジェクションとは」ということは今回はさらっと流します。それらをお探しの方は他のサイトをご覧ください。IPAのサイトは国の機関なので信頼できると思われます。
「こんなパターンで脆弱性が発生するのか」や「ここの実装するときは気を付けないと!」などと感じていただくのが目的です。とはいっても実際のソースは大人の事情で載せられないので、実際のソースとは少しズレてしまいますが、そこはご容赦ください。。
XSS
XSSとは
いきなりですが、新人エンジニアの私から見てもわかりやすくまとまっていると感じた記事があるので引用します。「XSSとは何か」ということをお探しの方はこちらをご確認ください。
XSS(Cross Site Scripting)は、あるWebページにアクセスした標的のブラウザ上で、攻撃者が任意のコードを実行し得るバグ、あるいはそれを用いた攻撃手法のこと
XSSが発生したソース例
XSSが発生した原因などは次で説明するとして、まずはXSSが発生してしまったソース例を示します。
この時実現したかったことは、フォームから入力値を受け取り、その入力値をパラメータにセットすることです。
なぜXSSが発生したのか
ソース例を見ていただければわかるかと思いますが、直接の原因は単純にエスケープが漏れていたことです。言い方は悪いですが半ば思考停止気味に「とりあえずエスケープしておこう」で防ぐことはできたミスです。
ではなぜエスケープが漏れてしまったのかと言い訳をしますと、単純に注意不足でエスケープをしなかったことに加えて、「入力値検証をしっかりと行っているから大丈夫」という無意識のうちに安心感を持っていたことです。
むしろ今回の件では見事にその意識の甘さが脆弱性を生み出しました。どういうことかと申しますと、具体的には以下の流れで発生していました。
今回XSSを発生させてしまったのは<input>
のtype="hidden"
パラメータでした。これは通常の画面操作からは直接変更できませんが、developerツールではできてしまいます。
それでは好き放題に変更された入力値を受け入れてしまうので、普通は入力値検証を行い、決められた値以外は許可しないようにします。
また、ユーザの使いやすさを考えると、エラー時に戻った画面ですでに入力されていた内容をセットしておくことも必要です。(入力内容を1か所間違えただけで全部やり直しというのはあまりに不親切ですので。)
今回の件でもそれに乗っ取り入力値検証を行い、数値以外は許可しないようにしていました。また、エラー時に入力値をセットするということもしていました。XSSを発生させる原因となった処理はこの「エラー時に入力値をセットする」という処理で、この入力値を出力する際にエスケープしなかったためにXSSが発生しました。
実施した対処
今回の件ではエスケープが漏れていたことが原因なので、エスケープを実施して対処しました。PHPではhtmlspecialchars()
という関数を利用することでエスケープできます。
以下が修正後のソース例となります。
この件を通して感じたこと
このXSS脆弱性は被害という意味ではほぼ問題ないと考えています。その理由は、
以上の2点から被害はほぼないと考えました。
しかし、エスケープが漏れてしまっていたことは問題なので、今後は忘れないように十分に注意します。
SQLインジェクション
XSS同様にSQLインジェクションも詳しい説明は省略させていただきます。詳しくはIPAの資料をご覧ください。
SQLインジェクションが発生したソース例
SQLインジェクションが発生した原因などは次で説明するとして、まずはSQLインジェクションが発生してしまったソース例を示します。
この時実現したかったことは、フォームから入力値を受け取り、その入力値によりDB検索を行うことです。また、フォームで入力されるパラメータは毎回すべて入力されるわけではないので、SQLのWHERE句は動的に組み立てる必要があります。
なぜSQLインジェクションが発生したのか
上記のソース例を見ていただければ一目でわかりますが、パラメータid
は正しくプリペアードステートメントが使用されていますが、パラメータstatus
は単なる文字列結合となってしまっています。このことがSQLインジェクションを発生させていました。
また間接的な原因として、パラメータstatus
についての入力値検証が全く行われていなかったことがあります。ただの言い訳でしかありませんが、入力値検証を行わなかった理由はパラメータstatus
の入力方法がプルダウンメニューであり、「プルダウンならプログラムが用意した値以外は送られてこない」という誤った認識をもってしまっていたからです。すでに上記XSSの項でも述べていますが、Chromeなどのdeveloperツールを利用すれば簡単に値を変更できることを失念していました。
実施した対処
理想論でいえば、本来は保険的な対策でしかない入力値検証だけで対処するのではなく、適切にプリペアードステートメントを利用することが必要です。しかし今回の件では諸事情により根本的な原因であるSQLの組み立て部分を変更することはできませんでした。よって入力値検証で数値以外は許容しないようにして対処しました。
XSSと同様、修正後のソース例を書こうと考えましたが、大人の事情で書くことができません。 代わりに、理想的な対処法であるプリペアードステートメントを適切に利用して対処したソース例を以下に示しますので、ご容赦ください。
この件を通して感じたこと
今回の件では「プルダウンなら入力値検証を行わくてもよい」という完全に誤った認識が露呈しました。プルダウンだけではなく、XSSの項でも挙げている<input>
のtype="hidden"
パラメータも同様で、「通常の画面操作から直接変更できないパラメータこそ入力値検証が必要」と感じました。
おわりに
以上が、私が実装してしまった2大脆弱性です。この記事の目的の通り、「こんなパターンで脆弱性が発生するのか」と把握していただけたでしょうか。実際のソースが載せられないため、正直よくあるソース例になってしまった感が否めません。。
ちなみにと言っては何ですが、今回ご紹介した脆弱性はどちらも単体テストで発見・修正しているので、大事には至っておりません。
最後までお読みいただきありがとうございました。