提出 #1033603: https://github.com/201206030/ novel 3.5.0 Missing Authorization情報

タイトルhttps://github.com/201206030/ novel 3.5.0 Missing Authorization
説明require purchase entitlement before returning VIP chapter content- #52 ## Summary `BookServiceImpl.getBookContentAbout(chapterId)`, reachable via the public `GET /api/front/book/content/{chapterId}` endpoint, returns the full chapter body unconditionally regardless of the chapter's `isVip` flag. Authentication on this endpoint is optional (`TokenParseInterceptor` only parses a JWT if one is present, never requires it), so any caller, including an anonymous one, can read paid chapter content for free. `isVip` is only ever used for display purposes elsewhere in this class (badging a chapter as VIP in list/metadata responses), never consulted for an access decision. `user_consume_log`, the purchase-record table, has zero service-layer callers anywhere in the codebase: the backend implements no payment-gating logic for VIP chapters at all, despite `isVip` existing specifically to mark them and the project's own feature list advertising recharge/subscription ("充值订阅"). ## Details ```java @Override public RestResp<BookContentAboutRespDto> getBookContentAbout(Long chapterId) { log.debug("userId:{}", UserHolder.getUserId()); // 查询章节信息 BookChapterRespDto bookChapter = bookChapterCacheManager.getChapter(chapterId); // 查询章节内容 String content = bookContentCacheManager.getBookContent(chapterId); ... return RestResp.ok(BookContentAboutRespDto.builder() .bookInfo(bookInfo) .chapterInfo(bookChapter) .bookContent(content) .build()); } ``` No check of `bookChapter.getIsVip()`, no check of `UserHolder.getUserId()` (which stays `null` for any request with no `Authorization` header), and no check of any purchase record precedes returning `content`. ## Proof of Concept 1. As any author (or via direct DB insert for testing), publish a book with a chapter marked `is_vip = 1` and non-empty content. 2. As a completely anonymous caller, with no `Authorization` header at all: ```bash curl -s http://localhost:8080/api/front/book/content/<chapterId> ``` 3. The response is `200 OK` with the full VIP chapter text in `data.bookContent`, despite no token, no purchase, and no subscription of any kind. 4. With the fix applied, the same anonymous request instead returns: ```json {"code":"A0301","message":"访问未授权"} ``` 5. Repeating step 2 as an *authenticated* user who has never purchased the chapter (a valid JWT, no `user_consume_log` row for this `chapterId`) produces the same `A0301` rejection. Only a request from a user with a matching `user_consume_log` row (`user_id`, `product_type = 0`, `product_id = <chapterId>`) receives the content. ## Impact Any deployment of this project that marks chapters as paid (`is_vip = 1`) has no server-side enforcement of that restriction at all: the entire revenue-gating feature is bypassable by anyone, with or without an account, via a single unauthenticated GET request. ## Fix `getBookContentAbout` now requires, for a VIP chapter, that the caller is authenticated and has a matching `user_consume_log` row for that specific chapter. Since no code path currently writes such a row, this correctly denies every caller for now, while recognizing entitlement the moment a purchase flow (or an administrator) starts writing these rows. ## Testing Live-validated end to end against real MySQL + Redis (no project test suite exists for this service layer, same as the prior #51 review of this repo): planted a VIP chapter's content, confirmed an anonymous request returned it in full before the fix and was rejected (`A0301`) after; confirmed an authenticated-but-non-purchasing user is also rejected; confirmed inserting a matching `user_consume_log` row grants access; confirmed a non-VIP chapter is unaffected throughout.
ソース⚠️ https://github.com/201206030/novel/pull/52
ユーザー
 carfeii (UID 97470)
送信2026年10月14日 14:55 (23 日 ago)
モデレーション2026年11月06日 10:38 (23 days later)
ステータス承諾済み
VulDBエントリ431793 [xxyopen/201206030 novel 迄 3.5.0 Book Content Service BookServiceImpl.java BookServiceImpl.getBookContentAbout chapterId 特権昇格]
ポイント20

Do you want to use VulDB in your project?

Use the official API to access entries easily!