توضیح حمله CBC Bit Flipping
رمزگذاری به این معنا نیست که دادههای شما در برابر دستکاری ایمن هستند.
بسیاری از توسعهدهندگان مرتکب این اشتباه میشوند. آنها فکر میکنند اگر مهاجم نتواند دادهها را بخواند، نمیتواند آنها را تغییر دهد. این اشتباه است. رمزنگاری، محرمانگی (secrecy) و یکپارچگی (integrity) را دو وظیفه متفاوت در نظر میگیرد.
حمله CBC Bit Flipping این موضوع را ثابت میکند. یک مهاجم میتواند بدون دانستن کلید مخفی شما، دادههایتان را تغییر دهد.
نحوه عملکرد آن به این صورت است:
AES دادهها را به صورت یک قطعه بزرگ رمزگذاری نمیکند، بلکه آنها را به بلوکهای ۱۶ بایتی تقسیم میکند. در حالت CBC، این بلوکها به هم زنجیر میشوند. خروجی رمزگذاریشدهی بلوک اول با متن اصلی (plaintext) بلوک دوم ترکیب میشود.
این زنجیره یک نقطه ضعف در طول رمزگشایی ایجاد میکند. برای بهدست آوردن متن اصلی بلوک ۲، سرور آن را رمزگشایی کرده و با ciphertext بلوک ۱ ترکیب میکند.
یک مهاجم میتواند از این موضوع سوءاستفاده کند:
- مهاجم ترافیک رمزگذاریشده شما را شنود (intercept) میکند.
- آنها کلید را نمیدانند، بنابراین دادهها شبیه به مجموعهای از کاراکترهای بیمعنی به نظر میرسند.
- آنها بیتهای خاصی را در ciphertext بلوک ۱ تغییر میدهند.
- آنها این دادههای تغییریافته را به سرور شما ارسال میکنند.
- وقتی سرور آن را رمزگشایی میکند، تغییر در بلوک ۱ محاسبات مربوط به بلوک ۲ را تغییر میدهد.
مهاجم نیازی به خواندن پیام ندارد. آنها فقط بیتها را معکوس (flip) میکنند تا نتیجه نهایی را تغییر دهند.
یک اپلیکیشن وب قدیمی را در نظر بگیرید که از کوکیهای رمزگذاریشده برای مدیریت نشستها (sessions) استفاده میکند. یک کوکی ممکن است حاوی این باشد:
userid=994;role=user;
یک مهاجم این کوکی را شنود کرده و بیتهای ciphertext را تغییر میدهد. آنها درخواستهای زیادی ارسال میکنند تا زمانی که سرور یکی از آنها را بپذیرد. از آنجایی که سرور فقط بررسی میکند که آیا دادهها قابل رمزگشایی هستند یا خیر، متن تغییریافته را پردازش میکند. ناگهان، رشته رمزگشاییشده به این صورت خوانده میشود:
userid=994;role=admi;
اکنون مهاجم دسترسی ادمین دارد. آنها هرگز کلید یا کوکی اصلی را نخواندهاند.
اشتباه اینجاست که فرض شود رمزگذاری، یکپارچگی را تضمین میکند.
- محرمانگی (Confidentiality) مانع از خواندن دادهها توسط افراد میشود.
- یکپارچگی (Integrity) مانع از تغییر دادهها توسط افراد میشود.
برای رفع این مشکل، از رمزگذاری احرازشده (Authenticated Encryption) مانند AES-GCM استفاده کنید. این روش یک تگ رمزنگاری ایجاد میکند. این تگ مانند یک مُهر عمل میکند. اگر مهاجم حتی یک بیت را هم تغییر دهد، مُهر میشکند. سرور بلافاصله داده را رد میکند.
اگر مجبور به استفاده از CBC هستید، از معماری Encrypt-then-MAC استفاده کنید. یک کد احراز هویت برای ciphertext ایجاد کنید و قبل از شروع رمزگشایی، آن را تأیید کنید.
دادههای مخفی همیشه دادههای قابل اعتماد نیستند. همیشه قبل از اینکه از دادهها برای تصمیمگیری استفاده کنید، ثابت کنید که تغییر نکردهاند.
توضیح حمله Bit-Flipping در حالت CBC: چرا رمزنگاری به تنهایی تضمینکننده یکپارچگی نیست
وقتی صحبت از رمزنگاری میشود، اولین چیزی که به ذهن میرسد محرمانگی (Confidentiality) است؛ یعنی اطمینان از اینکه فقط افراد مجاز میتوانند محتوا را بخوانند. اما یک مفهوم حیاتی دیگر وجود دارد که اغلب نادیده گرفته میشود: یکپارچگی (Integrity).
در این مقاله، ما به بررسی یک آسیبپذیری در حالت رمزنگاری CBC (Cipher Block Chaining) میپردازیم که به آن حمله Bit-Flipping میگویند. این حمله نشان میدهد که چگونه یک مهاجم میتواند بدون داشتن کلید رمزنگاری، محتوای پیام را تغییر دهد.
محرمانگی در مقابل یکپارچگی
- محرمانگی: تضمین میکند که دادهها برای افراد غیرمجاز قابل خواندن نیستند.
- یکپارچگی: تضمین میکند که دادهها در طول انتقال یا ذخیرهسازی، بدون اجازه تغییر نکردهاند.
رمزنگاری به تنهایی (مانند استفاده از AES در حالت CBC) فقط محرمانگی را فراهم میکند. اگر شما فقط از رمزنگاری استفاده کنید، یک مهاجم ممکن است نتواند محتوا را بخواند، اما میتواند آن را تغییر دهد.
حالت CBC چگونه کار میکند؟
در حالت CBC، هر بلوک از متن اصلی (plaintext) قبل از رمزنگاری، با بلوک رمزنگاریشدهی (ciphertext) قبلی از طریق عملیات XOR ترکیب میشود. بلوک اول نیز با یک بردار مقداردهی اولیه (Initialization Vector - IV) XOR میشود.
فرمول ساده شده برای بلوک $n$ به این صورت است: $C_n = E_k(P_n \oplus C_{n-1})$
و برای رمزگشایی: $P_n = D_k(C_n) \oplus C_{n-1}$
نکته کلیدی در اینجا این است که برای به دست آوردن متن اصلی بلوک $n$ ($P_n$)، ما از خروجی رمزگشایی بلوک $n$ ($C_n$) و بلوک رمزنگاریشدهی قبلی ($C_{n-1}$) استفاده میکنیم.
حمله Bit-Flipping چیست؟
از آنجایی که $P_n$ از طریق XOR کردن $D_k(C_n)$ با $C_{n-1}$ به دست میآید، اگر مهاجم یک بیت را در $C_{n-1}$ تغییر دهد (flip کند)، دقیقاً همان بیت در $P_n$ نیز تغییر خواهد کرد.
مهاجم نیازی ندارد بداند محتوا چیست یا کلید رمزنگاری را داشته باشد؛ او فقط کافی است بداند در کدام موقعیت بیت قرار دارد و آن را معکوس کند.
مثال عملی
فرض کنید یک پیام رمزنگاری شده داریم که حاوی اطلاعات زیر است:
{"user": "guest", "admin": false}
اگر این پیام در بلوکهای مشخصی قرار بگیرد و مهاجم بداند که کلمه false در کدام بلوک و در کدام موقعیت قرار دارد، میتواند بیت مربوط به آن را تغییر دهد تا به true تبدیل شود.
پیامد حمله:
- تغییر هدفمند: متن اصلی بلوک $n$ دقیقاً همانطور که مهاجم میخواهد تغییر میکند.
- تخریب بلوک قبلی: به عنوان یک اثر جانبی، بلوک $n-1$ کاملاً خراب (garbled) میشود، زیرا تغییر در $C_{n-1}$ باعث میشود خروجی رمزگشایی $P_{n-1}$ کاملاً متفاوت و نامفهوم شود.
اگر برنامه شما فقط به بلوک $n$ اهمیت دهد و از خراب شدن بلوک $n-1$ چشمپوشی کند، حمله با موفقیت انجام شده است.
چگونه از این حمله جلوگیری کنیم؟
برای جلوگیری از این نوع حملات، شما نباید فقط به رمزنگاری تکیه کنید. شما به احراز هویت پیام (Message Authentication) نیاز دارید.
۱. استفاده از MAC (کد احراز هویت پیام)
شما میتوانید از یک کد احراز هویت مانند HMAC استفاده کنید. در این حالت، شما یک امضای دیجیتال برای متن رمزنگاریشده ایجاد میکنید. اگر مهاجم حتی یک بیت را تغییر دهد، امضا نامعتبر خواهد بود.
۲. استفاده از حالتهای AEAD
بهترین راهکار مدرن، استفاده از حالتهای AEAD (Authenticated Encryption with Associated Data) است. این حالتها همزمان هم محرمانگی و هم یکپارچگی را فراهم میکنند.
نمونههای معروف عبارتند از:
- AES-GCM (Galois/Counter Mode)
- AES-CCM
با استفاده از AES-GCM، اگر مهاجم سعی کند حتی یک بیت از Ciphertext را تغییر دهد، فرآیند رمزگشایی با خطا مواجه شده و پیام رد میشود.
نتیجهگیری
رمزنگاری به تنهایی، امنیت کامل را تضمین نمیکند. برای محافظت در برابر حملات دستکاری دادهها، همیشه از روشهایی استفاده کنید که همزمان محرمانگی و یکپارچگی را فراهم میکنند (مانند AEAD).