فهرست مطالب (6)
بعضی باگهای امنیتی بهقدری سادهاند که اول باورتان نمیشود کار کنند. آسیبپذیری تازهٔ TokenGuard در لاراول از همین دسته است: مهاجم بهجای یک توکن واقعی، یک آرایه با عدد صفر میفرستد و سیستم او را با حساب یک کاربر واقعی وارد میکند.
این آسیبپذیری با شناسهٔ CVE-2026-114509 و امتیاز ۹.۲ ثبت شده است. نسخههای اصلاحشدهٔ لاراول اواخر اوت بیسروصدا منتشر شده بودند، ولی جزئیات عمومی تازه ۱۹ اکتبر اعلام شد. حالا که همه میدانند باگ کجاست، پروژههایی که بهروز نشدهاند در معرض خطرند.
چه کسانی درگیرند
همهٔ پروژههای لاراولی درگیر نیستند. پروژهٔ شما در خطر است اگر هر سه شرط زیر برقرار باشد:
- **در
config/auth.phpگاردی با'driver' => 'token'دارید.** این همان گارد قدیمی و سادهای است که توکن را در یک ستون جدول کاربران نگه میدارد. - دیتابیستان MySQL یا MariaDB است.
- نسخهٔ لاراول پایینتر از 12.68.0 یا 13.29.0 است.
Sanctum و Passport درگیر این آسیبپذیری نیستند. ولی یک نکته را دستکم نگیرید: تا لاراول ۷، گارد api در اسکلت پروژههای تازه بهطور پیشفرض همین درایور token بود. پروژههایی که از آن زمان چند بار ارتقا گرفتهاند، ممکن است هنوز همان تنظیم را داشته باشند، حتی اگر کسی دیگر یادش نباشد.
باگ دقیقاً کجا بود
TokenGuard پیش از اصلاح فقط بررسی میکرد که توکن «خالی» نباشد. اما در PHP، یک آرایهٔ یکعضوی مثل [0] از نظر تابع empty() خالی نیست. وقتی مهاجم بدنهٔ درخواست را بهصورت JSON و با یک آرایه میفرستد، این آرایه از بررسی رد میشود و به لایهٔ دیتابیس میرسد.

در لایهٔ دیتابیس، Eloquent برای ورودی آرایهای از whereIn() استفاده میکند و کوئری به چیزی شبیه api_token in (0) تبدیل میشود. اینجا رفتار MySQL وارد ماجرا میشود: وقتی یک رشته با یک عدد مقایسه میشود، MySQL رشته را به عدد تبدیل میکند. رشتهای که با حرف شروع شود به صفر تبدیل میشود، و صفر با صفر برابر است. نتیجه این است که کوئری اولین کاربری را برمیگرداند که توکنش با حرف شروع شده، و گارد او را احراز هویتشده حساب میکند.
درخواست مهاجم چیزی بیشتر از این نیست:
POST /api/orders HTTP/1.1
Content-Type: application/json
{"api_token": [0]}
اصلاح چه بود
اصلاح لاراول در یک خط خلاصه میشود: پیش از رفتن سراغ دیتابیس، با is_string() بررسی میشود که توکن واقعاً رشته باشد. اگر نباشد، درخواست همانجا رد میشود.
// The idea behind the fix, in short.
if ( ! is_string( $token ) || $token === '' ) {
return null;
}
الان چه کنید
- لاراول را بهروز کنید. با
composer update laravel/frameworkبه نسخهٔ 12.68.0 یا 13.29.0 یا بالاتر بروید. نسخهٔ 11.56.1 هم همین بررسی را دارد، هرچند در اطلاعیهٔ رسمی نیامده است. - **
config/auth.phpرا نگاه کنید.** اگر جایی'driver' => 'token'دارید، اولویت این پروژه بالاست، بهخصوص اگر روی MySQL یا MariaDB است. - اگر روی لاراول 9 یا 10 هستید، طبق گزارشها تا ۲۱ اکتبر این شاخهها هنوز اصلاح نشده بودند. یا به نسخهٔ پشتیبانیشده ارتقا دهید، یا گارد را به Sanctum منتقل کنید.
- **
composer auditرا به چرخهٔ کارتان اضافه کنید.** این دستور آسیبپذیریهای شناختهشدهٔ وابستگیها را فهرست میکند و جایش در CI است، نه فقط در روزهای بحران.
درسی که فقط مال لاراول نیست
این باگ یادآوری خوبی است که «ورودی کاربر همیشه رشته است» فرضی غلط است. هر چیزی که از JSON یا یک فرم میآید ممکن است آرایه، عدد یا null باشد. وقتی همین ورودی به دیتابیسی برسد که بیسروصدا نوعها را به هم تبدیل میکند، نتیجه میتواند دور زدن کامل احراز هویت باشد.
قاعدهٔ سادهاش این است: نوع ورودی را همان اول، صریح بررسی کنید. در لاراول، قانون اعتبارسنجی string همین کار را میکند. در وردپرس هم وقتی مسیر REST میسازید، برای هر آرگومان 'type' => 'string' بگذارید. یک خط کد است، ولی جلوی یک دستهٔ کامل از باگها را میگیرد.
منابع
$ ./request_review
همین مشکل را در فروشگاه خودتان دارید؟
توسعهدهنده ارشد WordPress و WooCommerce برای معماری، اتصال سیستمها و حل مسائل پیچیده production.
درخواست بررسی فنی
## دیدگاهها