Authentication vs Authorization: เอนด์พอยต์ที่ใครก็เรียกได้
สองคำนี้ฟังดูคล้ายกัน และความแตกต่างระหว่างมันคือจุดที่การเจาะระบบจริง ๆ มักเกิดขึ้น
- Authentication คือ คุณเป็นใคร? — การล็อกอิน การพิสูจน์ตัวตน
- Authorization คือ คุณได้รับอนุญาตให้ทำอะไรได้บ้าง? — ว่าผู้ใช้ที่ล็อกอินอยู่ คนนี้ สามารถทำ การกระทำนี้ กับ ข้อมูลนี้ ได้หรือไม่
AI ทำ authentication ได้ดีพอสมควร เพราะไลบรารีจัดการส่วนใหญ่ให้อยู่แล้ว Authorization ต่างหากที่มันมักล้มเหลวเป็นประจำ เพราะ authorization ขึ้นอยู่กับกฎเฉพาะของแอปคุณ ซึ่ง AI ไม่รู้จัก นี่คือหายนะในตำราเรียน:
// VULNERABLE: checks you're logged in, but not WHO you are
app.get("/admin/export-all-users", requireLogin, (req, res) => {
res.json(db.getAllUsers()); // any logged-in user can hit this
});
เอนด์พอยต์นั้น "ได้รับการป้องกัน" แล้ว — คุณต้องล็อกอินก่อน แต่ผู้ใช้ที่ล็อกอินอยู่ คนไหนก็ได้ รวมถึงคนที่เพิ่งสมัครไปเมื่อสามสิบวินาทีก่อน สามารถเรียกมันและดาวน์โหลดข้อมูลของผู้ใช้ทุกคนได้ มี authentication แต่ไม่มี authorization วิธีแก้คือตรวจสอบสิทธิ์บนการกระทำนั้นโดยตรง:
// SAFE: confirms this user is actually an admin
app.get("/admin/export-all-users", requireLogin, (req, res) => {
if (!req.user.isAdmin) return res.status(403).send("Forbidden");
res.json(db.getAllUsers());
});
ลองนึกภาพประตูสองบานที่คำขอต้องผ่านให้ได้ Authentication ถามว่า "คุณล็อกอินอยู่ไหม?"; authorization ถามว่า "คุณคนนี้ได้รับอนุญาตให้ทำสิ่งนี้ไหม?" การเจาะระบบเกิดขึ้นเมื่อแอปสร้างประตูแรกแต่ลืมสร้างประตูที่สอง:
request ──▶ ┌──────────────────┐ ──▶ ┌──────────────────┐ ──▶ action
│ AUTHENTICATION │ │ AUTHORIZATION │ runs
│ "logged in?" │ │ "may THIS user │
│ │ │ do THIS action?" │
└──────────────────┘ └──────────────────┘
✓ most apps ✗ often missing
build this → the breach
EXAMPLE — /admin/export-all-users
logged-in user ──▶ [auth ✓] ──▶ [ no authz check ] ──▶ ALL users dumped
logged-in user ──▶ [auth ✓] ──▶ [ isAdmin? → 403 ] ──▶ blocked ✓
กับดักเดียวกันปรากฏในรูปแบบย่อ ๆ ได้ทุกที่ เช่น เอนด์พอยต์ที่คืนค่าออเดอร์หมายเลข #1234 โดยไม่ตรวจสอบว่าออเดอร์นั้นเป็นของผู้ใช้ที่ร้องขอหรือไม่ ใครก็สามารถเปลี่ยนหมายเลขใน แล้วอ่านออเดอร์ของคนอื่นได้ กฎที่ไม่หรูหราแต่เด็ดขาดคือ: ตรวจสอบสิทธิ์บนทุกเอนด์พอยต์ที่แตะข้อมูล และอย่าไว้ใจ ID ที่มาจากไคลเอนต์ อย่าคิดว่า URL ที่ซ่อนอยู่จะปลอดภัยเพราะมันถูกซ่อนไว้ — "ไม่มีใครรู้ว่าสิ่งนี้มีอยู่" ไม่ใช่มาตรการรักษาความปลอดภัย