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); |
|
0 ignored issues
–
show
|
|||
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); |
|
0 ignored issues
–
show
$response of type object<Psr\Http\Message\ResponseInterface> is not a sub-type of object<GuzzleHttp\Psr7\Response> . It seems like you assume a concrete implementation of the interface Psr\Http\Message\ResponseInterface to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
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
|
|||
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 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.