XigenChris /
ComodoDecodeCSR
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * @author Chris Hilsdon <[email protected]> |
||
| 4 | * @package ComodoDecodeCSR |
||
| 5 | * @copyright 2016 Xigen |
||
| 6 | * @license GNU General Public License v3 |
||
| 7 | * @link https://github.com/XigenChris/ComodoDecodeCSR |
||
| 8 | */ |
||
| 9 | |||
| 10 | namespace Xigen; |
||
| 11 | |||
| 12 | use GuzzleHttp\Client; |
||
| 13 | use GuzzleHttp\Exception\ClientException; |
||
| 14 | use GuzzleHttp\Psr7\Response; |
||
| 15 | |||
| 16 | class ComodoDecodeCSR |
||
| 17 | { |
||
| 18 | use Traits\GetSetUnset; |
||
| 19 | |||
| 20 | protected $MD5; |
||
| 21 | protected $SHA1; |
||
| 22 | protected $Endpoint = "https://secure.comodo.net/products/!decodeCSR"; |
||
| 23 | protected $CSR; |
||
| 24 | /** |
||
| 25 | * An array of warnings that can be show after the test |
||
| 26 | * @var array |
||
| 27 | */ |
||
| 28 | protected $warnings = []; |
||
| 29 | protected $Form = [ |
||
| 30 | 'responseFormat' => 'N', |
||
| 31 | 'showErrorCodes' => 'N', |
||
| 32 | 'showErrorMessages' => 'N', |
||
| 33 | 'showFieldNames' => 'N', |
||
| 34 | 'showEmptyFields' => 'N', |
||
| 35 | 'showCN' => 'N', |
||
| 36 | 'showAddress' => 'N', |
||
| 37 | 'showPublicKey' => 'N', |
||
| 38 | 'showKeySize' => 'N', |
||
| 39 | 'showSANDNSNames' => 'Y', |
||
| 40 | 'showCSR' => 'N', |
||
| 41 | 'showCSRHashes' => 'Y', |
||
| 42 | 'showSignatureAlgorithm' => 'N', |
||
| 43 | 10 | 'product' => '', |
|
| 44 | 'countryNameType' => 'TWOCHAR' |
||
| 45 | 10 | ]; |
|
| 46 | private $request; |
||
| 47 | 10 | ||
| 48 | 10 | private $forceSSL = false; |
|
| 49 | 10 | ||
| 50 | public function getCN() |
||
| 51 | 10 | { |
|
| 52 | $CSRInfo = $this->decodeCSR(); |
||
| 53 | return $CSRInfo['subject']['CN']; |
||
| 54 | 10 | } |
|
| 55 | |||
| 56 | 2 | public function setCSR($csr) |
|
| 57 | 2 | { |
|
| 58 | $this->CSR = $csr; |
||
| 59 | 2 | //Check that this is a valid CSR |
|
| 60 | $this->decodeCSR(); |
||
| 61 | $this->Form['csr'] = $csr; |
||
| 62 | 2 | } |
|
| 63 | 2 | ||
| 64 | 1 | protected function addWarning($code, $message) |
|
| 65 | 10 | { |
|
| 66 | $this->warnings[] = [ |
||
| 67 | 1 | $code => $message |
|
| 68 | 1 | ]; |
|
| 69 | } |
||
| 70 | |||
| 71 | 7 | public function fetchHashes() |
|
| 72 | { |
||
| 73 | 7 | $client = new Client(); |
|
| 74 | 7 | ||
| 75 | $this->request = $client->request('POST', $this->getEndpoint(), [ |
||
| 76 | 7 | 'form_params' => $this->Form |
|
| 77 | ]); |
||
| 78 | |||
| 79 | 7 | return $this->processResponse(); |
|
| 80 | } |
||
| 81 | 7 | ||
| 82 | public function checkInstalled() |
||
| 83 | { |
||
| 84 | 7 | ||
| 85 | 2 | try { |
|
| 86 | $domain = $this->getCN(); |
||
| 87 | } catch (\Exception $e) { |
||
| 88 | return false; |
||
| 89 | 5 | } |
|
| 90 | 1 | ||
| 91 | 1 | $response = $this->fetchDVCFile($domain); |
|
| 92 | if ($response == false) { |
||
| 93 | return false; |
||
| 94 | 5 | } |
|
| 95 | |||
| 96 | 2 | $check = $this->checkDVC($response); |
|
| 97 | 2 | if ($check === true) { |
|
| 98 | return $check; |
||
| 99 | } |
||
| 100 | 5 | ||
| 101 | 2 | //Try again but this time use https:// |
|
| 102 | $this->forceSSL = true; |
||
| 103 | |||
| 104 | 3 | $response = $this->fetchDVCFile($domain); |
|
| 105 | if ($response == false) { |
||
| 106 | return false; |
||
| 107 | 2 | } |
|
| 108 | |||
| 109 | 2 | $check = $this->checkDVC($response); |
|
| 110 | 2 | if ($check === true) { |
|
| 111 | 2 | //TODO Add a message to say then you will need to select 'HTTPS CSR |
|
| 112 | 2 | //Hash' |
|
| 113 | return $check; |
||
| 114 | } |
||
| 115 | 2 | ||
| 116 | return false; |
||
| 117 | 2 | } |
|
| 118 | |||
| 119 | public function generateDVC() |
||
| 120 | 10 | { |
|
| 121 | $DVC = $this->getSHA1() . "\n"; |
||
| 122 | 10 | $DVC .= "comodoca.com\n"; |
|
| 123 | 10 | ||
| 124 | 10 | return $DVC; |
|
| 125 | } |
||
| 126 | |||
| 127 | 10 | /** |
|
| 128 | * |
||
| 129 | 10 | * @param GuzzleHttp\Psr7\Response $response |
|
| 130 | 10 | * @return bool |
|
| 131 | 10 | */ |
|
| 132 | 10 | public function checkDVC(Response $response) |
|
| 133 | 10 | { |
|
| 134 | 10 | $body = $response->getBody() . ''; |
|
| 135 | $DVC = $this->generateDVC(); |
||
| 136 | 10 | ||
| 137 | 10 | //Check if we received a 301 or 302 redirect |
|
| 138 | if ($response->getStatusCode() === 301 || $response->getStatusCode() == 302) { |
||
| 139 | 10 | return false; |
|
| 140 | } |
||
| 141 | |||
| 142 | //If the response matches the DVC value return true |
||
| 143 | if ($body === $DVC) { |
||
| 144 | return true; |
||
| 145 | } |
||
| 146 | |||
| 147 | //Check if last 2 characters are new lines |
||
| 148 | if (substr($body, -2) === "\n\n") { |
||
| 149 | $body = substr($body, 0, -2) . "\n"; |
||
| 150 | } |
||
| 151 | |||
| 152 | //Check if last character is not a new line |
||
| 153 | if (substr($body, -1) !== "\n") { |
||
| 154 | //Add said new line |
||
| 155 | $body = $body . "\n"; |
||
| 156 | } |
||
| 157 | |||
| 158 | var_dump($body, $DVC); |
||
|
0 ignored issues
–
show
Security
Debugging Code
introduced
by
Loading history...
|
|||
| 159 | |||
| 160 | //Check it again |
||
| 161 | if ($body === $DVC) { |
||
| 162 | return true; |
||
| 163 | } |
||
| 164 | |||
| 165 | return false; |
||
| 166 | } |
||
| 167 | |||
| 168 | private function decodeCSR() |
||
| 169 | { |
||
| 170 | try { |
||
| 171 | $data = openssl_csr_get_public_key($this->getCSR()); |
||
| 172 | $details = openssl_pkey_get_details($data); |
||
| 173 | $key = $details['key']; |
||
| 174 | $subject = openssl_csr_get_subject($this->getCSR()); |
||
| 175 | } catch (\Exception $e) { |
||
| 176 | throw new Exception("Invalid CSR"); |
||
| 177 | } |
||
| 178 | |||
| 179 | return array( |
||
| 180 | "subject" => $subject, |
||
| 181 | "key" => $key |
||
| 182 | ); |
||
| 183 | } |
||
| 184 | |||
| 185 | private function processResponse() |
||
| 186 | { |
||
| 187 | $response = $this->request->getBody(); |
||
| 188 | $lines = explode("\n", $response); |
||
| 189 | $data = array(); |
||
| 190 | //Remove the first array as we don't need the SAN and can cause problems |
||
| 191 | //with a multi domain SAN |
||
| 192 | unset($lines[0]); |
||
| 193 | |||
| 194 | foreach ($lines as $v) { |
||
| 195 | if (!empty($v)) { |
||
| 196 | $value = explode("=", $v); |
||
| 197 | $data[$value[0]] = $value[1]; |
||
| 198 | } |
||
| 199 | } |
||
| 200 | |||
| 201 | $this->setMD5($data["md5"]); |
||
| 202 | $this->setSHA1($data["sha1"]); |
||
| 203 | |||
| 204 | return $data ? $data : false; |
||
| 205 | } |
||
| 206 | |||
| 207 | private function fetchDVCFile($domain) |
||
| 208 | { |
||
| 209 | //We do most of our DVC over http:// unless the site is fully SSL |
||
| 210 | $protocol = 'http://'; |
||
| 211 | |||
| 212 | if ($this->forceSSL) { |
||
| 213 | $protocol = 'https://'; |
||
| 214 | } |
||
| 215 | |||
| 216 | $url = $protocol . $domain . "/" . $this->getMD5() . '.txt'; |
||
| 217 | |||
| 218 | $client = new Client(['allow_redirects' => false, 'verify' => false]); |
||
| 219 | |||
| 220 | try { |
||
| 221 | $response = $client->request('GET', $url); |
||
| 222 | } catch (ClientException $e) { |
||
| 223 | var_dump('te', $e); |
||
|
0 ignored issues
–
show
|
|||
| 224 | return false; |
||
| 225 | } |
||
| 226 | |||
| 227 | return $response; |
||
| 228 | } |
||
| 229 | } |
||
| 230 |