فرمت داده ها: تفاوت بین نسخهها
(۴ نسخهٔ میانیِ همین کاربر نمایش داده نشده است) | |||
سطر ۱: | سطر ۱: | ||
− | + | هنگامی که از توابع ورودی و خروجی بر اساس فرمتی استفاده می کنید، ممکن است مهاجم بتواند با رشته فرمت شده بتواند پروسه آسیب پذیری را crash کند و بتواند محتوای stack، محتوای memory بخواند و یا در محتوا حافظه مقداری را بنویسند و یا امکان اجرای کد با استفاده از دسترسی پروسه آسیب پذیر امکان پذیر است. | |
+ | |||
+ | توابع خروجی بر اساس فرمت می توانند مقدار integer را در آدرسی خاص با استفاده از %n بنویسند. | ||
+ | |||
+ | برای مثال در کدر زیر تابع incorrect_password() هنگام احراز هویت و نادرست بودن کلمه عبور پیام خطایی را چاپ می کند. | ||
+ | |||
+ | کد، نام کاربر را با user بدون هیچ گونه فیلتر از کاربر دریافت می کند. | ||
+ | |||
+ | پیام خطا در stderr و با استفاده از تابع fprintf چاپ می شود و هیچگونه کنترلی بر روی مقدار integer وارد شده و overflow آن نیست. | ||
+ | |||
+ | همپنین معمولا تابع ()snprintf برای نمایش پیام از چند نقطه استفاده می شود و در این کد msg بدون هیچ گونه کنترلی و به صورت مستقیم، ورودی کاربر را در snprintf استفاده می نماید. | ||
+ | |||
+ | <div lang="en" dir="ltr" class="mw-content-ltr"> | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | void incorrect_password(const char *user) { | ||
+ | int ret; | ||
+ | /* User names are restricted to 256 or fewer characters */ | ||
+ | static const char msg_format[] = "%s cannot be authenticated.\n"; | ||
+ | size_t len = strlen(user) + sizeof(msg_format); | ||
+ | char *msg = (char *)malloc(len); | ||
+ | if (msg == NULL) { | ||
+ | /* Handle error */ | ||
+ | } | ||
+ | ret = snprintf(msg, len, msg_format, user); | ||
+ | if (ret < 0) { | ||
+ | /* Handle error */ | ||
+ | } else if (ret >= len) { | ||
+ | /* Handle truncated output */ | ||
+ | } | ||
+ | fprintf(stderr, msg); | ||
+ | free(msg); | ||
+ | } | ||
+ | </pre> | ||
+ | </div> | ||
+ | |||
+ | در کد بهبود یافته زیر از تابع ()fputs برای خروجی msg در stderr استفاده شده است. | ||
+ | |||
+ | <div lang="en" dir="ltr" class="mw-content-ltr"> | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | void incorrect_password(const char *user) { | ||
+ | int ret; | ||
+ | /* User names are restricted to 256 or fewer characters */ | ||
+ | static const char msg_format[] = "%s cannot be authenticated.\n"; | ||
+ | size_t len = strlen(user) + sizeof(msg_format); | ||
+ | char *msg = (char *)malloc(len); | ||
+ | if (msg == NULL) { | ||
+ | /* Handle error */ | ||
+ | } | ||
+ | ret = snprintf(msg, len, msg_format, user); | ||
+ | if (ret < 0) { | ||
+ | /* Handle error */ | ||
+ | } else if (ret >= len) { | ||
+ | /* Handle truncated output */ | ||
+ | } | ||
+ | fputs(msg, stderr); | ||
+ | free(msg); | ||
+ | } | ||
+ | </pre> | ||
+ | </div> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
[[category:ورودی و خروجی(FIO)]] | [[category:ورودی و خروجی(FIO)]] |
نسخهٔ کنونی تا ۶ مارس ۲۰۲۰، ساعت ۱۴:۱۲
هنگامی که از توابع ورودی و خروجی بر اساس فرمتی استفاده می کنید، ممکن است مهاجم بتواند با رشته فرمت شده بتواند پروسه آسیب پذیری را crash کند و بتواند محتوای stack، محتوای memory بخواند و یا در محتوا حافظه مقداری را بنویسند و یا امکان اجرای کد با استفاده از دسترسی پروسه آسیب پذیر امکان پذیر است.
توابع خروجی بر اساس فرمت می توانند مقدار integer را در آدرسی خاص با استفاده از %n بنویسند.
برای مثال در کدر زیر تابع incorrect_password() هنگام احراز هویت و نادرست بودن کلمه عبور پیام خطایی را چاپ می کند.
کد، نام کاربر را با user بدون هیچ گونه فیلتر از کاربر دریافت می کند.
پیام خطا در stderr و با استفاده از تابع fprintf چاپ می شود و هیچگونه کنترلی بر روی مقدار integer وارد شده و overflow آن نیست.
همپنین معمولا تابع ()snprintf برای نمایش پیام از چند نقطه استفاده می شود و در این کد msg بدون هیچ گونه کنترلی و به صورت مستقیم، ورودی کاربر را در snprintf استفاده می نماید.
#include <stdio.h> #include <stdlib.h> #include <string.h> void incorrect_password(const char *user) { int ret; /* User names are restricted to 256 or fewer characters */ static const char msg_format[] = "%s cannot be authenticated.\n"; size_t len = strlen(user) + sizeof(msg_format); char *msg = (char *)malloc(len); if (msg == NULL) { /* Handle error */ } ret = snprintf(msg, len, msg_format, user); if (ret < 0) { /* Handle error */ } else if (ret >= len) { /* Handle truncated output */ } fprintf(stderr, msg); free(msg); }
در کد بهبود یافته زیر از تابع ()fputs برای خروجی msg در stderr استفاده شده است.
#include <stdio.h> #include <stdlib.h> #include <string.h> void incorrect_password(const char *user) { int ret; /* User names are restricted to 256 or fewer characters */ static const char msg_format[] = "%s cannot be authenticated.\n"; size_t len = strlen(user) + sizeof(msg_format); char *msg = (char *)malloc(len); if (msg == NULL) { /* Handle error */ } ret = snprintf(msg, len, msg_format, user); if (ret < 0) { /* Handle error */ } else if (ret >= len) { /* Handle truncated output */ } fputs(msg, stderr); free(msg); }