10最も一般的なWebセキュリティの脆弱性
公開: 2022-03-11あまりにも多くの企業にとって、セキュリティ違反が発生して初めて、Webセキュリティのベストプラクティスが優先されます。 ITセキュリティの専門家として働いている間、多くのプログラマーにとってWeb開発のセキュリティ問題の世界がいかに曖昧であるかを何度も目にしました。
Webセキュリティの脅威に対する効果的なアプローチは、定義上、予防的かつ防御的でなければなりません。 その目的に向けて、この投稿はセキュリティの考え方を刺激し、読者に健康的な妄想を注入することを目的としています。
特に、このガイドでは、軽減する方法に関する推奨事項を含め、知っておくべき10の一般的で重要なWebセキュリティの落とし穴に焦点を当てています。 焦点は、世界中のソフトウェアセキュリティを改善することを目標とする国際的な非営利組織であるOpen Web Application Security Project(OWASP)によって特定された上位10のWeb脆弱性にあります。
始める前のちょっとしたサイバーセキュリティ入門書–認証と承認
他のプログラマーやIT専門家と話すとき、認証と認証の違いについて混乱することがよくあります。 そしてもちろん、略語authが両方によく使用されるという事実は、この一般的な混乱を悪化させるのに役立ちます。 この混乱は非常に一般的であるため、この問題は「CommonWebVulnerabilityZero」としてこの投稿に含める必要があります。
したがって、先に進む前に、これら2つの用語の違いを明確にしましょう。
- 認証:セキュリティ資格情報(パスワード、セキュリティの質問への回答、指紋スキャンなど)を正しく提供しているため、特定のユーザーである(または少なくともそのように見える)ことを確認します。
- 承認:特定のユーザーが特定のリソースにアクセスできること、または特定のアクションを実行するための権限が付与されていることを確認します。
別の言い方をすれば、認証はエンティティが誰であるかを知っているのに対し、承認は特定のエンティティが何ができるかを知っているということです。 これを念頭に置いて、インターネットセキュリティの問題トップ10に入りましょう。
一般的なWebセキュリティの間違い#1:インジェクションの欠陥
インジェクションの欠陥は、信頼できない入力をフィルタリングするという古典的な失敗に起因します。 これは、フィルタリングされていないデータをSQLサーバー(SQLインジェクション)、ブラウザー(XSS –これについては後で説明します)、LDAPサーバー(LDAPインジェクション)、またはその他の場所に渡すときに発生する可能性があります。 ここでの問題は、攻撃者がこれらのエンティティにコマンドを挿入し、データを失い、クライアントのブラウザを乗っ取る可能性があることです。
アプリケーションが信頼できないソースから受け取るものはすべて、できればホワイトリストに従ってフィルタリングする必要があります。 ブラックリストを正しく取得することは非常に困難であり、通常はバイパスするのが簡単であるため、ブラックリストを使用することはほとんどありません。 ウイルス対策ソフトウェア製品は、通常、失敗したブラックリストの優れた例を提供します。 パターンマッチングは機能しません。
防止:良いニュースは、インジェクションから保護することは、入力を適切にフィルタリングし、入力が信頼できるかどうかを考えることの「単純な」問題であるということです。 しかし、悪いニュースは、間違いなく信頼できる場合を除いて、すべての入力を適切にフィルタリングする必要があることです(ただし、ここでは「決して言わない」という言葉が思い浮かびます)。
たとえば、1,000個の入力があるシステムでは、999個の入力を正常にフィルタリングするだけでは不十分です。これは、システムをダウンさせるためのアキレス腱として機能できるフィールドが1つ残っているためです。 また、データベースは信頼されているため、SQLクエリの結果を別のクエリに入れるのは良い考えだと思うかもしれませんが、境界が信頼されていない場合、入力は悪意のある人から間接的に行われます。 興味がある場合は、これを2次SQLインジェクションと呼びます。
フィルタリングは(暗号のように)正しく行うのがかなり難しいので、私が通常アドバイスするのは、フレームワークのフィルタリング機能に依存することです。それらは機能することが証明されており、徹底的に精査されています。 フレームワークを使用しない場合は、フレームワークを使用しないことがサーバーのセキュリティコンテキストで本当に意味があるかどうかを真剣に考える必要があります。 99%の確率でそうではありません。
一般的なWebセキュリティの間違い#2:認証の失敗
これは、認証の失敗中に発生する可能性のある複数の問題のコレクションですが、すべてが同じ根本原因に起因するわけではありません。
誰かが2014年にまだ自分の認証コードをロールしたいと思っていると仮定すると(あなたは何を考えていますか??)、私はそれに反対することをお勧めします。 正しく理解することは非常に困難であり、いくつか言及するだけで、考えられる落とし穴は無数にあります。
- URLにセッションIDが含まれていて、それをリファラーヘッダーで他の誰かにリークする可能性があります。
- パスワードは、保管中または転送中のいずれでも暗号化されていない可能性があります。
- セッションIDは予測可能である可能性があるため、アクセス権を取得するのは簡単です。
- セッション固定が可能かもしれません。
- セッションハイジャックが可能である、タイムアウトが正しく実装されていない、またはHTTP(SSLセキュリティなし)を使用しているなど…
防止:このWebセキュリティの脆弱性を回避する最も簡単な方法は、フレームワークを使用することです。 これを正しく実装できるかもしれませんが、前者の方がはるかに簡単です。 独自のコードを作成したい場合は、非常に偏執的になり、落とし穴について自分自身を教育してください。 かなりの数があります。
一般的なWebセキュリティの間違い#3:クロスサイトスクリプティング(XSS)
これは、かなり広範囲にわたる入力サニタイズの失敗です(基本的に、よくある間違い#1の特殊なケース)。 攻撃者は、入力時にWebアプリケーションにJavaScriptタグを与えます。 この入力がサニタイズされていないユーザーに返されると、ユーザーのブラウザーがそれを実行します。 リンクを作成してユーザーにクリックするように説得するのと同じくらい簡単な場合もあれば、もっと不吉なものにする場合もあります。 ページの読み込み時にスクリプトが実行され、たとえば、攻撃者にCookieを投稿するために使用される可能性があります。
防止:単純なWebセキュリティソリューションがあります。HTMLタグをクライアントに返さないでください。 これには、HTMLインジェクションに対して防御するという追加の利点があります。これは、攻撃者がプレーンなHTMLコンテンツ(画像や大音量の非表示のFlash Playerなど)をインジェクトする同様の攻撃です。影響は大きくありませんが、確かに迷惑です(「止めてください!」)。 通常、回避策はすべてのHTMLエンティティを変換するだけなので、 <script>
は<script>
として返されます。 。 他のよく使用されるサニタイズの方法は、正規表現を使用して<
および>
の正規表現を使用してHTMLタグを取り除くことですが、多くのブラウザがひどく壊れたHTMLをうまく解釈するため、これは危険です。 すべての文字をエスケープされた対応する文字に変換することをお勧めします。
一般的なWebセキュリティの間違い#4:安全でない直接オブジェクト参照
これは、ユーザー入力を信頼し、結果として生じるセキュリティの脆弱性に代償を払う典型的なケースです。 直接オブジェクト参照とは、ファイルやデータベースキーなどの内部オブジェクトがユーザーに公開されることを意味します。 これに伴う問題は、攻撃者がこの参照を提供でき、承認が強制されていない(または破られている)場合、攻撃者はアクセスしたり、除外すべきことを実行したりできることです。
たとえば、コードにはdownload.php
モジュールがあり、CGIパラメータを使用してファイル名を指定し、ユーザーがファイルを読み取ってダウンロードできるようにします(たとえば、 download.php?file=something.txt
)。 誤って、または怠惰のために、開発者はコードから認証を省略しました。 攻撃者はこれを使用して、PHPを実行しているユーザーがアクセスできるシステムファイルをダウンロードできます。たとえば、アプリケーションコード自体や、バックアップなど、サーバー上に残っている他のデータなどです。 ええとああ。
もう1つの一般的な脆弱性の例は、ユーザー入力に依存してリセットするパスワードを決定するパスワードリセット機能です。 攻撃者は、有効なURLをクリックした後、URLのusername
フィールドを変更して「admin」のように言うことができます。
ちなみに、これらの例は両方とも、私自身が「野生で」頻繁に現れるのを見たものです。
防止:ユーザー認証を適切かつ一貫して実行し、選択肢をホワイトリストに登録します。 ただし、多くの場合、データを内部に保存し、CGIパラメータを介してクライアントから渡されるデータに依存しないことで、問題全体を回避できます。 ほとんどのフレームワークのセッション変数は、この目的に適しています。
一般的なWebセキュリティの間違い#5:セキュリティの設定ミス
私の経験では、誤って構成されたWebサーバーとアプリケーションは、適切に構成されたものよりもはるかに一般的です。 おそらくこれは、失敗する方法が不足していないためです。 いくつかの例:
- 本番環境でデバッグを有効にしてアプリケーションを実行する。
- サーバーでディレクトリリストを有効にすると、貴重な情報が漏洩します。
- 古いソフトウェアを実行している(WordPressプラグイン、古いPhpMyAdminを考えてください)。
- マシン上で不要なサービスを実行している。
- デフォルトのキーとパスワードを変更しない。 (あなたが信じているよりもずっと頻繁に起こります!)
- スタックトレースなどのエラー処理情報を攻撃者に明らかにする。
防止:デプロイ時にテストを実行できる、優れた(できれば自動化された)「ビルドとデプロイ」プロセスを用意します。 貧乏人のセキュリティ設定ミスの解決策は、コミット後のフックであり、デフォルトのパスワードや開発関連のものが組み込まれた状態でコードが送信されるのを防ぎます。
一般的なWebセキュリティの間違い#6:機密データの漏洩
このWebセキュリティの脆弱性は、暗号化とリソース保護に関するものです。 機密データは、転送中および保存中を含め、常に暗号化する必要があります。 例外なく。 クレジットカード情報とユーザーパスワードは絶対に移動したり、暗号化せずに保存したりしないでください。また、パスワードは常にハッシュ化する必要があります。 明らかに、暗号化/ハッシュアルゴリズムは弱いものであってはなりません。疑わしい場合は、Webセキュリティ標準でAES(256ビット以上)およびRSA(2048ビット以上)が推奨されます。

言うまでもなく、セッションIDと機密データはURL内を移動してはならず、機密Cookieにはセキュアフラグがオンになっている必要がありますが、これは非常に重要であり、強調しすぎることはありません。
防止:
転送中:適切な証明書とPFS(Perfect Forward Secrecy)でHTTPSを使用します。 HTTPS以外の接続では何も受け入れないでください。 クッキーに安全なフラグを付けます。
ストレージ内:これは難しいです。 まず第一に、あなたはあなたの露出を下げる必要があります。 機密データが必要ない場合は、細断処理してください。 持っていないデータを盗むことはできません。 PCIに準拠することに対処する必要がない可能性があるため、クレジットカード情報を保存しないでください。 StripeやBraintreeなどの支払い処理業者にサインアップします。 次に、実際に必要な機密データがある場合は、暗号化して保存し、すべてのパスワードがハッシュ化されていることを確認します。 ハッシュにはbcryptの使用をお勧めします。 bcryptを使用しない場合は、ソルトテーブルとレインボーテーブルについて学習してください。
また、明らかなことを述べるリスクを冒して、保護されたデータの横に暗号化キーを保存しないでください。 これは、鍵が入っているロックを付けて自転車を保管するようなものです。 バックアップを暗号化で保護し、キーを非常にプライベートに保ちます。 そしてもちろん、鍵をなくさないでください!
一般的なWebセキュリティの間違い#7:機能レベルのアクセス制御の欠如
これは単に認証の失敗です。 これは、サーバーで関数が呼び出されたときに、適切な認証が実行されなかったことを意味します。 多くの場合、開発者はサーバー側がUIを生成したという事実に依存しており、サーバーによって提供されていない機能にはクライアントがアクセスできないと考えています。 攻撃者は常に「隠された」機能へのリクエストを偽造することができ、UIがこの機能に簡単にアクセスできないという事実によって阻止されないため、それはそれほど単純ではありません。 /admin
パネルがあり、ユーザーが実際に管理者である場合にのみ、ボタンがUIに表示されるとします。 攻撃者がこの機能を発見し、認証が欠落している場合にそれを悪用することを妨げるものは何もありません。
防止:サーバー側では、承認を常に行う必要があります。 はい、いつも。 例外や脆弱性が深刻な問題を引き起こすことはありません。
一般的なWebセキュリティの間違い#8:クロスサイトリクエストフォージェリ(CSRF)
これは、ブラウザが他の当事者にだまされてその権限を悪用するという混乱した副攻撃の良い例です。 たとえば、サードパーティのサイトでは、ユーザーのブラウザが攻撃者のために何かをする権限を悪用する可能性があります。
CSRFの場合、サードパーティのサイトは、Cookie /セッションでブラウザを使用してターゲットサイト(銀行など)にリクエストを発行します。 たとえば、銀行のホームページの1つのタブにログインしていて、この攻撃に対して脆弱である場合、別のタブを使用すると、ブラウザが攻撃者に代わってクレデンシャルを悪用し、混乱した代理問題が発生する可能性があります。 代理人は、攻撃者が指示したことを行うためにその権限(セッションCookie)を悪用するブラウザです。
この例を考えてみましょう。
攻撃者のアリスは、トッドのお金の一部を彼女に送金することで、ターゲットのトッドの財布を軽くしたいと考えています。 トッドの銀行はCSRFに対して脆弱です。 送金するには、トッドは次のURLにアクセスする必要があります。
http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243
このURLが開かれると、成功ページがToddに表示され、転送が行われます。 アリスはまた、トッドが自分の管理下にあるblog.aliceisawesome.comのサイトに頻繁にアクセスし、次のスニペットを配置していることも知っています。
<img src=http://example.com/app/transferFunds?amount=1500&destinationAccount=4673243243 width=0 height=0 />
アリスのウェブサイトにアクセスすると、トッドのブラウザはアリスが画像にリンクしていると見なし、画像を取得するためにHTTP GETリクエストを自動的に発行しますが、これは実際にはトッドの銀行に$1500をアリスに転送するように指示します。
ちなみに、この例では、CSRFの脆弱性を示すだけでなく、それ自体が深刻な脆弱性であるべき等のHTTPGETリクエストを使用してサーバーの状態を変更することも示しています。 HTTP GETリクエストはべき等(安全)である必要があります。つまり、アクセスされるリソースを変更することはできません。 サーバーの状態を変更するためにべき等メソッドを使用することは決してありません。
おもしろい事実:CSRFは、アフィリエイトが賢くなるまで、過去にCookieの詰め込みに使用されていた方法でもあります。
防止:サードパーティのサイトからアクセスできない非表示のフォームフィールドにシークレットトークンを保存します。 もちろん、常にこの隠しフィールドを確認する必要があります。 一部のサイトでは、機密性の高い設定を変更するときにもパスワードを要求されます(たとえば、パスワードのリマインダーメールなど)。ただし、これは、放棄されたセッションの誤用を防ぐためにあると思われます(たとえば、インターネットカフェで)。
一般的なWebセキュリティの間違い#9:既知の脆弱性を持つコンポーネントの使用
タイトルはそれをすべて言います。 これも、メンテナンス/展開の問題として分類します。 新しいコードを組み込む前に、調査、場合によっては監査を行ってください。 GitHubまたはフォーラムでランダムな人から入手したコードを使用すると非常に便利な場合がありますが、深刻なWebセキュリティの脆弱性のリスクがないわけではありません。
たとえば、サイトが所有された場合(つまり、部外者がシステムへの管理アクセスを取得した場合)は、プログラマーが愚かだったためではなく、サードパーティのソフトウェアが何年にもわたってパッチを適用されていなかったためです。 これは、たとえばWordPressプラグインで常に発生しています。 隠されたphpmyadmin
のインストールが見つからないと思われる場合は、dirbusterを紹介します。
ここでの教訓は、アプリケーションが展開されてもソフトウェア開発は終了しないということです。 特にサードパーティまたはオープンソースのコンポーネントが含まれている場合は、ドキュメント、テスト、および更新を維持および維持する方法に関する計画が必要です。
防止:
注意してください。 そのようなコンポーネントを使用するときに明らかに注意を払う以外に、コピー&ペーストコーダーにならないでください。 ソフトウェアに挿入しようとしているコードは、修復できないほど壊れている可能性があるため、注意深く調べてください(または、場合によっては、意図的に悪意があります。この方法で、無意識のうちにWebセキュリティ攻撃が引き起こされることがあります)。
最新に保つ。 信頼できるすべての最新バージョンを使用していることを確認し、定期的に更新する計画を立ててください。 少なくとも、製品に関する新しいセキュリティの脆弱性に関するニュースレターを購読してください。
一般的なWebセキュリティの間違い#10:未検証のリダイレクトと転送
これもまた、入力フィルタリングの問題です。 ターゲットサイトに、URLをGET
パラメーターとしてredirect.php
モジュールがあるとします。 パラメータを操作すると、ブラウザをmalwareinstall.com
にリダイレクトするURLをtargetsite.com
に作成できます。 ユーザーにリンクが表示されると、ユーザーが信頼でき、安全にクリックできるとユーザーが考えるtargetsite.com/blahblahblah
が表示されます。 これが実際にマルウェアドロップ(またはその他の悪意のある)ページに転送されることを彼らはほとんど知りません。 または、攻撃者がブラウザをtargetsite.com/deleteprofile?confirm=1
にリダイレクトする可能性があります。
言及する価値があるのは、サニタイズされていないユーザー定義の入力をHTTPヘッダーに詰め込むと、ヘッダーインジェクションが発生する可能性があり、これはかなり悪いことです。
予防:オプションは次のとおりです。
- リダイレクトは一切行わないでください(ほとんど必要ありません)。
- リダイレクト先の有効な場所の静的リストを用意します。
- ユーザー定義パラメーターをホワイトリストに登録しますが、これには注意が必要です。
エピローグ
この投稿であなたの脳を少しくすぐり、健康的な妄想とWebサイトのセキュリティ脆弱性の認識を紹介できたことを願っています。
ここでの重要なポイントは、古くからのソフトウェアプラクティスが理由で存在し、バッファオーバーフローに対して当時適用されていたものが、今日でもPythonのピクルス文字列に適用されることです。 セキュリティプロトコルは、すべてのプログラマーが目指すべき(より多くの)正しいプログラムを作成するのに役立ちます。
この知識を責任を持って使用し、許可なくページをテストしないでください。
詳細およびより具体的なサーバー側の攻撃については、https://www.owasp.org/index.php/Category:Attackを参照してください。
この投稿へのフィードバックとその軽減に関するアドバイスを歓迎し、感謝しています。 特に分散型サービス拒否(DDoS)および旧式の(Webではない)ITセキュリティの脆弱性の問題については、将来関連する投稿が計画されています。 どのような種類のWeb保護について書くべきかについて具体的な要求がある場合は、[email protected]まで直接お気軽にご連絡ください。
これがウェブサイトのセキュリティです! 乾杯。
- JSON Web Tokenチュートリアル:LaravelとAngularJSの例
- パフォーマンスと効率:HTTP/3での作業