Logo

רד-בורד: ארכיון

ראשי > אבטחת מידע > Format String Vulnerability Checker שכתבתי ב-Perl

17/10/2006 17:57:50 MasterBlaster
זה אמנם מתאים גם לפורום תיכנות, אבל בגלל שמדובר בסוג של סורק אבטחה החלטתי לפתוח את הנושא הזה כאן. מכל מקום, התוכנית שכתבתי מסוגלת לסרוק תוכניות שכתובות בשפת C ולאתר בהן חורי אבטחה המכונים Format String Vulnerabilities (למי שלא מכיר: http://doc.bughunter.net/format-string/exploit-fs.html).

נכון לעכשיו, התוכנית סורקת רק פונקציות שהוגדרו ב-ANSI C, אם כי ניתן בקלות להוסיף תמיכה בפונקציות נוספות דרך עריכת הקוד.

נקודה נוספת שחשוב לי להבהיר: התוכנית יוצאת מנקודת ההנחה שקוד ה-C כתוב היטב. כלומר - היא לא תעיר על שגיאות תחביר ו/או שגיאות לוגיות בקובץ הקוד שמוגש לה (למשל, היא לא בודקת ששמתם נקודה פסיק [;] בסוף כל הוראה).

הקוד:

קוד:#!/usr/bin/perl

##### [ Required Modules ] #####
use strict;
use vars qw (@functions $file $counter);

##### [ Main Script ] #####
@functions = ([’printf’,1],[’fprintf’,2],[’sprintf’,2],[’snprintf’,3],[’vprintf’,1],[’vfprintf’,2],[’vsprintf’,2],[’vsnprintf’,3]);
$file = shift || &usage;
$counter = 1;

open (file,$file) || die "Unable to open file $file\n";
while (my $line = <file>) {
foreach (@functions) {
if ($line =~ /$_->[0]\s*\((.+)\)/) {
my @args = split (’,’,$1);
if (@args == $_ -> [1] && index ($1,’"’) == -1) {
print "A format string vulnerability found at line $counter: $line\n";
}
}
}
$counter++;
}
close (file);

##### [ Script Subroutines ] #####
sub usage {
print "Usage: perl $0 <path to C source file>\n";
exit (1);
}

##### [ EOF ] #####

התוכנית נכתבה ונבדקה תחת מחשב PC עם מערכת Linux. גרסת Perl: 5.8.8.

הערות/הארות ותיקונים יתקבלו בברכה.[ההודעה נערכה על-ידי MasterBlaster ב-17/10/2006 17:58:41]
17/10/2006 23:45:52 Trancer
עבודה יפה אחי, תמשיך ככה.
אני לא בבית כרגע אבל איך שאגיע אני ינסה את הקוד.
18/10/2006 18:52:15 devil kide
אני לא יודע פרל, אבל נראה חמוד.
אם תוכל לתרגם לC אני אשמח, תודה.
19/10/2006 00:05:53 MasterBlaster
ציטוט:אני לא יודע פרל, אבל נראה חמוד.
אם תוכל לתרגם לC אני אשמח, תודה.
C זה לא בדיוק הצד החזק שלי, אבל אני אנסה.[ההודעה נערכה על-ידי MasterBlaster ב-19/10/2006 00:06:32]
20/10/2006 20:57:00 T4uSBaZ
מצאתי מסמך בעברית על זה:
http://www.underwar.co.il/document-details.asp?id=188
כמובן הוא לא מקצועי כמו שהביאו לפני באנגלית.

ולגבי התוכנה:
אחרי עבודה רבה, שחיפשתי איך לעזעזל למצוא את הבאג בקובץ טקסט, ולעשות את זה באופן טוב,
בניתי לך תוכנית בסי שמחפשת בתוך קוד מקור בסי את הבאג.
היא יכולה למצוא בשורה אחת כמה באגים כאלו,
וגם למצוא באג אחד. אם היא מוצאת היא כותבת את השורה.
היא כותבת איזה שורה היא סורקת, ובסוף כותבת כמה באגים כאלו נמצאו.

היא מחפשת בין 8 פונקציות שכתובות שם (לא בעיה להוסיף עוד, כל אחד עם ידע בסי יוכל להוסיף . )
ובעצם העיקרון שלה זה לחפש את את 8 הפונקציות בתוכנה, ואם היא מוצאת, לבדוק האם יש בזה סוגריים או לא. אם יש סוגריים אין באג, אם אין סוגריים יש באג.

התוכנה פותחה מנקודת הנחה שהקוד הנבדק ללא באגים!

חסרון אחד שמצאתי:
לדוגמא בשורה הזאת:
קוד:
func("printf(abc)");

הארגומנט שעובר לפונקציה, היא תחשוב שזה באג. זה חסרון שנוצר עקב שהתוכנה יכולה למצוא כמה באגים בשורה.

והקוד:

קוד:

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

/*

/* Really basic format string...
I think i didn’t understand it well, so tell me :P
It just search the functions that can include the bug,
and see if there is any "" in it. if there is, it means everythink ok, or the programmer
write a format and didn’t write the variable. for example printf("%s%s%s%s"); (that means the programmer
write wrong code, that didnt connected to the user input.
if there is no any "" , it alert format string found + in which sentence.
it search the functions and check it. it dont really check if it function..
it can be argument, and it will think it’s a format string. for example: func("printf(abc);"); it will think it’s a bug;

please correct me if there is any mistakes..
T4uSBaZ;

p.s.
The functions it check:
* fprintf - prints to a FILE stream
* printf - prints to the `stdout’ stream
* sprintf - prints into a string
* snprintf - prints into a string with length checking
* vfprintf - print to a FILE stream from a va arg structure
* vprintf - prints to `stdout’ from a va arg structure
* vsprintf - prints to a string from a va arg structure
* vsnprintf - prints to a string with length checking from a va arg structure
I dont know all this functions, but i am guessing it have to include "" , or it has format string.

Here it is: please replay! */

char functions[10][15]={"fprintf","printf","sprintf","snprintf","vfprintf","vprintf","vsprintf","vsnprintf"}; //the functions to check
int checksentence(char buffer[]); //prototype for this command
main()
{
int counter=0,all=0; //counter count the current sentence, all count how many Vulnerability founded.
int i; //temp var
FILE *s; //The file
char buffer[100]; //the data from the file will be here.
char filename[40]; //The filename
printf("wellcome to string format vulnerability check program!\n");
printf("Please enter the file name (C code): ");
gets(filename);
if((s=fopen(filename,"rt"))==NULL)
{
printf("Error: cant open %s for reading. maby the file isnt exist! ",filename);
printf("\nPress any key to exit.");
getch();
exit(1);
}
while(!feof(s))
{
fgets(buffer,sizeof(buffer),s);
counter++;
if( (i=checksentence(buffer)) == 0)
printf("At line %d: string format not founded in this sentence.\n",counter);
else{
all+=i;
printf("At line %d: found %d format string: \n%s\n",counter,i,buffer);
printf("Press any key to continune.\n");
getch();
}
}
fclose(s);
printf("\n%d Vulnerability founded.",all);
getch();
}

int checksentence(char buffer[]) //return how many vulnerbality founded.
{
int i,j,k,l,m; //temp counters
int b=0;
int hmn=0; //how many founded
for(i=0;i<8;i++) //search if every function is in the buffer (10 functions)
{
for(j=b;j<strlen(buffer);j++)
{ //search the function from every character .
if(j+strlen(functions)+4<=strlen(buffer)) //check if the current character is in place which the function can be found.
//(functionname) + 4 minimum characters. (4 minimum characters: "(" ")" for opening func and close it ";" for close it
// and the last character is the var name (minimun one char) in case of if bug founded.
{
l=0; //if it will be 0 in the end of the loop below, the function founded.
for(k=0;k<strlen(functions);k++) //check char char if the function is from that place, if not, l=1.
{
if(buffer[j+k]!=functions[k])
{
l=1;
break;
}
}
if(l==0) //if the function name founded, check if this function and if it vulnerbality.
{
if( buffer[j+strlen(functions)] ==’(’){
for(m=0;buffer[j+strlen(functions)+m]!=’\0’;m++)
{

if(buffer[j+strlen(functions)+m]==’"’)
{
b+=strlen(functions)+m;
break;
}
if(buffer[j+strlen(functions)+m]==’)’) // && buffer[j+strlen(functions)+m+1]==’;’
{
hmn++;
b+=strlen(functions)+m;
break;
}
}
}
}

}
}
}
return hmn; //return how many founded
}




תגיבו :P[ההודעה נערכה על-ידי T4uSBaZ ב-20/10/2006 20:58:30]
21/10/2006 18:45:00 devil kide
WOW
22/10/2006 13:47:35 T4uSBaZ
:P

רק תגידו לי אם הבנתי את הבאג נכון.? Oo
22/10/2006 14:55:08 MasterBlaster
ציטוט::P

רק תגידו לי אם הבנתי את הבאג נכון.? Oo
הפגיעות של Format String נוצרת כאשר מתכנת כותב למשל:

קוד:printf (argv[1]);

במקום:

קוד:printf ("%s",argv[1]);

במקרה הראשון argv[1] מפורש בתור ה-Format string, ובמקרה השני הוא יפורש כמחרוזת. בגלל שלמשתמש יש שליטה מלאה על argv[1], הוא יכול להריץ את התוכנית בצורה כזאת:

קוד:$ ./program %s%s%s%s%s

מה שיגרום בעצם ל-printf להיראות כך:

קוד:printf ("%s%s%s%s%s");

בגלל ש-%s מציג נתונים מכתובות שנדחפו לתוך המחסנית, יש לנו סיכוי גבוה לקרוא מכתובת לא חוקית, מה שיוביל לקריסת התהליך (שימושי במקרה של Service מרוחק כלשהו).

שימושים מתקדמים יותר של Format String Vulnerability כוללים את מיפוי המחסנית, מיפוי מרחב הזיכרון של התוכנית, כתיבה למקומות רנדומלים בזיכרון והרצת קוד זדוני (בדומה ל-Buffer Overflow, בה כתובת החזרה של הפונקציה מושחתת כדי שהיא תצביע על ה-Buffer שהצפנו).

זהו בגדול.[ההודעה נערכה על-ידי MasterBlaster ב-22/10/2006 14:56:24]
22/10/2006 16:25:50 T4uSBaZ
כן , הבנתי את זה כך, ובניתי את זה נכון - בעצם התוכנית שבניתי מחפשת את הבאג הזה.
עמודים: 1