مقدمه :
امنیت وباپلیکیشنها امروزه دیگر یک موضوع انتخابی نیست.
در دنیایی که:
-
دادههای مشتریان ارزشمندترین دارایی است
-
قوانین حفاظت داده سختگیرانهتر شده
-
حملات سایبری پیشرفته و خودکار شدهاند
-
و حتی یک اشتباه کوچک میتواند به ازکارافتادن کامل سیستم منجر شود
هر توسعهدهندهای باید امنیت را بخشی از توسعه بداند، نه یک مرحله بعد از آن.
طبق گزارش OWASP و IBM Security، بیش از ۷۰٪ حملات موفق سایبری ناشی از ۱۰ ضعف پایهای است که اگر توسعهدهنده آنها را رعایت کند، تقریباً ۹۰٪ حملات بیاثر میشود.
در این نسخه فوقجامع، ما هر ضعف امنیتی را بهصورت عمیق، با مثال، کد واقعی، سناریو حمله، و روشهای پیشگیری بررسی میکنیم.

۱. حملات SQL Injection — وقتی ورودی کاربر تبدیل به کوئری دیتابیس میشود
SQL Injection شاید قدیمیترین حمله معروف باشد، اما هنوز هم از موفقترین، مخربترین و رایجترین حملات است.
در سال ۲۰۲۳، بیش از ۳۷٪ نفوذهای ثبتشده از طریق SQLi انجام شدهاند.
این حمله وقتی رخ میدهد که برنامه، ورودی کاربر را مستقیم در کوئری SQL قرار دهد.
۱.۱ مکانیزم دقیق حمله چگونه است؟
فرض کنیم یک ورودی login داریم:
این کد یک فاجعه امنیتی است.
اگر مهاجم بنویسد:
کوئری تبدیل میشود به:
شرط '1'='1' همیشه true است.
یعنی مهاجم بدون نیاز به رمز عبور وارد هر حسابی میشود.
۱.۲ سناریوی حمله واقعی
در بسیاری از سایتهای ایرانی یکی از این موارد دیده میشود:
-
فرم جستجو
-
فرم لاگین
-
فرم ثبتنام
-
فرم فیلتر
-
ورودی API
مثال واقعی از حمله:
مهاجم در فیلد “جستجو” مینویسد:
اگر ورودی sanitize نشده باشد، دیتابیس کاربر حذف میشود.
حتی سادهتر:
با تزریق شرط OR میتوان دادههای کل جدول را استخراج کرد.
۱.۳ چگونه جلوی SQL Injection را بگیریم؟ (روش کامل)
✔ ۱. استفاده از Prepared Statements
در PHP (PDO):
در Node.js (Sequelize):
این روش ورودی کاربر را داده میبیند نه دستور.
✔ ۲. هرگز ورودیها را مستقیم در کوئری قرار ندهید
این اشتباه حتی با ORM هم رخ میدهد:
بدترین نوع Query Raw.
✔ ۳. محدودیت دسترسی دیتابیس
حتی اگر مهاجم تزریق کرد، نباید بتواند:
-
جدول حذف کند
-
ALTER انجام دهد
-
CREATE انجام دهد
به این اصل میگویند:
Least Privilege Principle
(کمترین دسترسی ممکن)
✔ ۴. Validation و Sanitization
همیشه ورودی را:
-
نوع داده بررسی کنید
-
طول بررسی کنید
-
regex قرار دهید
-
کاراکترهای خطرناک را پاک کنید
✔ ۵. نظارت روی Queryهای مشکوک
برای کشف حمله میتوانید روی کوئریهای غیرمعمول alert بگذارید.
۲. XSS — تزریق کدهای مخرب جاوااسکریپت در مرورگر کاربران
XSS دومین ضعف مرگبار امنیتی است.
در این حمله، مهاجم کد جاوااسکریپت خود را به سایت تزریق میکند و این کد در مرورگر قربانی اجرا میشود.
این یعنی کنترل کامل روی:
-
session
-
کوکیها
-
DOM
-
درخواستها
-
اطلاعات حساس
بسته به نوع XSS، مهاجم میتواند:
-
session کاربر را بدزدد
-
درخواست جعلی ارسال کند
-
صفحه جعلی نمایش دهد
-
محتوا را تغییر دهد
-
کاربران را ریدایرکت کند
۲.۱ انواع XSS
✔ ۱) Stored XSS
کد مخرب در دیتابیس ذخیره میشود.
مثال:
بخش نظرات سایت.
زمانی که هر کاربر صفحه را باز کند، کد اجرا میشود.
✔ ۲) Reflected XSS
کد از طریق URL بازتاب میشود:
اگر سایت مستقیماً q را نمایش دهد → XSS رخ میدهد.
✔ ۳) DOM-based XSS
مهمترین نوع در SPAها (React, Vue, Angular).
مثال:
اگر مهاجم بنویسد:
کد در DOM اجرا میشود.
۲.2 سناریوی واقعی از یک سایت ایرانی
در یک فروشگاه معروف ایرانی:
-
مهاجم در قسمت “نام کاربری” هنگام ثبتنام، اسکریپت تزریق کرد
-
نام کاربری ذخیره شد
-
در بخش «لیست مشتریان» مدیر سایت، اسکریپت اجرا شد
-
session مدیر دزدیده شد
-
مهاجم وارد پنل ادمین شد
-
و محصولات را با قیمت ۱ تومان قرار داد
این یعنی XSS فقط برای کاربران نیست؛
گاهی پنل مدیریت را هدف میگیرد.
۲.۳ روشهای جلوگیری (چکلیست کامل)
✔ ۱. Escape کردن خروجی (Output Encoding)
اطلاعاتی که نمایش داده میشود باید Encode شود:
مثلاً:
<script> → <script>
✔ ۲. استفاده از Content Security Policy (CSP)
این یک لایه امنیتی بسیار مهم است:
با CSP میتوانید:
-
اجرای اسکریپت خارجی را ممنوع کنید
-
inline script را بلاک کنید
-
منابع را محدود کنید
XSS با CSP تقریباً غیرممکن میشود.
✔ ۳. Validation ورودی
هیچ ورودی نباید HTML خام باشد مگر در شرایط خاص.
✔ ۴. ممنوعیت innerHTML
در React/Vue بهویژه:
یا در JS:
اینها قاتل امنیت هستند.
✔ ۵. استفاده از DOMPurify
برای sanitize ورودی HTML در وب:
✔ ۶. جلوگیری از اجرای اسکریپت در فایل آپلودی
مثلاً اگر مهاجم فایل SVG مخرب آپلود کند و سایت آن را مستقیم نمایش دهد
→ کد JS اجرا میشود.

۳. CSRF — جعل درخواست از سمت کاربر (Cross-Site Request Forgery)
CSRF یکی از خطرناکترین حملات وب است، چون بدون اینکه کاربر متوجه شود، از session او سوءاستفاده میشود.
وقتی کاربر:
-
وارد حساب کاربری میشود
-
session او در مرورگر فعال است
-
و بدون خروج از سایت، وارد یک سایت دیگر یا لینک ناشناخته میشود
مهاجم میتواند با یک درخواست مخرب، به جای او عملیاتی انجام دهد.
۳.۱ مکانیزم دقیق CSRF چگونه کار میکند؟
سناریو ساده:
-
شما وارد حساب بانکی/سایت/پنل شدید.
-
session فعال است.
-
مهاجم یک لینک مخرب برای شما میفرستد.
-
شما روی لینک کلیک میکنید.
-
درخواست زیر از طرف شما به سایت اصلی ارسال میشود:
چرا؟
چون مرورگر به صورت خودکار کوکی session شما را همراه درخواست میفرستد.
برای سایت هیچ راهی نیست که بفهمد این درخواست از سمت خود کاربر بوده یا نه.
۳.۲ مثال واقعی از CSRF در یک سایت ایرانی
در سال ۱۳۹۹، یک سایت فروشگاهی معروف ایران، API زیر را بدون امنیت منتشر کرده بود:
هیچ توکنی وجود نداشت.
مهاجم کافی بود لینک زیر را در قالب یک تصویر جعلی ارسال کند:
کاربر تنها با باز کردن صفحه، ایمیلش تغییر میکرد.
و مهاجم کنترل کامل حساب او را میگرفت.
۳.۳ روشهای جلوگیری از CSRF (چکلیست کامل)
✔ ۱. استفاده از CSRF Token
روشی استاندارد و بسیار امن.
توکن باید:
-
تصادفی باشد
-
برای هر درخواست متفاوت باشد
-
در فرمهای POST قرار بگیرد
-
در سمت سرور با session مطابقت داده شود
مثال در Node/Express:
✔ ۲. استفاده از SameSite Cookie
در تنظیمات کوکی:
این کار باعث میشود کوکی از سایت دیگر ارسال نشود.
✔ ۳. محدودکردن اقدامات حساس به روش POST یا بهتر: PUT / DELETE
نباید عملیات مهم با GET انجام شود.
✔ ۴. بررسی Headerهای Origin و Referer
اگر درخواست از دامنه دیگری باشد → بلاک.
✔ ۵. اجبار احراز هویت مجدد برای عملیات حساس
مثل:
-
تغییر ایمیل
-
تغییر پسورد
-
حذف حساب
۳.۴ چرا CSRF همچنان خطرناک است؟
-
تشخیص آن سخت است
-
کاربر هیچ علامتی نمیبیند
-
session خودکار ارسال میشود
-
حمله بدون نیاز به مهارت خاص اجرا میشود
-
بسیاری از توسعهدهندگان آن را جدی نمیگیرند
به همین دلیل هنوز هم در OWASP Top 10 قرار دارد.
۴. عدم اعتبارسنجی ورودیها (Input Validation Failure)
یکی از سادهترین اما مخربترین ضعفهای امنیتی.
اگر ورودیها را کنترل نکنید، مهاجم میتواند:
-
XSS تزریق کند
-
SQLi وارد کند
-
فایلهای مخرب آپلود کند
-
API را تخریب کند
-
سیستم را crash کند
-
سرور را overload کند
Input Validation یک دیوار دفاعی است که تقریباً تمام حملات را ضعیف میکند.
۴.۱ ورودیهایی که باید اعتبارسنجی شوند
هر چیزی که از کاربر دریافت شود:
-
فرمهای ثبتنام
-
فرم login
-
فرم تماس
-
فیلد جستجو
-
فیلدهای فیلتر
-
API request body
-
Query params
-
فایلهای آپلود
-
اطلاعات تبادلشده در Socket
بله، همه چیز.
«فقط یک جستجو ساده است؟»
نه، همین «جستجو ساده» میتواند محل ورود XSS یا SQL Injection باشد.
۴.۲ روش استاندارد اعتبارسنجی
✔ ۱. Check — چه دادهای باید باشد؟
مثلاً:
-
نام → حروف الفبا
-
ایمیل → regex معتبر
-
شماره تلفن → ۱۱ رقم
-
قیمت → عدد
-
نقش کاربر → enum محدود
✔ ۲. Trim — حذف کاراکترهای اضافی
مانند:
-
فاصلههای ناخواسته
-
کاراکترهای مخفی Unicode
-
NBSP
-
کاراکترهای Zero Width
این کار مانع دور زدن Validator میشود.
✔ ۳. Type Validation
کاربر نباید بتواند:
-
رشته به جای عدد
-
آرایه به جای رشته
-
object به جای مقدار ساده
بفرستد.
در Node.js (express-validator):
✔ ۴. Length Validation
هیچ فیلدی نباید بدون محدودیت طول باشد.
مهاجم میتواند با ارسال مقدار ۵۰۰ هزار کاراکتری، سرور را crash کند.
✔ ۵. Sanitization
خروجیهای خطرناک باید پاک شوند:
-
<script>حذف شود -
HTML غیراستاندارد حذف شود
-
کاراکترهای escape نشده encode شوند
✔ ۶. Enum Validation
برخی فیلدها باید فقط از یک لیست مشخص انتخاب شوند.
مثلاً:
اگر آزاد باشد، مهاجم:
ارسال میکند و وارد پنل مدیریت میشود.
۴.۳ مثال از یک حمله بدون Input Validation
در یک سیستم سفارشگیری:
این باعث شد:
-
total price overflow شود
-
پرداخت مشکل پیدا کند
-
فاکتور با رقم منفی صادر شود
مهاجم توانست محصول را «رایگان» بخرد.
۴.۴ اعتبارسنجی مقابل Sanitization — تفاوت مهم
-
Validation = بررسی درستی داده
-
Sanitization = پاکسازی داده خطرناک
باید هر دو انجام شود.

۵. ضعف در مدیریت Session و کوکی — قلب امنیت کاربر
Session مدیریت هویت کاربر است.
اگر این بخش ناامن باشد، هکر میتواند:
-
session کاربر را بدزدد
-
وارد حساب او شود
-
رمز را تغییر دهد
-
تراکنش انجام دهد
-
دادهها را سرقت کند
Session Hijacking یکی از مرگبارترین حملات وب است.
۵.۱ خطرات رایج در مدیریت Session
❌ ۱. کوکی بدون HttpOnly
هکر با XSS میتواند کوکی را بخواند:
❌ ۲. کوکی بدون Secure
در HTTP ناامن، مهاجم کوکی را شنود میکند.
❌ ۳. کوکی بدون SameSite
برای CSRF ایدهآل است.
❌ ۴. Session Fixation
وقتی Session ID بعد از login تغییر نکند.
❌ ۵. Session Timeout طولانی
session نباید همیشه فعال باشد.
۵.۲ تنظیمات امن برای Session Cookie
چکلیست کامل:
۵.۳ تولید Session جدید بعد از Login (High Priority)
یکی از مهمترین اقدامات امنیتی:
وقتی کاربر login میکند باید یک session جدید صادر شود.
چرا؟
چون مهاجم ممکن است session قبلی را حدس زده باشد یا در یک سناریو Fixation آن را به کاربر داده باشد.
۵.۴ Session Storage امن
در Node.js (express-session):
-
Redis امنتر از Memory Store است
-
حافظه محلی اصلاً مناسب production نیست
-
session باید رمزگذاری شود
۵.۵ جلوگیری از Session Hijacking
✔ ۱. اعمال IP Binding
ترکیب session + IP = بسیار سخت برای دزدیدن.
✔ ۲. بررسی User-Agent
اگر UA تغییر کرد → session invalid شود.
✔ ۳. لاگگیری کامل
ورودهای مشکوک را باید تشخیص دهید.
۶. آپلود فایل بدون کنترل — دروازه طلایی نفوذ هکرها
آپلود فایل اگر درست مدیریت نشود، خطرناکترین بخش هر وبسایت است.
بیش از ۴۰٪ نفوذهای امنیتی در سایتهای ایرانی از همین بخش شروع میشود.
هنگامی که کاربر اجازه دارد فایل آپلود کند، عملاً به او اجازه میدهید:
-
داده وارد سرور کند
-
فایل روی دیسک ذخیره کند
-
مسیرهای خاص را اشغال کند
-
سرور را با فایل ناسازگار درگیر کند
اگر این ورودی کنترل نشود، مهاجم میتواند:
-
فایل اجرایی آپلود کند
-
اسکریپت PHP یا Node قرار دهد
-
Shell اجرا کند
-
فایلهای مهم سرور را بخواند
-
و حتی Root Access بگیرد
۶.۱ مکانیزم حمله چگونه است؟
سناریوی رایج
فرض کنید سایت اجازه آپلود عکس پروفایل میدهد:
تصویر با فرمت jpg باید آپلود شود.
اما مهاجم فایلی با محتوای PHP ایجاد میکند:
و نامش را میگذارد:
اگر سایت تنها «پسوند» را بررسی کند، مهاجم میتواند فایل php را اجرا کند.
حتی اگر پسوند را درست چک کنید، مهاجم از فرمتهای زیر سوءاستفاده میکند:
-
svg
-
xlsx
-
pdf
-
webp
زیرا برخی از اینها قابلیت اجرای جاوااسکریپت یا XML Injection را دارند.
۶.۲ حمله با SVG (یکی از خطرناکترین فرمتها)
SVG در واقع یک فایل XML است، نه تصویر.
کد مخرب قابل جاسازی:
اگر فایل SVG مستقیماً رندر شود، کد جاوااسکریپت اجرا میشود.
این یعنی XSS از طریق آپلود فایل.
۶.۳ روشهای جلوگیری از نفوذ از طریق فایلها
✔ ۱. بررسی MIME Type واقعی
نه فقط پسوند.
مثال Node.js:
✔ ۲. اسکن فایل با آنتیویروس مخصوص وب
ابزارهای حرفهای:
-
ClamAV
-
VirusTotal API
-
MalDet
✔ ۳. ذخیره فایلها خارج از root وبسرور
فایل آپلودی نباید قابل اجرا باشد.
✔ ۴. rename فایلها
فایل نباید نام اصلی را نگه دارد.
استفاده از UUID:
✔ ۵. محدودکردن اندازه فایل
فایل بزرگ میتواند سرور را crash کند.
✔ ۶. استفاده از کتابخانههای پردازشگر امن
برای پردازش تصاویر:
-
Sharp
-
ImageMagick بهصورت sandbox شده
✔ ۷. جلوگیری از فایلهای چند پسوندی
مانند:
حتماً کامل بررسی کنید.

۷. پیکربندی اشتباه سرور (Security Misconfiguration) — دشمن خاموش امنیت
این ضعف یکی از چندریختترین و خطرناکترین ضعفهای امنیتی است.
و در پروژههای واقعی بیشتر از آنچه تصور کنید دیده میشود.
از وبسرور گرفته تا دیتابیس، CDN، Reverse Proxy و حتی Firewall—
کوچکترین اشتباه در پیکربندی هر کدام میتواند سیستم را در برابر حملات باز بگذارد.
۷.۱ اشتباهات رایج امنیتی در سرورهای ایرانی
❌ ۱. فعال بودن Directory Listing
اگر این قابلیت فعال باشد:
همه فایلها قابل مشاهدهاند.
❌ ۲. نمایش خطاهای PHP یا Node
وقتی خطا نمایش داده میشود، اطلاعات مهم لو میرود:
-
مسیر فایلها
-
نسخه PHP/Node
-
ساختار پروژه
-
نام کلاسها و فانکشنها
این اطلاعات طلای ناب برای مهاجم هستند.
❌ ۳. باز بودن پورتهای غیرضروری
هکرها همیشه با اسکن پورت شروع میکنند:
اگر پورتهای اضافی باز باشند، مهاجم میتواند حمله کند:
-
SSH
-
FTP
-
SMTP
-
Redis
-
MongoDB
اینها نباید عمومی باشند.
❌ ۴. فعال بودن ماژولهای غیرضروری
مثلاً در Apache:
-
mod_autoindex
-
mod_userdir
-
mod_info
بسیار خطرناک هستند.
❌ ۵. عدم محدودیت روی درخواستها
بدون Rate Limit، مهاجم میتواند:
-
Brute Force
-
DDOS لایت
-
API Abuse
انجام دهد.
۷.۲ حملات واقعی ناشی از Misconfiguration
سناریو ۱: خروج اطلاعات با HEAD request
بسیاری از سرورها اطلاعات نسخه را لو میدهند:
مهاجم با این اطلاعات:
-
آسیبپذیری نسخه
-
Exploitهای مربوطه
-
Zero-dayهای آن ورژن
را پیدا میکند.
سناریو ۲: Docker ناامن
یکی از بزرگترین فجایع امنیتی زمانی است که Docker daemon بدون TLS باز باشد.
هکر میتواند:
-
container بسازد
-
فایل بخواند
-
حتی host را کنترل کند
۷.۳ چکلیست کامل جلوگیری از Misconfiguration
✔ غیرفعالکردن Directory Listing
Apache:
Nginx:
✔ غیرفعال کردن نمایش خطا
PHP:
Node:
استفاده از Error Handler اختصاصی و جلوگیری از چاپ stack.
✔ فعال کردن Firewall
UFW، iptables یا Cloudflare.
✔ محدودکردن پورتها
فقط:
-
80
-
443
-
پورت API مورد نیاز
باز باشند.
✔ اسکن امنیتی منظم
با ابزارهایی مانند:
-
Nessus
-
OpenVAS
-
Nmap
✔ استفاده از Reverse Proxy
مانند Nginx/Traefik برای محافظت.
۸. رمزنگاری ضعیف (Weak Cryptography) — رمزگذاری اشتباه بدتر از بدون رمزگذاری
بسیاری از توسعهدهندگان فکر میکنند:
“اگر رمز عبور را رمزگذاری کنم، کافی است.”
اما رمزگذاری اشتباه بدتر از رمزگذاری نکردن است.
چرا؟
چون:
-
با چند خط کد قابل شکستن است
-
با rainbow table قابل استخراج است
-
با GPU طی چند ثانیه کرک میشود
ضعف رمزنگاری یعنی مهاجم با دسترسی کوچک میتواند:
-
رمز همه کاربران
-
تراکنشها
-
توکنها
-
دادههای محرمانه
را استخراج کند.
۸.۱ اشتباهات رایج در رمزنگاری
❌ ۱. استفاده از MD5
MD5 کاملاً مرده است.
هش آن طی ۰.۳ ثانیه توسط GPU شکسته میشود.
❌ ۲. استفاده از SHA1
کاملاً ناامن.
❌ ۳. ذخیره رمز بدون salt
یعنی دو نفر با رمز یکسان → هش یکسان.
❌ ۴. استفاده از رمزگذاری Base64
Base64 اصلاً رمزنگاری نیست!
فقط encoding است.
❌ ۵. عدم استفاده از HTTPS
ارسال رمز و دادهها در plaintext = فاجعه.
۸.۲ ابزارهای استاندارد رمزنگاری
بهترین الگوریتمهای hash برای رمز عبور:
-
bcrypt
-
argon2
-
scrypt
اینها:
-
زمانبر هستند
-
GPU-resistant هستند
-
salt خودکار دارند
مثال bcrypt در Node.js:
۸.۳ اهمیت رمزنگاری در انتقال داده
حتماً باید:
-
HTTPS
-
HSTS
-
TLS 1.2 یا 1.3
-
عدم استفاده از SSL یا TLSهای قدیمی
فعال باشد.
۸.۴ جلوگیری از XXE و XML Encryption Attacks
اگر سرویس XML دارید:
-
External Entity را غیرفعال کنید
-
DTDها را ببندید
-
از parser امن استفاده کنید
XXE میتواند فایلهای سرور را بخواند:
