اشکال فرمت رشته - آسیب‌پذیری فرمت رشته - خرابی حافظه

چگونه یک اشکال ساده در رشته فرمت می‌تواند منجر به خرابی حافظه شود (و چگونه آن را در کد خود تشخیص دهید)

اشکال رشته فرمت چیست و چرا هنوز اهمیت دارد؟

A اشکال رشته فرمت زمانی رخ می‌دهد که داده‌های کنترل‌شده توسط کاربر به عنوان رشته فرمت در توابعی مانند ... ارسال شوند. printf، fprintf یا syslog بدون اعتبارسنجی.

به زبان ساده، اشکال رشته قالب‌بندی زمانی رخ می‌دهد که ورودی کاربر به عنوان یک الگوی قالب‌بندی استفاده شود و امکان خواندن یا نوشتن ناخواسته در حافظه را فراهم کند. این امر به ویژه در زبان‌هایی مانند ... خطرناک است. C / C ++، که در آن مشخص‌کننده‌های قالب مانند %s، %x, و %n می‌تواند مستقیماً داده‌های پشته را دستکاری کند.

چرا این موضوع در DevSecOps مدرن اهمیت دارد؟ زیرا این اشکالات هنوز در پایگاه‌های کد فعال یافت می‌شوند، به خصوص در:

  • کامپوننت‌های متن‌باز با کد C قدیمی
  • اتصالات بومی در پایتون، گو یا راست
  • ادغام خودکار کد شخص ثالث در محیط عملیاتی pipelines

تأثیر واقعی است: نشت حافظه، خرابی پشته و حتی اجرای کد از راه دور (RCE)و با این حال، بسیاری از تیم‌ها به اسکنرهای استاتیک اعتماد می‌کنند و این اشکالات را از دست می‌دهند، مگر اینکه صریحاً آنها را بررسی کنند.

مستقیماً به سراغ کد بروید: printf(ورودی کاربر) و خطر

بیایید یک اشتباه رایج را بررسی کنیم:

printf(ورودی کاربر)؛

این جمله‌ی کوتاه، مستقیماً به دردسر ختم می‌شود. اگر ورودی_کاربر شامل چیزی شبیه به %x %x %x % x% %x, دستور می‌دهد printf برای خواندن مقادیر از پشته، که باعث افشای حافظه می‌شود. بدتر از آن، اگر %n گنجانده شده باشد، مهاجم می‌تواند مقادیر دلخواه را در حافظه بنویسد.

این الگو نه تنها داده‌های پشته را نشت می‌دهد، بلکه می‌تواند حافظه را نیز خراب کرده و به اجرای کد از راه دور (RCE) منجر شود. این دقیقاً همان چیزی است که یک آسیب‌پذیری رشته فرمت در عمل به نظر می‌رسد. این آسیب‌پذیری‌ها خطاها یا هشدارهای کامپایلر را ایجاد نمی‌کنند، مگر اینکه پرچم‌ها یا پاک‌کننده‌های خاصی فعال شوند. و در بسیاری از موارد، آنها در بسته‌بندی‌ها یا توابع کاربردی پنهان شده‌اند و باعث می‌شوند که از بررسی‌های تصادفی کد پنهان بمانند.

فساد حافظه ۱۰۱: واقعاً چه چیزی در خطر است

هنگامی که یک fبا سوءاستفاده از اشکال رشته‌ای ormat، مهاجمان می‌توانند:

  • آدرس‌های حافظه و مقادیر پشته را با استفاده از دستور زیر خالی کنید %x or %s
  • متغیرهای پشته را بازنویسی کنید یا آدرس‌ها را با %n
  • ایجاد خطای قطعه‌بندی یا خطاهای منطقی از طریق تخریب حافظه
  • به سمت RCE کامل بچرخید، به خصوص اگر محافظت‌هایی مانند ASLR یا stack canaries به اشتباه پیکربندی شده باشند.

درک چارچوب پشته در اینجا مفید است. printf نمی‌داند انتظار چند آرگومان را داشته باشد؛ کاملاً به رشته‌ی قالب‌بندی متکی است. به همین دلیل است %x در پشته بالا می‌رود و داده‌ها را آشکار یا دستکاری می‌کند. نتیجه از نشت جزئی تا کنترل کامل بر اشاره‌گر دستورالعمل متغیر است.

جایی که اشکالات رشته فرمت در پایگاه‌های کد مدرن پنهان می‌شوند

این آسیب‌پذیری‌ها منحصر به کدهای قدیمی C نیستند. آن‌ها در محیط‌های مدرن نیز کمین کرده‌اند:

  • پایتون (ctypes)، راست (FFI) و گو (cgo) متغیرهایی که با کتابخانه‌های بومی رابط کاربری دارند، اغلب به عنوان پوشش‌های نازک عمل می‌کنند و پارامترها را مستقیماً به توابع آسیب‌پذیر C ارسال می‌کنند.
  • ابزارها و سرویس‌های واسط خط فرمان شخص ثالث، کدهای قدیمی C را بدون بررسی کافی ادغام می‌کنند.
  • بسته‌های ثبت وقایع مانند debug_log(ورودی کاربر) که به صورت داخلی به توابعی به سبک printf مسیر می‌دهند
  • ادغام خودکار مشارکت‌های OSS حاوی الگوهای قدیمی یا اعتبارسنجی حداقلی

یک اشکال در لایه بومی C در آنجا باقی نمی‌ماند؛ بلکه به سمت بالا منتشر می‌شود. اگر یک تابع C مانند log_event(char *msg) ناامن است، فراخوانی آن از طریق پایتون ctypes، زنگ زدگی از طریق خارجی ناامنیا از طریق برو سی‌گو آسیب‌پذیری را به محیط‌های سطح بالاتر منتقل می‌کند.

مشکل چیست؟ این ادغام‌ها رایج هستند و DevSecOps اغلب فرض می‌کند که اتصال‌ها انتزاع‌های امنی هستند. اما اینطور نیست. یک آسیب‌پذیری رشته فرمت در یک لایه از پشته می‌تواند بی‌سروصدا در رابط‌ها منتشر شود، به خصوص زمانی که ماژول‌های بومی بدون اجرای قوی نوع یا پاکسازی ورودی بسته‌بندی شوند. اگر تابع C اصلی آسیب‌پذیر باشد، کد سطح بالاتر آسیب‌پذیری رشته فرمت را به ارث می‌برد.

CI/CD Pipelineچگونه این از بررسی‌های امنیتی شما عبور می‌کند؟

مدرن pipelineبرای سرعت طراحی شده‌اند، اما این سرعت نقاط کوری را ایجاد می‌کند:

  • SAST ابزار به ندرت استفاده از رشته با فرمت پویا را تشخیص می‌دهد، مگر اینکه به طور خاص برای ردیابی داده‌های آلوده پیکربندی شده باشد
  • بررسی‌کنندگان روابط عمومی بر منطق یا سبک تمرکز می‌کنند، نه بر رفتار تابع C که زیربنای آن است
  • CI بسته‌های آسیب‌پذیر را که در ظاهر بی‌خطر به نظر می‌رسند، وارد سیستم می‌کند.
  • اسکنرهای وابستگی اغلب کد بومی یا منطق ورود ناامن را نادیده می‌گیرند

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

ادغام قوانین خاص رشته قالب در CI/CD برای شناسایی و متوقف کردن زودهنگام این اشکالات ضروری است. این به این معنی است که:

  • مسدود کردن کد در جایی که ورودی‌های غیرقابل اعتماد به توابع قالب‌بندی می‌رسند
  • علامت‌گذاری رشته‌های قالب پویا در طول تحلیل استاتیک
  • اجرای این سیاست‌ها به عنوان بخشی از فرآیند ادغام CI شما

بدون این، شما pipeline نسبت به دسته‌ای از آسیب‌پذیری‌ها که می‌توانند منجر به تخریب حافظه و اجرای کد از راه دور (RCE) شوند، مدت‌ها قبل از اینکه کد به مرحله تولید برسد، بی‌توجه است.

تشخیص اشکال: تشخیص عملی با GDB و ابزارهای استاتیک

برای یافتن و تأیید این اشکالات، از ترکیبی از اشکال‌زدایی دستی و تحلیل استاتیک خودکار استفاده کنید.

تحلیل دستی با GDB:

GDB به ویژه زمانی مفید است که به سوءاستفاده از رشته قالب‌بندی مشکوک هستید اما نیاز دارید که نحوه رفتار آن را در زمان اجرا تأیید کنید:

  • استراحت printf یا توابع مرتبط برای بررسی پشته فراخوانی و آرگومان‌ها.
  • به دنبال ناهنجاری‌ها، خواندن غیرمنتظره حافظه، خرابی‌ها هنگام قالب‌بندی یا مقادیر عجیب در پشته باشید.
  • ورودی انتزاعی مانند تکرار %x or %s می‌تواند به شناسایی میزان عمق رشته فرمت در پشته کمک کند.

از دستی تا خودکار:

وقتی الگوی سوءاستفاده را به صورت دستی تأیید کردید، مرحله بعدی تبدیل آن بینش به یک قانون خودکار است. برای مثال:

  • استفاده کنید دستور grep 'printf('src/') برای یافتن فراخوانی‌های قالب‌بندی خام.
  • این را با اسکریپت‌نویسی ترکیب کنید تا هرگونه استفاده از [] را علامت‌گذاری کنید. printf( که در آن اولین آرگومان قرار دارد نیستم یک رشته‌ی تحت‌اللفظی.
  • از ابزارهای مبتنی بر AST برای ردیابی مقادیر رشته‌ای قالب‌بندی شده استفاده کنید و مسیرهای غیر تحت‌اللفظی را به صورت پویا شناسایی کنید.
  • یافته‌های دستی مکرر، مانند توابع پوششی که ورودی‌های غیرقابل اعتماد را ارسال می‌کنند، را به قوانین CI تبدیل کنید که این موارد را به طور خودکار مسدود می‌کنند.

نکته‌ای برای یکپارچه‌سازی CI: پیکربندی کنید pipeline اگر هر تابع فرمتی ورودی پویا را به عنوان رشته فرمت خود دریافت کند، ساخت‌ها با شکست مواجه می‌شوند. این بررسی‌ها مانند یک فایروال عمل می‌کنند که آموخته‌های شما از GDB و اشکال‌زدایی در زمان اجرا را اجرا می‌کند.

مقاوم‌سازی کد: اعتبارسنجی ورودی و الگوهای ایمن‌تر

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

  • همیشه از رشته‌های با قالب ثابت استفاده کنید: printf("%s", user_input);، هرگز ورودی خام را به عنوان فرمت ارسال نکنید.
  • گزینه‌های امن‌تر را ترجیح دهید: چاپ فوری، vsnprintf, و توابع مشابه به کنترل اندازه بافر و اعمال ساختار خروجی کمک می‌کنند.
  • اعتبارسنجی تمام ورودی‌های کاربر که ممکن است حتی در توابع پوششی، وارد منطق ثبت وقایع یا قالب‌بندی شود.

اقدامات کاهش خودکار که باید فعال کنید:

  • ضدعفونی‌کننده آدرس (ASan): خرابی حافظه، از جمله سرریز بافر و نقض پشته، که اغلب توسط رشته‌های قالب‌بندی ناقص ایجاد می‌شوند را به صورت بلادرنگ تشخیص می‌دهد.
  • UndefinedBehaviorSanitizer (UBSan): رفتارهای تعریف نشده مانند ارسال آرگومان‌های نامتناسب یا مفقود برای قالب‌بندی توابع را علامت‌گذاری می‌کند.
  • -D_FORTIFY_SOURCE=2: بررسی‌های سبکی را به توابع libc در حین کامپایل اضافه می‌کند و به شناسایی سوءاستفاده از رشته قالب‌بندی یا سرریز بافر با حداقل سربار عملکردی کمک می‌کند.

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

نکته: این ضدعفونی‌کننده‌ها را بخشی از ساخت‌وساز خود قرار دهید pipeline با سیاست‌های هشدار عدم موفقیت. با هرگونه تخلف از رشته قالب‌بندی مانند یک تست ناموفق برخورد کنید.

چگونه Xygeni قبل از ارسال، خطاهای رشته فرمت را متوقف می‌کند

شیگنی تقویت می شود CI/CD با اعمال ایمنی رشته قالب‌بندی با پیشگیری بلادرنگ، نه فقط تشخیص:

  • الگوهای خطرناک را شناسایی می‌کند حرفه ای printf(ورودی کاربر) قبل از اینکه کد به مرحله تولید برسد
  • تجزیه و تحلیل استاتیک رنگ را اعمال می‌کند برای ردیابی ورودی‌های غیرقابل اعتماد به توابع قالب‌بندی، حتی در چندین لایه یا فراخوانی‌های wrapper
  • ادغام‌های ناامن را به‌طور خودکار مسدود می‌کند در گیت‌هاب، گیت‌لب، بیت‌باکت و جنکینز
  • بازخورد واضحی ارائه می‌دهد با ردیابی تماس، مبدا ورودی و پیشcisپیشنهادات اصلاحی الکترونیکی

مثال در عمل: منتوسعه‌دهنده commitخط است اشکال‌زدایی_ورودی_کاربر و اشکال‌زدایی_ورودی() از درون یک آسیب‌پذیر را در بر می‌گیرد printf، Xygeni نمودار فراخوانی را دنبال می‌کند، مسیر ورودی پویا را تشخیص می‌دهد و ادغام را مسدود می‌کند. توسعه‌دهنده بلافاصله یک پیام در درخواست ادغام خود مشاهده می‌کند:

⚠️ آسیب‌پذیری فرمت رشته شناسایی شد: ورودی_کاربر به درون جریان می‌یابد printf() در src/logger.c:42. از یک رشته با فرمت ثابت استفاده کنید و ورودی‌ها را اعتبارسنجی کنید.

این بازخورد به عنوان بخشی از فرآیند MR/PR مستقیماً در GitHub، GitLab، Jenkins یا Bitbucket ارائه می‌شود. توسعه‌دهندگان نمی‌توانند آن را از دست بدهند و راهنمایی‌های عملی در مورد چگونگی رفع مشکل دریافت می‌کنند، نه فقط یک هشدار مبهم.

ادغام بدون مشکل انجام می‌شود:

  • پیکربندی قوانین سیاست‌گذاری برای هر مخزن، شاخه یا پروژه
  • اعمال شرایط مسدودسازی برای استفاده از قالب ناامن
  • ورودی‌های ناامن را در C/C++، پایتون، Go، Rust و پیوندهای بومی آنها به طور خودکار ردیابی کنید

با تعبیه امنیت در گردش کار شما و ارائه بازخوردهای توسعه‌دهنده‌محور، Xygeni تضمین می‌کند که اشکالات رشته فرمت هرگز به مرحله تولید نمی‌رسند و دقیقاً در همان جایی که ظاهر می‌شوند، متوقف می‌شوند.

سخن آخر: باگ‌های رشته فرمت هنوز پابرجا هستند

با وجود ابزارهای مدرن زبان برنامه‌نویسی، اشکالات رشته‌های فرمت هنوز هم وجود دارند. آن‌ها از طریق بسته‌بندی‌ها، بسته‌های شخص ثالث و PRهای تحت بررسی عبور می‌کنند. تأثیر آن‌ها واقعی است: خرابی حافظه، نشت داده‌ها و RCE بالقوه.

کد خود را حسابرسی کنید. خودت را سفت کن CI/CDقوانین تشخیص را پیاده‌سازی و اجرا کنید. این فقط یک مشکل قدیمی نیست، بلکه یک تهدید فعال است که در معرض دید عموم پنهان شده است. از ابزارهای خودکار، تحلیل‌های ایستا و پاک‌کننده‌های زمان اجرا برای شناسایی زودهنگام مشکلات استفاده کنید. صرفاً به دلیل کامپایل شدن کد، فرض نکنید که در امان هستید.

ابزارهای-نرم‌افزاری-ترکیب-تحلیل-ترکیب-ابزارها
ریسک‌های نرم‌افزاری خود را اولویت‌بندی، اصلاح و ایمن‌سازی کنید
حساب کاربری رایگان خود را دریافت کنید.
بدون کارت اعتباری مورد نیاز است.

توسعه و تحویل نرم‌افزار خود را ایمن کنید

با مجموعه محصولات Xygeni