我是 GMO Connect 的永田。
我曾在兩個承包參與的系統上,讓 Claude Code 閱讀原始碼並進行脆弱性搜尋診斷(白箱診斷)。等到緊急/高風險的指摘都出爐後再對照,發現幾乎每一項都是以前就聽過的問題。
試著對照 OWASP ASVS 5.0 之後,21 件裡有 6 件落在同一個要件(8.2.2),而且只看 L1 的要件就有 12 件符合。ASVS 總共有 345 項,要全部看完很費工夫。這篇是記錄:從實際出現緊急/高風險的要件出發,在需求定義時應該指定到哪個指南的哪個程度。
要件(ASVS 5.0)件數等級8.2.2 依資料粒度的授權(IDOR・BOLA)6L12.2.1 輸入值驗證1L18.3.1 在可信層進行授權1L19.1.1 驗證權杖簽章1L15.2.2・3.2.1・5.3.2 檔案種類・顯示方式・路徑2L114.2.1 URL 不要帶敏感資訊1L18.2.3 欄位粒度的授權1L215.3.3 批次指派1L22.4.1 呼叫次數・數量上限1L26.6.3 驗證碼暴力破解防護1L26.8.1 多個 IdP 的冒充1L213.3.1 機密管理1L2ASVS 之外(AWS 設定 2 件、舊 API 殘留 1 件)3不適用-
兩者都是用 AWS 無伺服器架構(API Gateway 與 Lambda)以及 Amazon Cognito 建成的、多公司共用的業務系統。
我統計的是診斷中風險等級被判為「緊急」或「高」的指摘。風險等級是依「嚴重度」與「攻擊成立可能性」的組合判定。相同原因的指摘合併成 1 件後,共 21 件。中、低風險的指摘沒有統計。AI 漏掉的脆弱性,當然也不在這 21 件之內。
診斷是交給 Claude Code 的子代理來做。把系統按功能領域切開後,每個領域由 5 個代理一起看:
觀點是根據公司內部自行維護的檢查清單,以及之前寫的 Cognito 文章中的檢查項目整理出來的。因為沒有把 ASVS 當作觀點,所以「ASVS 裡有寫」是指等緊急/高風險都出齊後,再拿 ASVS 5.0 原文逐項對照的結果。對照草稿先由 Claude 產生,再以要件原文與指摘本文重新核對。
不過,Cognito 屬性那一項(第 2 章的 ASVS 8.3.1)是用 Cognito 文章中的檢查項目作為觀點找出的。
ASVS 5.0.0 是 2025 年 5 月發布的版本。根據 v5.0.0_release 標籤中的 V1~V17 表格統計,要件共有 345 項,其中 L1 有 70 項、L2 有 183 項、L3 有 92 項。ASVS 本身對 L1 與 L2 的說明如下:
This level contains the minimum requirements to consider when securing an application and represents a critical starting point. This level contains around 20% of the ASVS requirements. The goal for this level is to have as few requirements as possible, to decrease the barrier to entry.
Most applications should be striving to achieve this level of security.
What is the ASVS?(OWASP ASVS 5.0.0)
L1 是為了降低門檻而精簡過的起點。L2 則被視為大多數應用程式應該追求的等級。
若 1 件同時符合多個要件,我會記成最直接描述它的那一項。猶豫的有以下 3 件:
指摘都來自真實系統,但說明用的例子全部改成假想服務。
這些例子只是為了說明,不是實際跑過驗證的結果。
這個要件出現最多次。
Verify that the application ensures that data-specific access is restricted to consumers with explicit permissions to specific data items to mitigate insecure direct object reference (IDOR) and broken object level authorization (BOLA).
IDOR・BOLA 是只要改 URL 或本文中的 ID,就能碰到不該看的資料的問題。以會議室預約服務為例,像這樣:
GET /reservations/1043
Authorization: Bearer <A 公司使用者的權杖>
即使 1043 是 B 公司預約,只要登入就回傳,這就是問題。這 6 件雖然入口不同,但都沒有確認「收到的 ID,是否是呼叫者所屬公司/負責人/角色可以操作的資料」。實際出現的型態如下:
這 6 件裡有 5 件是能碰到其他公司的資料。確認方式很單純:對每個入口整理成表,列出「接收的 ID」以及「是否有檢查擁有者/所屬/角色」。這次診斷也要求授權負責人,針對所有入口都做了這張表。
Verify that input is validated to enforce business or functional expectations for that input. This should either use positive validation against an allow list of values, patterns, and ranges, or be based on comparing the input to an expected structure and logical limits according to predefined rules. For L1, this can focus on input which is used to make specific business or security decisions. For L2 and up, this should apply to all input.
L1 只要求先檢查會用來做業務或資安判斷的輸入即可。例子是成員邀請:
{ "email": "[email protected]", "role": "owner" }
畫面只會送出 "member" 與 "admin",但如果 API 也接受 "owner",管理者就能建立比自己更高的角色。角色正是「用來做資安判斷的輸入」。
Verify that the application enforces authorization rules at a trusted service layer and doesn't rely on controls that an untrusted consumer could manipulate, such as client-side JavaScript.
這就是其中一件緊急項目。Cognito 自訂屬性(例如 custom:company_id)被拿來做授權,而使用者可以自己修改這個屬性。使用者能改的值,就屬於要件所說的 "controls that an untrusted consumer could manipulate"。AWS 文件也寫得很清楚:
When you don't specify WriteAttributes for an app client, the app client has write access to all standard and custom attributes. Users can change the value of these attributes for themselves with UpdateUserAttributes. Your application or identity pool might make authorization decisions based on an attribute. In that case, remove the attribute from the WriteAttributes of every app client in your user pool.
Working with user attributes(Amazon Cognito)
Cognito 屬性的寫入權限,我已經整理在之前文章的檢查清單第 (2) 點。
Verify that self-contained tokens are validated using their digital signature or MAC to protect against tampering before accepting the token's contents.
這是 Lambda 在使用 ID 權杖內容(角色與公司)時,沒有先檢查簽章、發行者與期限的案例。即使以為已在 API Gateway 的授權器檢查過,只要有不經授權器直接到 Lambda 的路徑,偽造的權杖內容仍然會通過。應該在使用內容的地方驗證,或只使用授權器已驗證過的值。期限檢查則記在 ASVS 同章的 9.2.1(L1)。
第一件是議程資料上傳時,沒有限制檔案種類與 Content-Type。若上傳 HTML 檔,打開資料連結的人會在瀏覽器中以 HTML 顯示。
Verify that when the application accepts a file, either on its own or within an archive such as a zip file, it checks if the file extension matches an expected file extension and validates that the contents correspond to the type represented by the extension.(5.2.2 開頭)
Possible controls could include: not serving the content unless HTTP request header fields (such as Sec-Fetch-*) indicate it is the correct context, using the sandbox directive of the Content-Security-Policy header field or using the attachment disposition type in the Content-Disposition header field.(3.2.1 後半)
做法是把副檔名縮到允許清單;如果使用簽署網址,也要把 Content-Type 與 Content-Disposition 一併簽入,讓上傳者無法更改。
第二件是取出資料時,對使用者傳入的 key 即使含有 .. 也沒有擋下來。
Verify that when the application creates file paths for file operations, instead of user-submitted filenames, it uses internally generated or trusted data, or if user-submitted filenames or file metadata must be used, strict validation and sanitization must be applied.(5.3.2 開頭)
key 應由伺服器端依預約 ID 等可信值組合而成。
Verify that sensitive data is only sent to the server in the HTTP message body or header fields, and that the URL and query string do not contain sensitive information, such as an API key or session token.
這是外部服務登入時,將密碼與 client_secret 放在 URL 查詢字串裡,還把那個 URL 記錄到 log 的案例。只要能讀 log 的人,就能拿到外部服務的憑證。寫出這些資訊的要件(16.2.5)屬於 L2。
下面 6 件只對應到 L2 的要件。它們都是會因系統型態而改變重要性的項目。
Verify that the application ensures that field-level access is restricted to consumers with explicit permissions to specific fields to mitigate broken object property level authorization (BOPLA).
Verify that multi-tenant applications use cross-tenant controls to ensure consumer operations will never affect tenants with which they do not have permissions to interact.(8.4.1)
這種情況是,公司資料回傳的 API,除了其他公司也能看到的公司名稱之外,還回傳了管理者個人的聯絡方式,以及公司內部設定。是否能看這筆資料,和是否能看這個欄位,是兩回事。BOPLA 指的就是少了欄位粒度的確認。
第 2 章 ASVS 8.2.2 的 6 件裡也有 5 件是會碰到其他公司的資料。雖然都符合 8.2.2,但明確要求不能跨租戶的是 L2 的 8.4.1。若系統是多公司共用,最好從設計階段就把 8.4.1 納入需求,這樣每個入口該檢查什麼就會清楚。
Verify that the application has countermeasures to protect against mass assignment attacks by limiting allowed fields per controller and action, e.g., it is not possible to insert or update a field value when it was not intended to be part of that action.
這是預約更新時,連畫面沒有送出的欄位也從本文接收並儲存的情況:
{ "title": "定期會議", "status": "approved", "approved_by": "user-0001" }
畫面明明只送 title,但一旦加上 status 與 approved_by,就可能把它變成已核准。做法是針對每個入口明確決定可接收的欄位,其餘全部拒絕。
Verify that anti-automation controls are in place to protect against excessive calls to application functions that could lead to data exfiltration, garbage-data creation, quota exhaustion, rate-limit breaches, denial-of-service, or overuse of costly resources.
這是預約通知的 Email/SMS 可以無上限重送的案例。每送一次都會產生成本,也會讓接收者收到惱人的通知。加上上限後檢查時,又發現計數沒有做鎖定,所以同時呼叫時還可能突破上限。上限不只要有,連計數方式也要一併驗證。
Verify that a code based out-of-band authentication mechanism is protected against brute force attacks by using rate limiting. Consider also using a code with at least 64 bits of entropy.
登入第二步要用 Email 收到的驗證碼時,應用程式 API 有在統計錯誤次數,但直接呼叫 Cognito API 的路徑卻沒有計數。只知道密碼的人,可以無限次嘗試驗證碼。Cognito 驗證流程的縮減方法,整理在前面提到的 Cognito 文章第 (4) 點。
Verify that, if the application supports multiple identity providers (IdPs), the user's identity cannot be spoofed via another supported identity provider (eg. by using the same user identifier). The standard mitigation would be for the application to register and identify the user using a combination of the IdP ID (serving as a namespace) and the user's ID in the IdP.
這是 SSO 第一次登入的人,因為從 IdP 收到的公司名稱相同,就被歸到同一家公司的情況。只要名稱一樣,就會被當成同一家公司。依照要件,應該用「來自哪個 IdP」與「該 IdP 內的使用者 ID」組合來辨識。
Verify that a secrets management solution, such as a key vault, is used to securely create, store, control access to, and destroy backend secrets.(13.3.1 開頭)
這是把外部服務的連線資訊做成設定檔放進 S3 bucket,而那個 bucket 竟然能從部分 IP 範圍匿名讀取的案例。連線資訊應該放在像 AWS Secrets Manager 這樣的機密管理機制中。
ASVS 是針對應用程式需求,所以雲端設定與已棄用 API 的收尾,並不會直接寫進去。剩下的 3 件,在 AWS 文件與 OWASP API Security Top 10 裡有寫到。
這是允許 API Gateway 呼叫 Lambda 時,沒有把來源 API 限制住的案例。其他 AWS 帳號的 API Gateway 也能呼叫這個函式。IAM 文件建議在替 AWS 服務授權時,加上來源條件。
We recommend using aws:SourceArn, aws:SourceAccount, aws:SourceOrgID, or aws:SourceOrgPaths in your resource policies wherever an AWS service principal is granted permission to access one of your resources.
The confused deputy problem(AWS IAM)
ASVS 類似的內容是,要求後端元件之間的通訊要有驗證與最小權限的 13.2.1、13.2.2(L2),但沒有明確寫到被呼叫端要限制來源。
正式環境與非正式環境在同一個 AWS 帳號裡,而從跳板角色可以讀到所有環境的機密值。AWS 白皮書把多帳號的好處之一列為能把正式與非正式環境分開。
By using separate accounts for the non-production and production environments, by default, the resources and data that make up a workload environment are separated from other environments and workloads.
Benefits of using multiple AWS accounts(AWS 白皮書)
重構之後,修正前的 API Gateway 與 Lambda 函式還在運作,導致可以不經過修正後的路徑直接呼叫。OWASP API Security Top 10 2023 的 API9(Improper Inventory Management)有提到這種情況。
Threat agents usually get unauthorized access through old API versions or endpoints left running unpatched and using weaker security requirements.
API9:2023 Improper Inventory Management(OWASP API Security Top 10)
ASVS 中接近的是 6.3.4(L2),它要求如果驗證路徑有多條,就不能有未記錄的路徑。這次的情況不只是驗證,連 API 本身都把修正前的版本整包留著,所以我把它算到 API9。
21 件裡有 18 件能對上 ASVS,剩下的 3 件也都寫在 AWS 文件與 OWASP API Security Top 10 裡。既然文件上有寫,就能在開始做之前先寫進需求。ASVS 本身也把在採購時指定 ASVS 等級列為一種用法。
The buyer can simply set a requirement that the software they wish to procure must be developed at ASVS level X, and request that the seller proves that the software satisfies ASVS level X.
What is the ASVS?(OWASP ASVS 5.0.0)
數位發展部的 Security by Design 指南(DS-200)也在需求定義流程的工作內容裡,列出要根據應遵循的標準與風險分析結果來決定安全需求。這是給政府資訊系統參考的文件,並非強制遵循。
遵守すべきセキュリティ標準(セキュリティベースライン)やリスク分析結果等に基づく、システムとして満たすべきセキュリティ要件の定義(4.2 の「セキュリティ要件定義」の実施内容から)
DS-200 政府資訊系統的 Security by Design 指南(數位發展部,2024 年 1 月 31 日)
只要在需求中寫清楚,設計與實作階段就能逐項確認是否符合。這次的 21 件是實作後的診斷才找出來的,沒有實際驗證如果在設計階段檢查是否能預防。
如果只指定「L1」,那麼 21 件裡有 9 件找不到對應要件。L2 裡哪些要件有用,會隨系統型態改變,很難事先挑好。若是多公司共用、會處理個資等資安要求較高的服務,即使加上 L1 共 253 項也很多,仍然值得指定到 L2。ASVS 本身也表示,目標等級不是由 ASVS 規定,而是由組織根據風險分析、應用程式的敏感度與使用者期待來決定。
Rather than the ASVS prescriptively stating what level an application should be at, an organization should analyze its risks and decide what level it believes it should be at, depending on the sensitivity of the application and of course, the expectations of the application's users.
What is the ASVS?(OWASP ASVS 5.0.0)
ASVS 5.0 也有非官方日文版。選要件時可以和原文對照閱讀。
OWASP 應用程式安全驗證標準 5.0 日文版(非官方,coky-t/owasp-asvs-ja)
第 4 章的 3 件(Lambda 呼叫允許條件、帳號分離、舊 API 殘留)都不屬於 ASVS 要件。若是 AWS,先以 Security Hub CSPM 的 AWS Foundational Security Best Practices(FSBP)做自動設定檢查,會比較方便。
AWS Foundational Security Best Practices standard in Security Hub CSPM
不過,就我查看的 FSBP 中 Lambda、API Gateway、帳號與 IAM 項目來看,沒有對應到這次 3 件的檢查。像 Lambda.1 檢查函式政策時,也只有公開存取,以及從 S3 呼叫但沒有條件限制這些情況才會判定失敗。
The control fails if public access is permitted. The control also fails if a Lambda function is invoked from Amazon S3, and the policy doesn't include a condition to limit public access, such as AWS:SourceAccount.
Security Hub CSPM controls for AWS Lambda
因此,除了 FSBP 之外,還要把以下 3 個也列為遵循對象:
SEC01-BP01 Separate workloads using accounts(AWS Well-Architected)
OWASP Top 10 API Security Risks – 2023
這次診斷的觀點,是從公司內部自行維護的檢查清單整理出來的。不過,是否涵蓋完整,以及之後的維護方式,仍有問題。如果改用像 ASVS 這樣的指南當作觀點,也能找出差不多數量的指摘,那就更容易證明覆蓋範圍,也能把維護工作交給外部。下一步想試試看:把 ASVS 的 L1 與 L2 原封不動當成觀點,看看這 21 件能抓到多少。
最後,GMO Connect 除了服務開發支援與技術支援之外,也提供多方面的協助,若有需要,歡迎隨時聯絡我們。
聯絡我們:https://gmo-connect.jp/contactus/