gokrazy/rsync: پیادهسازی Go چطور از آسیبپذیریها جلوگیری میکنه
خلاصهٔ کاملتر
در ژانویه ۲۰۲۵، محققان امنیتی مجموعاً ۶ آسیبپذیری در rsync فاش کردن که بعداً با ۶ مورد دیگه در می ۲۰۲۶ به ۱۲ آسیبپذیری رسید. برخی از اینها شدت بالایی دارن — مثل heap buffer overflow با امتیاز ۹.۸ که امکان اجرای کد دلخواه رو میده. نویسندهی gokrazy/rsync، یک پیادهسازی مستقل و مینیمال rsync به زبان Go، بررسی کرده که آیا زبان Go و سادگی پیادهسازی واقعاً از این آسیبپذیریها جلوگیری کرده. اگر rsync اصلی یا سامبا رو در پروداکشن دارید، حتماً به نسخه ۳.۴.۳ یا جدیدتر آپگرید کنید.
CVE-2024-12084 (امتیاز ۹.۸) یک heap buffer overflow کلاسیکه: rsync طول چکسام رو از شبکه میخوند و با MAX_DIGEST_LEN مقایسه میکرد، ولی ساختار داده همیشه فقط ۱۶ بایت (SUM_LENGTH) رزرو کرده بود. وقتی rsync با پشتیبانی SHA256 کامپایل میشه، MAX_DIGEST_LEN میتونه ۶۴ بشه — یعنی مهاجم میتونه تا ۴۸ بایت خارج از بافر بنویسه. Go اینجا کمک واقعی میکنه: رانتایم Go بررسی مرز (bounds check) رو خودکار انجام میده و بهجای نوشتن خارج از حافظه، پنیک میکنه. gokrazy/rsync هم validation کافی نداشت، ولی همین bounds check رانتایم Go جلوی سوءاستفاده رو گرفت — و بعد از کشف، validation مناسب هم اضافه شد.
CVE-2024-12085 (امتیاز ۷.۵) یک نشت اطلاعات پشتهست که ASLR رو خنثی میکنه. مهاجم میتونه با ترکیب این باگ و CVE-2024-12084، اجرای کد دلخواه داشته باشه. ریشهی مشکل اینه که بافر sum2 روی پشته مقداردهی اولیه نمیشه و مقادیر تصادفی حافظه توش میمونه. Go اینجا هم کمک میکنه: در Go همه متغیرها بهطور خودکار با مقدار صفر مقداردهی میشن و برنامهنویس نیازی به مقداردهی دستی نداره. gokrazy/rsync اصلاً آسیبپذیر نبود.
CVE-2024-12087 (امتیاز ۷.۵) یک path traversal از طریق symlinkهاست. سرور مخرب میتونه در حالت inc-recursive چند لیست فایلی بفرسته که در اولی یک دایرکتوری معمولی نشون بده و در دومی همون مسیر رو بهعنوان symlink به یک مسیر دلخواه معرفی کنه — و اینطوری فایلها خارج از پوشه مقصد نوشته میشن. Go اینجا کمکی نمیکنه چون این یک باگ منطقیه. ولی gokrazy/rsync اصلاً حالت --inc-recursive رو پیادهسازی نکرده، پس آسیبپذیر نیست. CVE-2024-12088 (امتیاز ۷.۵) هم بایپس --safe-links بود که از یک اشتباه منطقی در تابع اعتبارسنجی میاومد — Go اینجا هم کمکی نمیکنه، ولی gokrazy/rsync این feature رو پیادهسازی نکرده.
CVE-2024-12086 (امتیاز ۶.۸) یک نشت فایل دلخواهه: سرور مخرب میتونه به کلاینت دستور بده چکسام فایلهایی خارج از پوشه مقصد رو بفرسته و با مقایسه واکنشها محتوای فایل رو بایتبهبایت بازسازی کنه. این هم یک باگ منطقیه و Go کمکی نمیکنه. gokrazy/rsync در حالت client پیادهسازی نشده بود، پس آسیبپذیر نبود — هرچند بعداً پشتیبانی client هم اضافه شد و validation مربوطه هم همراهش اومد.
نتیجهگیری کلی اینه که Go برای دستهای از آسیبپذیریهای حافظهای (buffer overflow، uninitialized memory) بهطور ساختاری کمک میکنه، ولی باگهای منطقی رو حل نمیکنه. اونجاست که سادگی و minimalism پیادهسازی اهمیت پیدا میکنه: وقتی یک feature پیادهسازی نشده، آسیبپذیری مربوط بهش هم وجود نداره. مقاله همچنین به مکانیزمهای defense-in-depth مثل os.Root در Go (که از دسترسی به فایلهای خارج از یک دایرکتوری جلوگیری میکنه) و openrsync اوپنبیاسدی هم پرداخته.
نکات کلیدی:
- ۱۲ آسیبپذیری در rsync اصلی کشف شد؛ ارتقا به نسخه ۳.۴.۳+ ضروریه
- Go با bounds check خودکار و مقداردهی صفر به متغیرها، کلاسهای کاملی از باگهای حافظه رو حذف میکنه
- باگهای منطقی (path traversal، validation نادرست) رو زبان حل نمیکنه — سادگی پیادهسازی حل میکنه
- gokrazy/rsync در اکثر موارد بهخاطر پیادهسازی نکردن featureهای پیچیده آسیبپذیر نبود
- مکانیزمهایی مثل os.Root در Go میتونن لایه دفاعی اضافه ایجاد کنن




