RATS - Rough Auditing Tool for Security
Transcript of RATS - Rough Auditing Tool for Security
![Page 1: RATS - Rough Auditing Tool for Security](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/1.jpg)
RATS Rough Auditing Tool for Security
Iuga Andreea Alexandra MISS22
Stan Petronela ISS21
![Page 2: RATS - Rough Auditing Tool for Security](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/2.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/3.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/4.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/5.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/6.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/7.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/8.jpg)
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](https://reader036.fdocuments.net/reader036/viewer/2022073114/577cc9bf1a28aba711a482fc/html5/thumbnails/9.jpg)
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;
}