فرمت داده ها: تفاوت بین نسخه‌ها

از Secure Coding

 
(۴ نسخهٔ میانیِ همین کاربر نمایش داده نشده است)
سطر ۱: سطر ۱:
تست
+
هنگامی که از توابع ورودی و خروجی بر اساس فرمتی استفاده می کنید، ممکن است مهاجم بتواند با رشته فرمت شده بتواند پروسه آسیب پذیری را 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);
}