Signal() and signed integers

This example is taken from a wargame. First a more simplified version of the c code:

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <unistd.h>

void catcher(int a)

{

printf("WIN!\n");

exit(0);

}

int main(int argc, char **argv)

{



signal(SIGFPE, catcher);

return abs(atoi(argv[1])) / atoi(argv[2]);

}

We obviously want to go to the handler of the signal, which in our case is the catcher() function. In order to do that we must cause SIGFPE signal.

According to signal() man page: Integer division by zero has undefined result. On some architectures it will generate a SIGFPE signal”

If we check the code we see that the function main() has for a return:

return abs(atoi(argv[1])) / atoi(argv[2]);

the second argument we pass to the program should not be zero in order to have a valid return value. If it is zero we create a SIGFPE signal. As a result we call the catcher function.

So now the real example which had an extra security condition

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <unistd.h>

void catcher(int a)

{

printf("WIN!\n");

exit(0);

}

int main(int argc, char **argv)

{

if (argc != 3 || !atoi(argv[2]))

return 1;

signal(SIGFPE, catcher);

return abs(atoi(argv[1])) / atoi(argv[2]);

}

The «if» condition makes things harder:

if (argc != 3 || !atoi(argv[2]))

return 1;

If we pass zero this time we get a valid return of 1. This means that we don’t create a SIGFPE signal.

By reading Signal() man page: https://linux.die.net/man/2/signal

Integer division by zero has undefined result. On some architectures it will generate a SIGFPE signal. (Also dividing the most negative integer by -1 may generate SIGFPE.)

Diving the most negative integer by -1. I think now it is clear that the argv[2] should be -1. But now we should figure out “the most negative integer”. In C, integers need 4 bytes = 32 bits. As we care about signed integers we know that one bit is for the sign. So the number we are looking for is -1 * 2^31 =-2147483648.

If we pass to our program -2147483648 -1 we create a SIGFPE signal and we access the catcher function.

Read about signed and unsigned integers here:

http://kias.dyndns.org/comath/13.html


SSH Black Magic (an example)

Scenario: Suppose we have gained ssh access (not as root user) on a server and we are trying to find a way for privilege escalation. Obviously there are a lot of ways to go and look for vulnerabilities but here I am trying to show how ssh black magic might be useful.

There might be some processes that run on localhost («inside» the server) not visible from the outside world (and this might be really useful for privilege escalation). For instance mysql might be running on its default port 3306 or a Solr server on 8983 or a tomcat server on some port. We can search for the open ports in localhost by typing ss -tunlp (i use this command cause we might not have access to other tools such as netstat, lsof etc) .

Let’s say we get a result 127.0.0.1:5601 which means a process is running on localhost on port 5601. With a simple google search we see that this is the default port of kibana

https://www.elastic.co/guide/en/kibana/current/settings.html

This is a good start, because if we can access kibana it might be vulnerable to CVE-2018-17246

And this is exactly where ssh black magic helps. It enable us to access a process that is accessible only via (server’s) localhost. If we fire a terminal , write

ssh -L 5601:localhost:5601 <username>@<serversip>

and provide the password for the specific user we can now basically access the process running on the server by typing localhost:5601 on our clients browser.

Basically the command means: when I access localhost:5601 from my computer, please forward to port 5601 of the SSH server