یک چت‌بات در صفحه‌ی پشتیبانی، یک دستیار داخل ابزار سازمانی، یا عاملی که خودش تیکت ثبت می‌کند؛ همه‌ی این‌ها پیش از هر چیز برنامه‌اند و بعد مدل زبانی. بیشتر مشکلات امنیتی‌شان هم از خودِ مدل نیست. از برنامه‌ای است که به خروجی مدل اعتماد می‌کند، یا بیش از نیاز کار به آن دسترسی می‌دهد، یا اجازه می‌دهد متنِ نامطمئن از دری به مدل برسد که کسی در نمودار معماری نکشیده است.

تست نفوذ این برنامه‌ها باید روی همین نقطه تمرکز کند. ارزیابی معمول وب هنوز برای هر چیزی که دور مدل ساخته شده لازم است. آنچه از دستش می‌رود جایی است که دستور و داده از یک کانال می‌گذرند.

برنامه‌ی مبتنی بر LLM چه فرقی دارد

در یک برنامه‌ی معمولی کد و داده از هم جدا هستند: پرس‌وجوی SQL و مقداری که درون آن قرار می‌گیرد قابل تفکیک‌اند، و به همین دلیل پرس‌وجوی پارامتری جواب می‌دهد. مدل زبانی اما دستورهای خود (پرامپت سیستمی)، پیام کاربر، اسناد بازیابی‌شده و نتیجه‌ی ابزارها را یک‌جا و به‌صورت یک جریان متن دریافت می‌کند و راه مطمئنی ندارد که دستور را از محتوایی که فقط شبیه دستور است تشخیص دهد.

این واقعیت سه پیامد دارد که هر آزمونی را شکل می‌دهد:

  • هر کسی که بتواند متنی جلوی مدل بگذارد، می‌تواند برای هدایت آن تلاش کند. فقط کاربری نیست که در پنجره‌ی گفت‌وگو تایپ می‌کند؛ نویسنده‌ی هر صفحه‌ی وب، ایمیل، فایل PDF یا تیکتی هم هست که برنامه بازیابی می‌کند.
  • خروجی مدل برای هر چیزی که از آن استفاده می‌کند ورودیِ نامطمئن است: مرورگری که نمایشش می‌دهد، پرس‌وجویی که از آن ساخته می‌شود، ابزاری که مدل فراخوانی می‌کند.
  • رفتار مدل احتمالاتی است. یک حمله ممکن است در تلاش سوم موفق شود و در تلاش چهارم نه، و به‌روزرسانی مدل می‌تواند نتیجه را یک‌شبه عوض کند.

محدوده: اول جریان داده را رسم کنید

پیش از هر آزمونی مشخص کنید متن از کجا وارد زمینه‌ی مدل (context) می‌شود و خروجی مدل به کجا می‌رود. در بیشتر برنامه‌ها این فهرست چنین است:

  • پرامپت سیستمی، و این‌که چه کسی می‌تواند تغییرش دهد؛
  • ورودی کاربر، از جمله فایل‌ها و تصاویر بارگذاری‌شده؛
  • بازیابی (RAG): کدام مخزن اسناد، و اسناد چه کسانی؛
  • ابزارها و فراخوانی توابع: هر کدام چه کاری می‌تواند بکند و با دسترسی چه کسی؛
  • حافظه یا تاریخچه‌ی گفت‌وگو، و این‌که بخشی از آن میان کاربران مشترک است یا نه؛
  • مقصدهای خروجی: نمایش در مرورگر، ارسال با ایمیل، ذخیره در پایگاه داده، اجرا؛
  • ارائه‌دهنده، نسخه و تنظیمات مدل، و هر افزونه یا مؤلفه‌ی شخص ثالث.

هر پیکانی در این نقشه که از یک مرز اعتماد عبور کند، یک مورد آزمون است. خط لوله‌ی بازیابی‌ای که اسناد ارسالیِ مشتریان را نمایه می‌کند مرز اعتماد است، حتی اگر خودِ پنجره‌ی گفت‌وگو فقط داخلی باشد.

هشت حوزه‌ای که باید آزمون شود

فهرست OWASP Top 10 for LLM Applications 2025 مرجعی است که بیشتر تیم‌ها یافته‌هایشان را به آن نگاشت می‌کنند. بر اساس آنچه در عمل آزمون می‌شود:

۱. تزریق پرامپت، مستقیم و غیرمستقیم (LLM01)

تزریق مستقیم یعنی کاربر به مدل بگوید دستورهایش را نادیده بگیرد. تزریق غیرمستقیم همان دستور است که در محتوایی پنهان شده که مدل بعداً می‌خواند: یک خط متنِ سفید در صفحه‌ی وب، یادداشتی در یک سند، یا فیلدی در تیکت پشتیبانی. برای بیشتر برنامه‌های سازمانی نوع غیرمستقیم مهم‌تر است، چون مهاجم حتی به حساب کاربری نیاز ندارد.

هر دو را آزمون کنید. در هر منبعی که برنامه بازیابی می‌کند دستور بکارید و ببینید مدل از آن پیروی می‌کند یا نه. همه‌ی زبان‌هایی را که برنامه می‌پذیرد امتحان کنید: فیلتری که با متن انگلیسی تنظیم شده ممکن است همان دستور را به فارسی، به فینگلیش یا با ترکیب دو خط نبیند.

۲. نشت پرامپت سیستمی (LLM07)

فرض کنید پرامپت سیستمی استخراج می‌شود؛ معمولاً می‌شود. یافته‌ی اصلی به‌ندرت خودِ نشت است. محتوای پرامپت است: یک کلید API، یک نشانی داخلی، فهرست مشتریان، یا قواعد کسب‌وکاری که برنامه تنها کنترل دسترسی‌اش را به آن‌ها سپرده. آزمون، بازیابی پرامپت است و توصیه تقریباً همیشه این است که راز یا قاعده از پرامپت بیرون برود.

۳. افشای اطلاعات حساس (LLM02)

دنبال داده‌ای بگردید که مدل به آن دسترسی دارد ولی کاربر فعلی نباید داشته باشد: اسناد مشتری دیگر در یک نمایه‌ی مشترک، داده‌ی شخصی که بازیابی به زمینه آورده، گفت‌وگوهای قبلی در حافظه‌ی مشترک، رازهایی که در پاسخ ابزارها برمی‌گردند، و لاگ‌هایی که پرامپت و پاسخ را کامل ذخیره می‌کنند.

۴. مدیریت نادرست خروجی (LLM05)

با خروجی مدل دقیقاً مثل ورودی کاربر رفتار کنید. اگر برنامه آن را به‌صورت HTML نمایش می‌دهد، XSS را آزمون کنید؛ اگر از آن پرس‌وجو یا فرمان سیستمی می‌سازد، تزریق را. نمونه‌ی شناخته‌شده‌ای وجود دارد: مدل وادار می‌شود تصویری با قالب Markdown بنویسد که نشانی‌اش داده‌ی گفت‌وگو را به سرور مهاجم می‌برد. مرورگر تصویر را بارگذاری می‌کند و داده بی‌آن‌که کسی کلیک کند بیرون می‌رود.

۵. اختیار بیش از حد (LLM06)

برای هر ابزاری که مدل می‌تواند فراخوانی کند سه پرسش بپرسید. آیا کار اصلاً به این ابزار نیاز دارد؟ آیا ابزار بیش از نیاز کار دسترسی دارد؟ آیا کاری برگشت‌ناپذیر بدون تأیید یک انسان انجام می‌شود؟ عاملی که هم ایمیل می‌خواند و هم می‌فرستد، با یک تزریق غیرمستقیم تا ارسال کل صندوق ورودی به بیرون فاصله دارد.

۶. ضعف‌های بردارها و embeddingها (LLM08)

بازیابی به همان کنترل دسترسیِ اسنادی نیاز دارد که نمایه می‌کند؛ کنترلی که هنگام واکشی نتایج اعمال شود، نه با خواهش از مدل که رازدار باشد. آزمون کنید آیا کاربر می‌تواند بخش‌هایی از اسنادی را بازیابی کند که اجازه‌ی باز کردن مستقیمشان را ندارد، و آیا کسی که می‌تواند سندی به نمایه اضافه کند می‌تواند پاسخ‌ها را برای بقیه آلوده کند.

۷. مصرف بی‌حد (LLM10)

مدل زبانی به ازای هر توکن و هر ثانیه پردازش هزینه دارد. درخواست‌هایی را آزمون کنید که صورت‌حساب بزرگی می‌سازند یا ظرفیت را اشغال می‌کنند: ورودی‌های بسیار طولانی، پرامپت‌هایی که خروجی طولانی یا حلقه‌ای از فراخوانی ابزار راه می‌اندازند، و نبودِ محدودیت نرخ و سقف هزینه برای هر کاربر.

۸. زنجیره‌ی تأمین، مسموم‌سازی و اطلاعات نادرست (LLM03، LLM04، LLM09)

بررسی کنید مدل‌ها، adapterها، افزونه‌ها و مجموعه‌داده‌ها از کجا می‌آیند و نسخه‌شان چطور ثابت شده است. جایی که پاسخ‌های برنامه مبنای تصمیم است، ببینید وقتی مدل با اطمینان اشتباه می‌کند چه اتفاقی می‌افتد. برای نمونه، دستیارهای کدنویسی گاهی بسته‌هایی را پیشنهاد می‌کنند که وجود ندارند، و مهاجم می‌تواند همان نام را ثبت کند.

آزمون را چطور اجرا کنیم

  1. یک نسخه‌ی آزمایشی با داده‌ی واقعی‌نما و همه‌ی یکپارچگی‌های فعال بگیرید. آزمونِ تنها پنجره‌ی گفت‌وگو بازیابی، ابزارها و مقصدهای خروجی را جا می‌اندازد؛ همان جاهایی که بیشتر یافته‌های واقعی در آن‌هاست.
  2. ابزار و کار دستی را کنار هم به کار ببرید. اسکنرهای متن‌بازی مثل garak، PyRIT و promptfoo jailbreakها و الگوهای شناخته‌شده‌ی تزریق را سریع و تکرارپذیر پوشش می‌دهند. یافته‌هایی که بیشترین اهمیت را دارند، مثل تیکتی آلوده که عامل را به فراخوانی ابزار بازپرداخت وامی‌دارد، از کسی می‌آیند که منطق کسب‌وکار برنامه را می‌فهمد.
  3. هر تلاش را تکرار کنید و نرخ موفقیت را ثبت کنید. هر حمله‌ی مهم را بارها اجرا کنید و گزارش دهید چند بار موفق شد، همراه با نسخه و تنظیمات مدلی که به کار رفت.
  4. اصلاح را آزمون کنید، نه پرامپت را. تغییری در پرامپت سیستمی که payload امروز را متوقف می‌کند، به‌ندرت بازنویسیِ فردای همان payload را متوقف می‌کند. پیش از بستن یک یافته، با شکل‌های دیگر دوباره آزمون کنید.

یک یافته باید چه چیزهایی داشته باشد

علاوه بر فیلدهای معمول، که در گزارش تست نفوذ باید شامل چه چیزهایی باشد؟ آمده‌اند، یافته‌ی یک برنامه‌ی مبتنی بر LLM به این‌ها هم نیاز دارد:

  • ورودی دقیق، و این‌که از کجا وارد شد: گفت‌وگو، فایل بارگذاری‌شده، سند بازیابی‌شده یا نتیجه‌ی ابزار؛
  • مدل، نسخه و تنظیمات به‌کاررفته، و تاریخ آزمون؛
  • نرخ موفقیت در تعداد مشخصی تلاش؛
  • اثر با زبان کسب‌وکار: کدام داده بیرون رفت، کدام اقدام اجرا شد؛
  • علت ریشه‌ای، که تقریباً همیشه کنترلی است که بیرون از مدل وجود ندارد.

کنترل‌هایی که واقعاً جواب می‌دهند

پرامپت‌های محافظ و فیلترهای خروجی کمک می‌کنند، اما احتمالاتی‌اند و مهاجم فقط به یک جمله‌بندی نیاز دارد که از آن‌ها رد شود. کنترل‌هایی دوام می‌آورند که به درست رفتار کردن مدل وابسته نیستند:

  • مجوزدهی را در خودِ برنامه اعمال کنید، روی هر فراخوانی ابزار و هر بازیابی، با دسترسی کاربر فعلی؛
  • به هر ابزار کمترین دسترسی لازم برای کارش را بدهید و برای هر کار برگشت‌ناپذیر تأیید انسانی بگیرید؛
  • خروجی مدل را متناسب با مقصدش کدگذاری یا اعتبارسنجی کنید، همان‌طور که با ورودی کاربر می‌کنید؛
  • رازها و قواعد دسترسی را بیرون از پرامپت سیستمی نگه دارید؛
  • محتوای نامطمئن را علامت بزنید و جدا نگه دارید، و اجازه ندهید متن بازیابی‌شده دسترسی اعطا کند؛
  • برای هر کاربر محدودیت نرخ و سقف هزینه بگذارید و سوءاستفاده را پایش کنید.

پرسش‌های رایج

آیا آزمون خودِ مدل کافی است؟ نه. ارزیابی مدل، مدل را جدا از بقیه می‌سنجد. بیشتر ضعف‌های قابل بهره‌برداری در این است که برنامه مدل را چطور به داده و ابزار وصل کرده، پس آزمون باید کل برنامه را پوشش دهد.

ما از API یک مدل تجاری استفاده می‌کنیم؛ امنیتش با ارائه‌دهنده نیست؟ ارائه‌دهنده مسئول امنیت مدل و میزبانی آن است. پرامپت سیستمی، بازیابی، ابزارها و مدیریت خروجی مال شماست، و بیشتر یافته‌ها همان‌جاست.

هر چند وقت یک بار باید دوباره آزمون کرد؟ پس از هر تغییر در مدل یا نسخه‌ی آن، پرامپت سیستمی، ابزارها یا منابع داده، و دست‌کم به اندازه‌ی بقیه‌ی برنامه. ارتقای مدل می‌تواند رفتار را عوض کند، بی‌آن‌که یک خط از کد شما تغییر کرده باشد.