ログイン機能を実装し終えて、次はセキュリティ対策だと考える。SQLインジェクション対策、XSS対策、パスワードのハッシュ化——検索して出てくる項目を上から潰していく。その順番では、いちばん大きな穴が最後まで残ります。
OWASPが開発者向けにまとめた実装指針「Proactive Controls」の2024年版で、1位は「アクセス制御を実装せよ」でした。2018年版では7位だった項目です。この記事では順序が入れ替わった意味を追い、実際にコードを動かして、認可の有無が何を分けるのかを本物の出力で示します。
2024年版の1位はアクセス制御。2018年版では7位だった。攻撃の分類と開発の指針が、別々の経路で同じ結論に到達している。
セキュアコーディングの指針として OWASP が開発者向けにまとめているのが Proactive Controls です。公式は位置づけをこう定義しています。“a catalog of better practices, a set of items developers can embrace and implement in their code bases”。実装するものの目録であって、攻撃の一覧ではありません。
この目録の並び順が、2018年版と2024年版で大きく変わりました。アクセス制御が7位から1位へ繰り上がっています。逆に2018年版で1位だった「セキュリティ要件の定義」は、2024年版では4位に相当する位置へ移りました。
| 2024年版 | 内容 | 2018年版での対応 |
|---|---|---|
| C1 | アクセス制御の実装 | C7(7位) |
| C2 | データ保護のための暗号利用 | C8(8位) |
| C3 | 全入力の検証と例外処理 | C5・C10(5位・10位) |
| C4 | 最初からセキュリティを考える | C1(1位) |
| C5 | 既定値を安全にする | 該当なし(新設) |
| C6 | 依存コンポーネントを安全に保つ | C2(2位) |
| C7 | デジタルIDの保護 | C6(6位) |
| C8 | ブラウザのセキュリティ機能の活用 | 該当なし(新設) |
| C9 | セキュリティログと監視の実装 | C9(9位) |
| C10 | SSRFを止める | 該当なし(新設) |
OWASP には性格の違う2つの一覧があります。攻撃側の分類が Top 10、開発側の指針が Proactive Controls です。2024〜2025年版では、両方の1位がアクセス制御になりました。
| OWASP Top 10:2025 | Proactive Controls 2024 | |
|---|---|---|
| 視点 | 攻撃側(何が起きているか) | 開発側(何を実装するか) |
| 1位 | A01 Broken Access Control | C1 アクセス制御の実装 |
| 使いどころ | 現状把握・分類 | 着手順の決定 |
| データの出所 | 約17.5万件のCVE+コミュニティ調査 | 実務者による実装指針 |
順位の意味を詳しく知りたい場合はOWASP Top 10の解説記事を参照してください。あちらは「順位が出現率ではない」ことを扱っています。
セキュアコーディングと聞いて最初に浮かぶのは、SQLを文字列連結しないことやエスケープ処理でしょう。これらは2024年版では C3 に集約され、単独の最優先事項ではなくなりました。入力を完璧に検証しても、他人のデータを返す設計であれば何も防げない——順序の変更はそう読めると編集部は考えています。
Proactive controls are a catalog of better practices, a set of items developers can embrace and implement in their code bases to avoid many common security issues. Proactive controls provide positive patterns to implement solutions considered secure by design.出典OWASP Top 10 Proactive Controls 2024「Introduction」 一次情報を確認2026-08-16 この内容の有効期限2027-02-16
認可の実装は難しい理屈ではなく、クエリの条件を1つ増やすこと。IDだけで引くのをやめれば、他人のデータを返す経路が閉じる。
セキュアコーディングでアクセス制御が抜ける典型は、認証を実装し終えた直後です。ログインは通っている、セッションも有効——だからデータを返してよい、と書いてしまいます。認証(誰か)と認可(何をしてよいか)は別の判定です。
違いを文章で説明するより、動かした方が早いので実行しました。請求書を2件持つデータに対し、user_A がログインした状態で user_B の請求書IDを指定します。
const invoices = [
{ id: 'inv_1001', ownerId: 'user_A', amount: 12000, memo: 'Aさんの請求書' },
{ id: 'inv_1002', ownerId: 'user_B', amount: 98000, memo: 'Bさんの請求書' },
];
// 認可なし: IDが一致すれば誰にでも返す
function findInvoiceUnsafe(invoiceId) {
return invoices.find((v) => v.id === invoiceId) ?? null;
}
// 認可あり: IDと所有者の両方が一致したときだけ返す
function findInvoiceSafe(invoiceId, requesterId) {
return invoices.find((v) => v.id === invoiceId && v.ownerId === requesterId) ?? null;
}
// user_A がログイン中。他人(user_B)の請求書IDを指定して叩く
const attacker = 'user_A';
const target = 'inv_1002';
--- 認可チェックなし --- 返却: Bさんの請求書 / 98000円 --- 認可チェックあり --- 返却: null(403にする) --- 本人が自分のものを取得 --- 返却: Aさんの請求書 / 12000円
差分は && v.ownerId === requesterId の一節だけです。これが無いと 98,000円という他人の金額がそのまま返ります。あるとnullになり、本人の取得は通常どおり成功します。
実際のアプリではORMを使いますが、原理は変わりません。主キーだけで引く関数(Prismaなら findUnique({ where: { id } }))は、所有者の条件を書く場所がありません。所有者を条件に含められる関数へ置き換えます。
where: { id, userId: 現在のユーザー } の形にする認可の検証に道具は要らない。自分のアカウントで他人のIDを指定し、データが返らないことを確かめる。返ったら穴がある。
セキュアコーディングが事後対応を避けるための営みであることは、公式の説明に表れています。“prevent common vulnerabilities during an application's inception”。作り始めの段階で防ぐ、という発想です。ただし書いた後の確認は必要で、認可については特別な道具が要りません。
認可が実装済みと言えるのは4条件すべてを満たしたとき。読み取りだけ直して更新系が残る例が最も多い。
この検証の具体例はIDORの記事で扱っています。IDORはアクセス制御の失敗のうち、他人のIDを指定するだけで成立する形態を指します。
1本3分は、ブラウザの開発者ツールでIDを書き換えて再送し、結果を記録するまでの目安。自動テストに落とせば2回目以降はゼロになる。
この確認が効くのは実施した時点までです。機能を追加するたびにIDを受け取る経路は増え、そのたびに同じ穴が開きます。手作業の確認は初回の棚卸しに使い、以降はテストコードに落とすのが現実的だと編集部は考えています。上の試算で出た時間は、自動化すれば2回目から回収できる投資です。
Proactive controls prevent this by focusing on the development itself. Their idea is to prevent common vulnerabilities during an application's inception so that those tedious and embarrassing bug fixes can be avoided altogether.出典OWASP Top 10 Proactive Controls 2024「Introduction」 一次情報を確認2026-08-16 この内容の有効期限2027-02-16
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る