(2) Vulnerabilities in Linux Systems
Hello to you all! And, thank you for being curious enough to open a blog post titled '(2) Vulnerabilities in Linux Systems'.
Sounds dry, doesn't it?
Having spent a lot of time on this topic, I can confidently say that it is NOT dry (emphasis on the 'NOT')
Also, who writes their first post on a scientific topic?
NOT me! (emphasis on the NOT, again)
I write a lot, though I keep most of it to myself. But, if you really want to read some of my other work, you can find it here.
A majority of people think Linux-based operating systems are invulnerable. Though stats might support this argument, we have to consider the fact that linux systems are targeted a lot less as compared to Windows machines. Since the year 2016 the attack on linux distributions has increased by 300%, with the threats going far beyond just malware infections.
Here, we look at two vulnerabilities faced by linux-based systems - Shellshock & Race-Condition vulnerabilities.
To understand the shellshock attack, we first need to understand how functions & variables are defined and passed between processes within the linux shell.
When the terminal is opened, the parent process owns it. Let us understand what happens when each line in the above picture is executed:
1) We are creating a variable called foo (which is basically a string).
2) We are printing the contents of the memory location accessible by the name foo.
3) Since the content of the string foo looks like a function definition, we try to check if it is indeed considered to be a function. But in this case, it is NOT!
Clear so far? Great! Let's move on.
4) The export call passes the variable foo to a child process.
5) The bash function spawns a new child shell, and command is transferred to the shell immediately.
6) We try to print the variable foo which is now available with the child process.
But, it does not print out anything!!
What has happened here?
-- When a new process is created, bash goes through the content of every variable that is passed to the new process. If the content of the variable looks like a function definition, the environment variable is converted into a function within the child process.
To verify that is indeed is the case, we execute command (7), which prints out the definition of the 'function' named foo.
Everything seems to be behaving the way it was intended to. So, what is the problem?
-- When the bash functionality was written in C, when a child process is spawned, if an environment variable started off as a valid function, it was changed to a function. After the function definition ended, there was no check to verify if the variable content was over as well.
For eg.,
foo='() { echo "Test Message";}'
and
foo='() { echo "Test Message";} echo /bin/ls -l'
are both converted into functions, even though the second variable contains and echo command after the function definition.
To successfully attack the victim, the symbolic link has to be established after the access command, but before the open command.
Sounds dry, doesn't it?
Having spent a lot of time on this topic, I can confidently say that it is NOT dry (emphasis on the 'NOT')
Also, who writes their first post on a scientific topic?
NOT me! (emphasis on the NOT, again)
I write a lot, though I keep most of it to myself. But, if you really want to read some of my other work, you can find it here.
A majority of people think Linux-based operating systems are invulnerable. Though stats might support this argument, we have to consider the fact that linux systems are targeted a lot less as compared to Windows machines. Since the year 2016 the attack on linux distributions has increased by 300%, with the threats going far beyond just malware infections.
Here, we look at two vulnerabilities faced by linux-based systems - Shellshock & Race-Condition vulnerabilities.
1) Shellshock Attack -
To understand the shellshock attack, we first need to understand how functions & variables are defined and passed between processes within the linux shell.
| Fig 1: A simple demonstration of creating and passing variables between processes. |
When the terminal is opened, the parent process owns it. Let us understand what happens when each line in the above picture is executed:
1) We are creating a variable called foo (which is basically a string).
2) We are printing the contents of the memory location accessible by the name foo.
3) Since the content of the string foo looks like a function definition, we try to check if it is indeed considered to be a function. But in this case, it is NOT!
Clear so far? Great! Let's move on.
4) The export call passes the variable foo to a child process.
5) The bash function spawns a new child shell, and command is transferred to the shell immediately.
6) We try to print the variable foo which is now available with the child process.
But, it does not print out anything!!
What has happened here?
-- When a new process is created, bash goes through the content of every variable that is passed to the new process. If the content of the variable looks like a function definition, the environment variable is converted into a function within the child process.
To verify that is indeed is the case, we execute command (7), which prints out the definition of the 'function' named foo.
Everything seems to be behaving the way it was intended to. So, what is the problem?
-- When the bash functionality was written in C, when a child process is spawned, if an environment variable started off as a valid function, it was changed to a function. After the function definition ended, there was no check to verify if the variable content was over as well.
For eg.,
foo='() { echo "Test Message";}'
and
foo='() { echo "Test Message";} echo /bin/ls -l'
are both converted into functions, even though the second variable contains and echo command after the function definition.
This can be used to exploit and take control of a linux system.
Consider a case where a machine is hosting a web-cgi application.
Note - web-cgi programs are those which can process a standard input and environment variables and write that to a standard output.
Whenever a client tries to access the application, the request headers look something like this:
GET /cgi-bin/cgiAttackProgram.cgi HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:23.0) Gecko/20100101 Firefox/23.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
If an imposter, posing as a client can, in some way, change the content of any of the parameters in a way that will grant him/her access to the server, the server is compromised!
Let us see how that can be done.
| Fig 2: Launching a shellshock attack though an impostor's terminal |
Note -
i) The attacks have been launched through the terminal using the curl command. Similar results can be achieved through the client's browser.
ii) The URL in the above picture refers to localhost because the attack was launched from the same computer where the application was hosted. The IP address of the host machine should be used in place of localhost, if the attack is launched from some other machine.
Assume that the client has done the above operations:
1) The first command prints out the files which are present in the active directory on the server!
2) The second command takes it a step further. It prints out the contents of the configuration file for the SQL database that is stored on the server. Once the intruder has the username and password of the database, he/she has access to all the data stored on the server.
These are not the only attacks that can be launched! An intruder might be able to delete some files on the server. A denial-of-service (DoS) attack can be launched as well.
The same attack could be used by hackers to add a root account in the /etc/passwd and /etc/shadow files.
Other than CGI-based web servers, attackers, in 2014, were able to gain access to IBM Hardware Management Console (which used a semi-restricted shell). Some DHCP clients, which can send commands to bash, can launch an attack while trying to connect to a open Wi-Fi network.
Multiple patches were released to fix the problems with the linux shell, but since most of these patches were code-only, the patches could be used only by users who knew how to compile a new bash executable file from the patch file.
2) Race-Condition Vulnerability Attack -
A race condition occurs when multiple processes access and manipulate the same data concurrently, and the outcome of the execution depends on the particular order in which the access takes place. Intruders have exploited this vulnerability through multiple ways, since the 1990s.
A popular variety of a race-condition vulnerability attack is the TOCTOU (time-of-check to time-of-use) attack, one that is caused by changes in a system between the checking of a condition (such as a security credential) and the use of the results of that check.
A really good example of a TOCTOU attack is as follows:
| Fig 3: The attacker tries to create a symbolic link between file and /etc/passwd |
To successfully attack the victim, the symbolic link has to be established after the access command, but before the open command.
Note - A symbolic link is a file that links to another file via its path.
Consider the following scenario
/tmp/VulnerableProgram.c
#include <stdio.h>
#include<unistd.h>
int main()
{
char * fn = "/tmp/XYZ";
char buffer[60];
FILE *fp;
/* get user input */
scanf("%50s", buffer );
if(!access(fn, W_OK)){
fp = fopen(fn, "a+");
fwrite("\n", sizeof(char), 1, fp);
fwrite(buffer, sizeof(char), strlen(buffer), fp);
fclose(fp);
}
else printf("No permission \n");
}
To exploit the above vulnerable program, an attacker has to write another program which would link the file /tmp/XYZ to /etc/shadow or /etc/passwd.
If he/she is able to add an extra user account, the attack has succeeded.
To achieve this, the following files can be created:
1) A shellscript which keeps invoking the vulnerable program, and stops execution when some modification has been made to the critical file
2) A attack program, as mentioned above!
To overcome the problems caused due to race conditions, symlinks in world-writable sticky directories (e.g. /tmp) cannot be followed if the follower and directory owner do not match the symlink owner.
If you have come this far, I congratulate you, and I hope you've got an idea of what these two vulnerabilities are!
Hopefully, I'll be back soon, with another article.
Cheers,
Adhitya
Comments
Post a Comment