printf ไม่ปลอดภัยที่จะใช้ใน C

Sep 24 2020

ฉันยังใหม่กับ C ดังนั้นฉันจึงเริ่มเล่นกับโค้ด ฉันมีข้อบกพร่องในรหัสของฉันเนื่องจากฉันเชื่อว่าการใช้printf(pass)ไม่ปลอดภัยที่จะใช้เนื่องจากสามารถเขียนทับค่าได้และด้วยเหตุนี้จึงไม่ปลอดภัยสำหรับผู้ใช้ ฉันสงสัยว่าฉันพูดถูกprintf(pass)หรือเปล่าที่ไม่ปลอดภัยในรหัสของฉัน นอกจากนี้ฉันจะให้ผู้ใช้พิมพ์ข้อความfinally logged inโดยไม่เปลี่ยนรหัสได้อย่างไร มีวิธีใดบ้างที่จะทำเช่นนั้น?

รหัสของฉัน:

#include <stdio.h>

char pass[100];

char getPass() {
  int value = 'G';
  int * j = & value;
  fgets(pass, sizeof(pass), stdin);
  printf("your entered pass is ");
  printf(pass);
  return (char)( * j);
}

void main() {
  printf("enter the pass here ");
  if (getPass() == 'K') {
    printf("finally logged in\n");
    exit(0);
  } else {
    printf("Wrong password\n");
    exit(1);
  }
}

คำตอบ

5 r3mainer Sep 24 2020 at 08:48

ใช่มันไม่ปลอดภัย แต่ไม่ใช่ด้วยเหตุผลที่คุณแนะนำ หากคุณตรวจสอบmanหน้าสำหรับprintf()ฟังก์ชันคุณจะเห็นว่ามีต้นแบบดังต่อไปนี้:

int printf(const char * restrict format, ...);

constปรับปรุงนำไปใช้ระบุอาร์กิวเมนต์แรกว่าค่าของพารามิเตอร์นี้จะไม่เปลี่ยนแปลงเมื่อคุณเรียกใช้ฟังก์ชันนี้

formatแต่คุณจะสังเกตเห็นว่าพารามิเตอร์นี้จะถูกเรียกว่า นั่นเป็นเพราะมันควรจะระบุสตริงรูปแบบ ในโปรแกรมของคุณไม่มีอะไรที่จะหยุดผู้ใช้ที่ป้อนตัวระบุรูปแบบเช่น%pในกรณีนี้การโทรของคุณprintf()จะเริ่มพิมพ์เนื้อหาของสแต็ก มีบทความ Wikipediaที่อธิบายช่องโหว่นี้โดยละเอียด

4 VladfromMoscow Sep 24 2020 at 08:45

ฟังก์ชั่นfgetsหากการโทรสำเร็จจะให้สตริงที่คุณสามารถส่งออกได้

ปัญหาอาจเกิดขึ้นได้หากสตริงที่ได้รับออกมาในลักษณะนี้

printf(pass);

และมีการระบุการแปลง

ดังนั้นแทนที่จะเรียกว่า

printf(pass);

ปลอดภัยกว่าในการใช้งาน

printf( "%s", pass );

หรือ

puts(pass);

fgetsเบื้องต้นคุณสามารถเอาตัวอักษรบรรทัดใหม่เก็บไว้ในสตริงโดยการเรียกร้องของ