RATS - Rough Auditing Tool for Security

9
RATS Rough Auditing Tool for Security Iuga Andreea Alexandra MISS22 Stan Petronela ISS21

Transcript of RATS - Rough Auditing Tool for Security

Page 1: RATS - Rough Auditing Tool for Security

RATS Rough Auditing Tool for Security

Iuga Andreea Alexandra MISS22

Stan Petronela ISS21

Page 2: RATS - Rough Auditing Tool for Security

Introduction

RATS - Rough Auditing Tool for Security - is an open source tool for scanning source code. It

marks common errors in programming such as buffer overflows and TOCTOU (Time Of Check, Time Of

Use) race conditions. It finds potentially dangerous function calls, but it’s goal is not to find find bugs

definetively.

It’s goal is to provide a reasonable starting point for performing manual security audits. RATS

uses an amalgam of security checks, from the syntactic checks in ITS4 to the deep semantic checks for

buffer overflows derived from MOPS (Model Checking program for Security).

This tool provides a list with potential security problems and a short description of them, and

sometimes suggests remedies.

It also provides a relative assessment of the potential severity of each problem, to better help an

auditor prioritize. This tool also performs some basic analysis to try to rule out conditions that are

obviously not problems. Is to be mentioned that manual inspection of the code is still necessary, but this

tool still offers the programmer great help.

Supported Languages: C, C++, Perl, PHP, Python.

Usage

rats [-d ] [-h] [-r] [-w ] [-x] [file1 file2 ... filen]

-d - specifies a database to be loaded in order to check it for vulnerabilities. If there are multiple –

d options each database specified is loaded.

-h - shows a brief usage summary

-i - causes a list of function calls that were used which accept external input to be produced at the

end of the vulnerability report.

-l – the specified language (c, perl, php,python) has to be used regardless of filename.

-r - causes references to vulnerable function calls that are not being used as calls themselves to be

reported.

-w - sets the warning level. The levels are 1, 2 or 3. Warning level 1 includes only default and

high severity Level 2 includes medium severity. Level 2 is the default warning level 3 includes

low severity vulnerabilities.

-x - causes the default vulnerability databases (which are in the installation data directory,

/usr/local/lib by default) to not be loaded.

When started, RATS will scan each file specified on the command line and produce a report when

scanning is complete. The files need to be named appropriate (.c, .cc, .pl, .php, .py) to allow the usage of

the correct rule set (e.g. the Perl rule set). Alternatively the tool’s language option must be set, to enforce

the usage of a specified rule set.

Page 3: RATS - Rough Auditing Tool for Security

RATS prints potential problems sorted by severity, then by function name, then by file, then by line

number. For each function name rats prints an explanation of the problem (if available in the

vulnerability database). Finally Rats prints the number of lines analyzed and the time used.

The vulnerabilities reported in the final report depend on the data contained in the vulnerability

database or databases that are used and the warning level in use.

RATS can output its report in XML-Format. Automation is therefore easily possible.

RATS is configurable when the source code is modified (through lexical analysis), with error

messages controlled by XML reporting filters, which requires the XML tool expat to also be installed. At

runtime, you can configure the level of output you wish to see (defaulting to medium), alternative

vulnerability databases and even report functions that accept input from the user, facilitating the tracking

of user supplied data.

Some of the specific limitations of RATS include the use of greedy pattern matchings, meaning that

tracking for "printf" will match not only "print()" calls but also "vsnprintf()" and the like. This can make it

difficult to filter hits from noise when specific functions are being sought with the -a flag.

Common found problems Buffer Overflows

Format String Problems

Shell Executions

Insecure Tmpfiles

Race Conditions

Access Violations

Weak Random

User Input

Case studies Argument Number Mismatch - The program uses an improperly constructed format string

that contains a different number of conversion specifiers than the function has arguments.

Incorrect format strings can lead the program to read data outside the bounds of allocated

memory, which can allow access to sensitive information, introduce incorrect behavior, or crash

the program.

Example

#include<stdio.h>

void ArgTypeMismatch(float f, int d, char *s) {

char buf[1024];

sprintf(buf, "Wrong type of %d", f);

}

Page 4: RATS - Rough Auditing Tool for Security

RATS Output

argument_mismatch.cpp:5: High: fixed size local buffer

Extra care should be taken to ensure that character arrays that are

allocated on the stack are used safely. They are prime targets for

buffer overflow attacks.

Correction

Memory Leak Reallocation - the program resizes a block of allocated memory. If the resize

fails, the original block will be leaked.Memory leaks have two common and sometimes

overlapping causes: - error conditions and other exceptional circumstances.

- confusion over which part of the program is responsible for freeing the memory.

Most memory leaks result in general software reliability problems, but if an attacker can

intentionally trigger a memory leak, the attacker might be able to launch a denial of service attack (by

crashing the program) or take advantage of other unexpected program behavior resulting from a low

memory condition .

Example

void ArgTypeMismatch(float f, int d, char *s) {

char buf[ ];

sprintf(buf, "Correct type of %f", f);

}

#include <stdio.h>

char* getBlocks(int fd) {

int amt;

int request = BLOCK_SIZE;

char* buf = (char*) malloc(BLOCK_SIZE + 1);

if (!buf) {

goto ERR;

}

amt = read(fd, buf, request);

while ((amt % BLOCK_SIZE) != 0) {

if (amt < request) {

goto ERR;

}

request = request + BLOCK_SIZE;

buf = realloc(buf, request);

if (!buf) {

goto ERR;

}

amt = read(fd, buf, request);

}

return buf;

ERR: if (buf) {

free(buf);

}

return NULL;

}

Page 5: RATS - Rough Auditing Tool for Security

RATS Output

Analyzing memoryleakreallocation.cpp

memoryleakreallocation.cpp:9: Medium: read

memoryleakreallocation.cpp:19: Medium: read

Check buffer boundaries if calling this function in a loop

and make sure you are not in danger of writing past the allocated

space.

memoryleakreallocation.cpp:15: Medium: realloc

Don't use on memory intended to be secure, because the old structure

will not be zeroed out.

Out-of-Bounds Read - The program reads data from outside the bounds of allocated memory.

Buffer overflow is probably the best known form of software security vulnerability. Most

software developers know what a buffer overflow vulnerability is, but buffer overflow attacks

against both legacy and newly-developed applications are still quite common. Part of the

problem is due to the wide variety of ways buffer overflows can occur, and part is due to the

error-prone techniques often used to prevent them.

Example

#include<stdio.h>

void MemFuncs() {

char array1[MAX];

int array2[MAX];

memcpy(array2, array1, sizeof(array2));

}

RATS Output

outofboundsread.cpp:5: High: fixed size local buffer

Extra care should be taken to ensure that character arrays that are

allocated

on the stack are used safely. They are prime targets for buffer

overflow attacks.

Correction

#include<stdio.h>

void MemFuncs() {

char array1[];

int array2[];

memcpy(array2, array1, sizeof(array2));

}

Page 6: RATS - Rough Auditing Tool for Security

Format String Example

RATS Output Analyzing formatString.cpp

formatString.cpp:11: warning: bad token `ô'

formatString.cpp:11: warning: bad token `\'

formatString.cpp:11: warning: bad token `\'

formatString.cpp:11: warning: bad token `ö'

formatString.cpp:12: warning: bad token `ô'

formatString.cpp:7: High: fixed size local buffer

Extra care should be taken to ensure that character arrays that are

allocated

on the stack are used safely. They are prime targets for buffer

overflow

attacks.

formatString.cpp:11: High: printf

Check to be sure that the non-constant format string passed as argument

1 to

this function call does not come from an untrusted source that could

have added

formatting characters that the code is not prepared to handle.

#include <stdio.h>

#include <string.h>

#include <stlib.h>

int main (int argc, char **argv)

{

char buf [100]

int x = 1

snprintf ( buf, sizeof buf, argv [1] ) ;

buf [ sizeof buf -1 ] = 0

printf ( “Buffer size is: (%d) \nData input: %s \n” , strlen (buf) , buf ) ;

printf ( “X equals: %d/ in hex: %#x\nMemory address for x: (%p) \n” , x, x, &x) ;

return 0 ;

}

Page 7: RATS - Rough Auditing Tool for Security

Correction

Exec - The exec() class of functions are used for executing a file as a process image. The exec()

family of calls are vulnerable to TOCTOU attacks. A call to a exec() family function should be

flagged if the first argument (the directory or file name) is used earlier in a "check" category call.

Example

void doit(void)

{

char buf[ ];

fgets(buf,100);

printf("%s\n", buf,stdin);

}

int main (int argc, char **argv)

{

doit();

int x = 1;

unsigned int is incompatible with const char

printf ( "%c %d %c",buf, (char*)malloc(sizeof buf),argv [1] ) ;

buf [ sizeof buf -1 ] = 0;

printf ("Buffer size is: %d \n",strlen(buf),"Data input: %s \n",buf ) ;

printf ("x equals: %d/ in hex: %#x\nMemory address for x: (%p) \n" , x,

x, &x) ;

return 0 ;

}

#include "stdio.h"

#include <unistd.h>

int main(int argc, char *argv[])

{

if (stat("text.exe", &stat_p) != -1)

{

if ((status = execl("text.exe", 0)) == -1)

{

perror("Parent - Execl failed");

exit(EXIT_FAILURE);

}

}

return 0;

}

Page 8: RATS - Rough Auditing Tool for Security

RATS Output

Medium: stat

A potential TOCTOU (Time Of Check, Time Of Use) vulnerability exists. This is

the first line where a check has occured.

The following line(s) contain uses that may match up with this check:

8 (execl)

Correction

GetText() - gets invalid informations from environment. Similar to getcat(), this function is used

for searching predefined messages in a library of messages and often is used for translating the

natural language.

Example

#include "stdio.h"

#include <unistd.h>

int main(int argc, char *argv[])

{

if ((status = execl("text.exe", 0)) == -1)

{

perror("Parent - Execl failed");

exit(EXIT_FAILURE);

}

return 0;

}

#include "stdio.h"

#include <unistd.h>

int main(int argc, char *argv[])

{

string my_name = "My name";

printf(gettext("My name is %s.\n"), my_name);

return 0;

}

Page 9: RATS - Rough Auditing Tool for Security

RATS Output

High: gettext

Environment variables are highly untrustable input. They may be of any

length, and contain any

data. Do not make any assumptions regarding content or length. If at all

possible avoid using

them, and if it is necessary, sanitize them and truncate them to a reasonable

length. gettext()

can utilize the LC_ALL or LC_MESSAGES environment variables.

lala.cpp:6: High: printf

Check to be sure that the non-constant format string passed as argument 1 to

this function call does not come from an untrusted source that could have

added formatting characters that the code is not prepared to handle.

Correction

#include "stdio.h"

#include <unistd.h>

int main(int argc, char *argv[])

{

string my_name = "My name";

printf("%c", _("My name is %s.\n"), my_name);

return 0;

}