#standards#security#lessons#auth#multi-tenant#bugs
บทเรียนบั๊กสิทธิ์และการข้ามฐานข้อมูล
รวมบั๊กที่ตรวจพบและแก้แล้วในรอบ 2026-10-24 (branch dev) ด้านการยืนยันตัวตน การแบ่งสิทธิ์ และการแยกฐานข้อมูล พร้อมกฎที่ต้องจำ เช็กลิสต์ใช้งานจริงอยู่ที่ เช็กลิสต์ความปลอดภัย API: ตัวตน สิทธิ์ และช่องโหว่เว็บ (Secure API Checklist)
บั๊ก → วิธีแก้ → กฎที่ต้องจำ
| รหัส | อาการ | วิธีแก้ | กฎ |
|---|---|---|---|
| S1 | POST /api/auth/google ที่ส่งแค่ email ก็ได้ session ของเจ้าของฐานข้อมูล (ไม่มี idToken) |
บังคับ idToken, ตรวจ aud และ email_verified |
ตัวตนต้องมาจากข้อมูลที่ตรวจแล้ว ห้ามเชื่อ body |
| S2 | GET/PUT screen-rights, GET members ตรวจแค่มี session แต่เรียก backend ด้วยกุญแจ Admin → Member ให้สิทธิ์จอตัวเองเต็มได้ |
isWorkspaceAdmin() ตรวจว่าเป็น Admin ของฐานนั้นจริง (Demo ถูกปฏิเสธ) |
route ที่ใช้กุญแจ Admin ต้องตรวจ Admin ฝั่ง server |
| B1 | /blob/insert ข้ามนโยบาย write lockdown → ผู้ใช้ระดับ 1 เขียนตาราง sml_user_list / gl_journal_detail ได้ |
ใช้ ValidateClientInsert() ตัวเดียวกับ /query/exec |
ทุกทางเขียนจากเบราว์เซอร์ใช้นโยบายเดียวกัน |
| B2 | route แผนที่ไม่ต้อง login แต่ ?db= เลือกฐานข้อมูลบริษัทได้ |
ผู้ไม่ login ถูกตรึงที่ smldemo |
ห้ามให้ผู้เรียกเลือก tenant เองเมื่อไม่ยืนยันตัวตน |
รอบที่ 2: เสริมเกราะ Auth/API
getAdminApiKey()ไม่ส่งกุญแจ dev ใน production (ตอบ 503NO_ADMIN_API_KEY)- Google OAuth redirect มี
state(cookie +timingSafeEqual) กัน login CSRF /api/auth/databasesตรวจว่าฐานข้อมูลอยู่ในavailableCompaniesของผู้ใช้/api/admin/*ใช้requireSystemAdmin()(ต้องsession.mode === "admin");/api/fraudwarning|workmonitorต้องมี session;/api/monitormap/tilePOST ต้อง login และ single-flightPOST /api/workspace/databasesใช้session.emailเท่านั้น (ไม่รับอีเมลจาก client)
รอบที่ 3 และการตัดสินใจของลุงจืด (2026-10-24)
- สิทธิ์จอแยกต่อฐานข้อมูล: เพิ่มคอลัมน์
database_nameในsml_permissions_user/sml_permissions_group; Backend บังคับสิทธิ์ Add/Edit/Delete บน/process/*(doc/save,stocktools/pointdocsave,stocktools/stockbeginningsave),/query/exec,/query/execBatch,/blob/insert; ฝั่งหน้าจอผูกuseScreenRights()ทุกจอ (เดิมTabsContext.screenRightsบังคับแค่ฝั่งหน้าจอ backend ต้องตรวจซ้ำเสมอ) — ไฟล์ที่เกี่ยวข้องadmin/menu_permissions.go,admin/workspace_google.go - โหมดสาธิตดูระบบส่วนกลางได้แต่ห้ามเพิ่ม/แก้ไข/ลบ:
isDemoCentralViewer()(ปุ่ม Demo, โดเมนสาธิต, บัญชีสาธารณะของsmldemo); GET ใช้requireSystemAdminView()+ ล็อก providersmldemo+ ตัดฟิลด์ลับ (demoSafe); เขียนทุกชนิดได้ 403DEMO_READ_ONLY; โซน/adminมีแถบ "ดูอย่างเดียว" - Login ผู้ดูแลส่วนกลาง (
mode: "admin") แยกจากปุ่ม Google และปฏิเสธบัญชีสาธิต (DEMO_ADMIN_FORBIDDEN); เปลี่ยนรหัสผ่านตัวเอง ผ่าน/api/auth/change-passwordตรวจรหัสเดิมก่อน (บัญชี Google ให้ไปเปลี่ยนที่ Google)
ที่มา
docs/kms/KMS_SECURITY_DATA_INTEGRITY_LESSONS.mdตาราง S1–S2, B1–B2, รอบที่ 2–3, "การตัดสินใจของลุงจืด" ข้อ 1, 3- ตรวจแล้วมีจริง:
frontend/src/app/api/workspace/[...path],frontend/src/app/api/auth/change-password/route.ts,backend/.../admin/menu_permissions.go,blob/handler.go
ดูเพิ่ม
สารบัญมาตรฐานและกฎเหล็กของ SML Ai Account (Standards Overview) · เช็กลิสต์ความปลอดภัย API: ตัวตน สิทธิ์ และช่องโหว่เว็บ (Secure API Checklist) · Google Login, Multi-Tenant PDPA และหน้าเลือกโมดูลหลัง Login (Google OAuth, Tenant Isolation, Home Hub) · ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch) · ภาพรวม Backend Go ของ SML Ai Account (Backend overview)