-
Notifications
You must be signed in to change notification settings - Fork 131
adding exploits
Adding new exploits is a little tricky. As the exploit source code needs to reside in the class, so that we can package the project as a binary, we have some special considerations to take in.
This is an example of an exploit for CVE-SOME-VULN. The vulnerability exists in the Linux kernel from 3.3.3 to 3.4.4. The patch for Ubuntu shows that Ubuntu 10 is vulnerable until patch at 3.3.7. The patch for Debian shows that Debian 6 is vulnerable until patch at 3.4.1. The public exploit script specifically targets Ubuntu 10 3.3.4-3.3.7.
class CVESOMEVULN(LinuxExploit):
def __init__(self, playground_path=PLAYGROUND_PATH):
self.name = "CVESOMEVULN" # needs to be name of class
self.formatted_name = "CVE-SOME-VULN" # formatted in CVE form
self.e_type = "linux" # OS type it targets (mac or linux)
self.brief_desc = "small snippet of what it targets"
self.reliability = MEDIUM_RELIABILITY # not really important atm
self.vulnerable_base = KernelWindow(GENERIC_LINUX, 3, 3, 3, 3, 4, 4, BASE_VULNERABLE, highest_patch_level="1.2.34-567.8.9")
self.vulnerable_kernels = [
KernelWindow(UBUNTU_10, 3, 3, 3, 3, 3, 7, VERSION_VULNERABLE, highest_patch_level="1.2.34-567.8.9"),
KernelWindow(UBUNTU_GENERIC, 3, 3, 3, 3, 3, 7, BASE_VULNERABLE, highest_patch_level="1.2.34-567.8.9"),
KernelWindow(DEBIAN_6, 3, 3, 3, 3, 4, 1, VERSION_VULNERABLE, highest_patch_level="1.2.34-567.8.9"),
KernelWindow(DEBIAN_GENERIC, 3, 3, 3, 3, 4, 1, BASE_VULNERABLE, highest_patch_level="1.2.34-567.8.9"),
]
self.exploit_kernels = [
KernelWindow(UBUNTU_10, 3, 3, 4, 3, 3, 7, EXPLOIT_AVAILABLE, highest_patch_level="1.2.34-567.8.9"),
]
self.architecture = ARCHITECTURE_GENERIC
self.playground_path = playground_path
self.exploit_source_file_name = "{}.c".format(self.name)
self.source_c_path = os.path.join(self.playground_path, self.exploit_source_file_name)
self.compilation_path = os.path.join(self.playground_path, self.name)
self.compilation_command = "gcc -o {} {}".format(self.compilation_path, self.source_c_path)
self.exploit_command = self.compilation_path
self.exploit_source = """
#include <stdio.h>
int main()
{
// printf() displays the string inside quotation
printf("exploit source goes here\\n");
return 0;
}
"""
# override so that we return a vulnerable status if the kernel matches
# no other system pre-requisites
def determine_vulnerability(self):
color_print("\t[*] checking exploitation prerequisites for {}".format(self.name), color="blue")
# if kernel matches...it should be vulnerable
color_print("\t[-] system appears to be vulnerable to {}".format(self.name), color="green")
return True
One idiosyncrasy in adding exploits is specific to the self.vulnerable_kernels array. Due to how kernelpop checks for vulnerability, if you add a vulnerable window that targets a version of a specific distro, you need to also include a KernelWindow that encompasses the DISTRO_GENERIC type that has a vulnerable status of BASE_VULNERABLE. This makes it so that if the vulnerability exists in UBUNTU_6, but not UBUNTU_5 (or unconfirmed), we don't return null for trying to match UBUNTU_5, but instead return BASE_VULNERABLE.
This is more accurate, because the base Linux kernel is in the vulnerable range, but the distro specific kernel version is not confirmed to be vulnerable.
We need to override the superclass method determine_vulnerability(). The superclass version always returns False. We want our method to return True. I may change this to default to True after doing some testing, because this seems dumb.
Because we need to store the exploit source code in a string, we need to escape any escape sequences so that they aren't interpreted as part of the string, and are written to disk properly.
i.e.
source:
println("this is a print\n");
string (in exploit class):
println("this is a print\\n");
I do this with find+replace in a text editor before copy-pasting to the class