Internal Server Error (内部サーバー エラー)¶
概要¶
500 Internal Server レスポンスは、サーバーが予期しない状況に遭遇し、 リクエストに対応できなかったことを示します。このエラー レスポンスは、 リクエストを処理中に未処理の例外が発生したときに使用される汎用的な 「キャッチオール」レスポンスです。
通常、Internal Server Errors は良性です。ただし、未処理の例外が SQL インジェクションなどの セキュリティの問題を示唆している場合もあります。
推奨事項¶
ユーザーが API にどのような値を入力しても処理可能な一貫したエラー処理メカニズムを追加することを考慮します。 理想としては、エラーは '400 Bad Request' のような 4xx 番台のステータスを返し、 エンドユーザーがリクエストを修正する方法を理解できるよう、意味のある詳細情報を 提供するべきです。
また、運用環境では、スタックトレースなどの攻撃者にとって有用な情報がエラー メッセージに含まれないようにします。
サンプル¶
通常、Internal Server Error は、エンドポイントによって適切に処理されて いない予期しない入力値に起因します。 FastAPI のサンプルを見てみましょう。
from fastapi import FastAPI
app = FastAPI()
DB = ["✨", "🔥"]
@app.get("/items")
async def read_item(idx: int):
return DB[idx]
API はクエリー パラメーターとして idx
を受け取る単一のエンドポイント /items
で構成されています。
エンドポイントはインメモリ データベースのアイテムを返します。
いくつかの異なる入力値を使用してエンドポイントを呼び出してみます。
$ curl 'localhost:8080/items?idx=0'
"✨"
$ curl 'localhost:8080/items?idx=1'
"🔥"
$ curl 'localhost:8080/items?idx=2'
Internal Server Error
最後のクエリーでは、内部サーバー エラーが返されました。これは、エンドポイントがインデックス境界外を間接参照し、 未処理の例外につながったために起きた問題です。しかし、クライアントには単に 'Internal Server Error' が表示されるだけで、 何が起きているかわかりません。
500 Internal Server Error レスポンスに有用な情報が含まれていることもありますが、 通常は何か問題が起きたという漠然としたテキストです。 リクエストに問題があったのでしょうか? 使用した URL が誤っていたのでしょうか?
API のコンシューマーは、それぞれ次のステップのすべてまたは一部を試していく必要があります。 - リクエストに明らかなエラーがないかを詳細に調べ、再試行します。 - stack overflow、Google…その他を調べ始めます。 - サポートに連絡して待ちます… - ひょっとして問題は一時的なものだったのでは? --再びリクエストを試します。 - ⚠️ 再試行が危険な場合もあります - リクエストは部分的に完了したのでしょうか? (支払いエンドポイントだったとして) クレジット カードは二重に請求されるのでしょうか?
時間および不満感という面でのコストは、API で 500 レスポンス コードに遭遇するコンシューマーが増えるごとに積み重なります。API を利用することで開発者が得た有能感は薄れ始めます。
入力検証を追加すると、未処理の例外を防ぐことができます。
クエリー パラメーター idx
が境界内であることの検証によってエンドポイントの問題を修正する方法は次のとおりです。
from typing import Optional
from fastapi import FastAPI, Query
app = FastAPI()
DB = ["✨", "🔥"]
@app.get("/items")
async def read_item(idx: int = Query(0, ge=0, lt=len(DB))):
return DB[idx]
問題のあるリクエスト (idx=2
) をもう一度送ってみると、わかりにくいメッセージではなく、
リクエストの何が悪かったのかという詳細を含む有用な 400 Bad Request レスポンスが表示されます。
{
"detail": [
{
"loc": [
"query",
"idx"
],
"msg": "ensure this value is less than 2",
"type": "value_error.number.not_lt",
"ctx": {
"limit_value": 2
}
}
]
}
500 Internal Server Error は未処理の例外であるため、 500 Internal Server Error レスポンスの一部としてスタック トレースを返したくなるかもしれません。 これは開発モードで実行しているときには有用です。 ソフトウェア開発者は、デバッグの補助としてエラー メッセージにスタック トレースを追加することがよくあります。 スタック トレースがあれば、開発者はエラー発生時のソフトウェアの最終状態だけでなく、エラーに至る一連のイベントについてより詳しく知ることができます。
Mayhem for API でのファジング時、テスト環境で (のみ)、より詳細なバグ レポートを提示できるようスタック トレースを返すことを推奨します。 ただし、運用環境においては、500 Internal Server Error が詳細情報やスタック トレースを返すべきではありません。これはよくあるサーバー構成の誤りであり、攻撃者に機密情報を公開するおそれがあります。
ファイル パスや関数名など、スタック トレースに含まれる情報は、アプリケーションやアプリケーションが利用する内部ライブラリの構造を漏らす可能性があります。 さらに、スタック トレース先頭のエラー メッセージには、アプリケーションが使用する SQL クエリーなどの情報が含まれ、攻撃者がその後の攻撃を調整するための手掛かりになる可能性があります。
参考資料¶
- OWASP: Improper Error Handling.
- Common Weakness Enumeration: CWE-20.
- Common Weakness Enumeration: CWE-391.
- Common Weakness Enumeration: CWE-550.