2019年3月6日 星期三

【C語言】緩衝區溢位攻擊

假如我寫了一個程式如下

#include <stdio.h>
#include <string.h>

int main()
{
  char str[5];
  int pass = 0;
  gets(str);
  if (!strcmp(str, "1234")) {
    pass = 1;
    puts("Your password is correct");
  } else {
    puts("Your password is wrong");
  }
  if (!pass) {
    puts("Access denied");
  } else {
    puts("You've loged in");
  }
  return 0;
}
我們使用了非常危險的函式gets,連gcc都會告訴大家
warning: the `gets' function is dangerous and should not be used.
因為gets這個函式只會硬塞進緩衝區,不能夠設定緩衝區大小,確保不會發生緩衝區溢位。
在gcc 8.2.1中,直接編譯,結果如下:

1000
Your password is wrong
Access denied
1234
Your password is correct
You've loged in
12345
Your password is wrong
Access denied
123456
Your password is wrong
Access denied
*** stack smashing detected ***: <unknown> terminated
zsh: abort (core dumped)  ./a.out


我只要打太多東西,直接就會crash。
我加入了-fstack-protector,得到的結果如下:

1000
Your password is wrong
Access denied
1234
Your password is correct
You've loged in
12345
Your password is wrong
Access denied
123456
Your password is wrong
Access denied
123812638791263127896378912631278963718923
Your password is wrong
Access denied
zsh: segmentation fault (core dumped)  ./a.out


只有在最後亂打一通,才會造成問題,但我只要採用-fno-stack-protector

1234
Your password is correct
You've loged in
12345
Your password is wrong
Access denied
123456
Your password is wrong
You've loged in

其中在我最後輸入123456的時候,就造成嚴重的安全問題,錯誤的密碼竟然可以登入,這就是所謂緩衝區溢位攻擊,因為讀入的字串已經蓋過了其他的資料,造成程式出錯。
比較正確的程式應該使用fgets:


#include <stdio.h>
#include <string.h>

int main()
{
  char str[5];
  int pass = 0;
  fgets(str, 5, stdin);
  if (!strcmp(str, "1234")) {
    pass = 1;
    puts("Your password is correct");
  } else {
    puts("Your password is wrong");
  }
  if (!pass) {
    puts("Access denied");
  } else {
    puts("You've loged in");
  }
  return 0;
}
這樣的程式就會安全很多。




👉【幫我們一個忙!】👈

👋如果您喜歡這篇文章,請在下方按5個Like!
 ❤您的支持是我們最大的動力!

您只要登入帳號(Facebook、Google),在下方按5個Like,我們就會收到來自LikeCoin基金會的贊助。
您只需要支持我們,完全不會花到錢!