-
Notifications
You must be signed in to change notification settings - Fork 65
/
main.c
452 lines (397 loc) · 9.85 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
/*
* Insecure code examples
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h> // read(), write(), close()
/*
* The following cases are using functions that are
* known to be dangerous, if used wrong.
*/
#define BUF_SIZE 10
void basic_logical_error(char *dst, char *src) {
// copy and paste error
if(strlen(dst) == 0 && strlen(dst) == 0)
return;
// size of "dst" is not considered here
strcpy(dst, src);
}
// Insecure use of strcpy
void insecure_strcpy(char *dst, char *src) {
// bad strlen comparison
if(strlen(dst) == 0 )
return;
// bad strlen comparison
if(strlen(src) == 0)
return;
// size of "dst" is not considered here
strcpy(dst, src);
}
// Insecure use of "strcat" could result in
// a buffer overflow
void insecure_strcat(char *dst, char *src) {
// bad strlen comparison
if(strlen(dst) == 0 )
return;
// bad strlen comparison
if(strlen(src) == 0)
return;
// size of "dst" is not considered here
strcat(dst, src);
}
// Format string vulnerability usinf printf
int bad_printf_wrapper(char* format, char* value) {
// bad strlen comparison
if(strlen(format) == 0 &&
strlen(value) == 0)
return;
printf(format, value);
}
//
int insecure_sprintf(char* format, char* value) {
char buffer [10];
// bad strlen comparison
if(strlen(format) == 0 &&
strlen(value) == 0)
return;
return sprintf(buffer, format, strlen(value));
}
// Insecure use of "strncat" could result in
// a buffer overflow
int insecure_strncat(char* src) {
char buf[BUF_SIZE];
// bad strlen comparison
if(strlen(src) == 0)
return;
// The calcualted size of the third parameter should be checked
return strlen(strncat(buf, src, BUF_SIZE - strlen(src)));
}
// Insecure use of "strtok"
int insecure_strtok() {
char *token;
char *path = getenv("PATH");
// the return value of strtok should be checked ":" could not be present
token = strtok(path, ":");
puts(token);
return printf("PATH: %s\n", path);
}
// Insecure usage of "gets"
int insecure_gets() {
char str[10];
// gets is not checking the size of the destination buffer
gets(str);
return printf("%s", str);
}
// Insecure usage of "getwd"
int insecure_getwd() {
// Size of "dir" is too small
char dir[12];
// return value of "getwd" is not checked
getwd(dir);
return printf("Working directory:%s\n",dir);
}
// Insecure usage of "getwd"
int insecure_scanf() {
char name[12];
// size of "name" is not considered here
scanf("%s", name);
return printf("Hello %s!\n", name);
}
/*
* Signed integer overflow is undefined behavior. Shifts of signed values to the
* left are very prone to overflow.
*/
void bad_shifting1(int val) {
val <<= 24;
}
void bad_shifting2(int val) {
255 << val;
}
void bad_shifting3(int val) {
val << val;
}
// A high level nesting could indicate bad coding style
// and (accidentally) introduce vulnerabilities
int func_with_nesting_level_of_3(int foo, int bar) {
if (foo > 10) {
if (bar > foo) {
for(int i = 0; i < bar ;i++) {
}
}
}
}
// Artificial example checking for
// high number of loops in a function.
int high_number_of_loops () {
for(int i = 0; i < 10; i++){ }
for(int i = 0; i < 10; i++){ }
for(int i = 0; i < 10; i++){ }
for(int i = 0; i < 10; i++){ }
}
// Heap based buffer overflow
int insecure_heap_handling(char* src, int asize) {
char *ptr = malloc(asize);
strncpy(ptr, src, asize);
strlen(ptr);
}
// The return value of a read/recv/malloc call is not checked directly and
// the variable it has been assigned to (if any) does not
// occur in any check within the caller.
void unchecked_read() {
// BUF_SIZE = 10
char buf[BUF_SIZE];
read(fd, buf, sizeof(buf));
}
// The return value of a read/recv/malloc call is not checked directly and
// the variable it has been assigned to (if any) does not
// occur in any check within the caller.
void checks_something_else() {
char buf[BUF_SIZE];
int nbytes = read(fd, buf, sizeof(buf));
int foo = 10;
if( foo != sizeof(buf)) {
}
}
// When calling `send`, the return value must be checked to determine
// if the send operation was successful and how many bytes were transmitted.
void return_not_checked(int sockfd, void *buf, size_t len, int flags) {
send(sockfd, buf, len, flags);
}
// For (buf, indices) pairs, determine those inside control structures (for, while, if ...)
// where any of the calls made outside of the body (block) are Inc operations. Determine
// the first argument of that Inc operation and check if they are used as indices for
// the write operation into the buffer.
int index_into_dst_array (char *dst, char *src, int offset) {
int i;
for(i = 0; i < strlen(src); i++) {
dst[i + + j*8 + offset] = src[i];
}
return i;
}
// The set*uid system calls do not affect the groups a process belongs to. However, often
// there exists a group that is equivalent to a user (e.g. wheel or shadow groups are often
// equivalent to the root user).
// Group membership can only be changed by the root user.
// Changes to the user should therefore always be preceded by calls to set*gid and setgroups,
void setresuid_case() {
// Minimal example
setresuid();
}
void setresuid_groups() {
// Minimal example
setgroups();
setresuid();
}
// The set*gid system calls do not affect the ancillary groups a process belongs to.
// Changes to the group membership should therefore always be preceded by a call to setgroups.
// Otherwise the process may still be a secondary member of the group it tries to disavow.
void setresgid_uid() {
setresgid();
setresuid();
}
// Heap based buffer overflow
int insecure_memcpy(size_t len, char *src) {
char *dst = malloc(len + 8);
memcpy(dst, src, len + 7);
return strlen(dst);
}
// The following function can cause a
// time-of-check, time-of-use race condition
void insecure_race(char *path) {
chmod(path, 0);
rename(path, "/some/new/path");
}
// Insecure usage of "strlen".
// The return value of strlen is size_t
// but the calling function returns int
int insecure_strlen(char *str) {
if(str == NULL)
return -1;
else
return strlen(str);
}
// A hihg number of parameters is
// considered as bad coding style
int too_many_params(int a, int b, int c, int d, int e) {
// no content because parameter check
}
// A high cyclomatic complexity
// can increase the likelyhood
// of security issues
int high_cyclomatic_complexity(int x) {
while(true) {
for(int i = 0; i < 10; i++) {
}
if(x<10) {}
}
if (x > 10) {
for(int i = 0; i < 10; i++) {
}
}
}
// Functions that have too many lines should be refactored
int func_with_many_lines(int x) {
// Artificial basic example for too many lines
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
x++;
return x;
}
/*
* The following code is based on
* https://github.com/hardik05/Damn_Vulnerable_C_Program
*/
struct Image
{
char header[4];
int width;
int height;
char data[10];
};
void stack_operation(){
char buff[0x1000];
while(1){
stack_operation();
}
}
int ProcessImage(char* filename){
FILE *fp;
struct Image img;
fp = fopen(filename,"r"); //Statement 1
if(fp == NULL)
{
printf("\nCan't open file or file doesn't exist.\r\n");
exit(0);
}
while(fread(&img,sizeof(img),1,fp)>0)
{
printf("\n\tHeader\twidth\theight\tdata\t\r\n");
printf("\n\t%s\t%d\t%d\t%s\r\n",img.header,img.width,img.height,img.data);
//integer overflow 0x7FFFFFFF+1=0
//0x7FFFFFFF+2 = 1
//will cause very large/small memory allocation.
int size1 = img.width + img.height;
char* buff1=(char*)malloc(size1);
//heap buffer overflow
memcpy(buff1,img.data,sizeof(img.data));
free(buff1);
//double free
if (size1/2==0){
free(buff1);
}
else{
//use after free
if(size1/3 == 0){
buff1[0]='a';
}
}
//integer underflow 0-1=-1
//negative so will cause very large memory allocation
int size2 = img.width - img.height+100;
//printf("Size1:%d",size1);
char* buff2=(char*)malloc(size2);
//heap buffer overflow
memcpy(buff2,img.data,sizeof(img.data));
//divide by zero
int size3= img.width/img.height;
//printf("Size2:%d",size3);
char buff3[10];
char* buff4 =(char*)malloc(size3);
memcpy(buff4,img.data,sizeof(img.data));
//OOBR read bytes past stack/heap buffer
char OOBR = buff3[size3];
char OOBR_heap = buff4[size3];
//OOBW write bytes past stack/heap buffer
buff3[size3]='c';
buff4[size3]='c';
if(size3>10){
//memory leak here
buff4=0;
}
else{
free(buff4);
}
int size4 = img.width * img.height;
if(size4/2==0){
//stack exhaustion here
stack_operation();
}
else{
//heap exhaustion here
char *buff5;
do{
buff5 = (char*)malloc(size4);
}while(buff5);
}
free(buff2);
}
fclose(fp);
return 0;
}
struct Example_Struct
{
char* ptr;
int size;
} example_struct;
void free_field_reassigned(Example_Struct *example_struct, char* buf) {
free(example_struct->ptr);
if (example_struct->size == 0) {
return;
}
example_struct->ptr = buf;
}
void not_free_field_reassigned(Example_Struct *example_struct, char* buf) {
free(example_struct->ptr);
if (example_struct->size == 0) {
example_struct->ptr = NULL;
return;
}
example_struct->ptr = buf;
}
void bad1(Example_Struct *example_struct) {
void *x = NULL;
example_struct->foo = x;
free(x);
}
void *bad() {
void *x = NULL;
if (cond)
free(x);
return x;
}
void *false_positive() {
void *x = NULL;
free(x);
if (cond)
x = NULL;
else
x = NULL;
return x;
}
/*
* End of code from
* https://github.com/hardik05/Damn_Vulnerable_C_Program
*/
int main(int argc,char **argv) {
char argumentInput[256];
strcpy_bad(argumentInput, argv[1]);
func_with_nesting_level_of_3(strlen(argv[1]), strlen(argv[2]))
}