認証と認可
認証(AuthN)と認可(AuthZ)の話題は、どちらかが脆弱であることを含む脆弱性の頻度が高いため、非常に重要である。これらの脆弱性は定期的に発生しているように見えるので、通常、これらの脆弱性が何なのか、あるいは何が原因なのかについて、少し不確かな部分があることを意味する。
注意事項として、各期間は以下の内容をカバーしている:
- 認証:ユーザーは誰か?
- 権限:ユーザーは何にアクセスできるのか?
以下、別々に見ていこう。
認証(識別と認証の失敗)
不適切な認証は、以下のような多種多様な脆弱性をカバーする可能性がある:
- 特定のページ/エンドポイントに認証がないこと。
- 総当たり攻撃(クレデンシャル・スタッフィング)に対する防御の欠如
- 安全でないアカウント/パスワード回復プロセス
- 安全でない認証トークンの生成、検証、有効期限切れ、送信、保管
- ユーザが 2FA で認証されたことの検証が不適切または欠落している(該当する場合)
リストの最初の項目(認証の不在)は、実際に観察される最も一般的な問題です。多くの場合、開発者はページやエンドポイントで要求される認証のレベルを明示的に注釈/設定する必要があり、そのステップは簡単に見逃されがちです。
システムがオープンに失敗するのではなく、クローズドに失敗することを保証するのは良い習慣です。ですから、認証されたユーザーセッションが必要であるという情報を各エンドポイントに注釈をつけるのではなく、特別に上書きされない限り、デフォルトではすべてのルートが認証されたユーザーセッションを必要とします。こうすることで、エラーの可能性を劇的に減らすことができます。
認可(壊れたアクセス制御)
オーソライズの問題は、非常に一般的なさまざまな形で現れる可能性がある:
- 安全でない直接オブジェクト参照(IDOR)
- 機能レベルのアクセス制御の欠落(AuthZの欠落)
- 特権の昇格(水平方向または垂直方向)
安全でない直接オブジェクト参照
オブジェクトは、それらを参照するためのキーとして使用される一意の識別子(ID)を持つ傾向がある。ユーザが注文や口座、あるいはそれに類するものを見るためにリクエストを送ると、通常この ID が含まれます。安全でないオブジェクトの直接参照」は、アプリケーションが、ユーザ(またはその欠如)がその特定のオブジェクトにアクセ スできるかどうかの妥当性確認に失敗した場合に発生します。
機能レベルのアクセス制御の欠落
もう1つの本当によくある脆弱性は、(オブジェクトではなく)ページやエンドポイントに対する権限チェックがないことです。
使用するフレームワークにもよるが、開発者はハンドラで認可をチェックするか、エンドポイントにアノテーションを付け、エンドポイントを呼び出すために必要な要件を指定しなければならないのが一般的だ。
残念なことに、このような余分なステップは非常に忘れやすいので、認証の脆弱性がどのように起こるか、しばしば説明される。
推薦の言葉
デフォルトはオープンではなくクローズ
認証(Authentication)と認可(Authorization)の両方において、オープンではなくクローズドをデフォルトとする原則は重要である。
あなたの言語/フレームワークにもよりますが、アプリケーションへのすべてのルートのデフォルトが、可能な限り高いロールもしくはパーミッションを持つ認証されたセッションを要求するようにするのはよい習慣です。 このようにすることで、開発者はルートの要件をオーバーライドしなければなりません。
cs
// Ensure the default behaviour is to authenticate requests, and check if they are admin
[Authenticate]
[Authorize("Admin")]
public class SecureController : Controller
{
}
public class MyController : SecureController
{
// Overrides the Authorize attribute inherited to allow any user to access the page
[Authorize("User")]
public Page ShowUserProfile() {
}
// Can only be accessed by an Admin user
public Page ShowAdminPage() {
}
// Overrides the Authenticate and Authorize attribute to allow ME
[AllowAnonymous]
public Page ShowLoginPage() {
}
}
サービスにおける認証チェックの実施
データにアクセスする場合、すべてのデータアクセスが統一された方法で関連するアクセスと認可チェックを確実に実施することが極めて重要である。これは通常、ドメイン・サービスを使用することで実現される。
その他の例
以下に、セキュアな認証と認可の違いについてよくわかる短い例を集めました。
C# - 安全ではない
認証の欠落
public class AdminController : Controller
{
// INSECURE: Does not check whether the user is logged in before showing an Admin page
public Page ShowAdminPage() {
}
}
認可の欠落