Skip to content

Commit 40687a2

Browse files
authored
X509: discuss new setURLFetchCallback method
1 parent 9b02f78 commit 40687a2

1 file changed

Lines changed: 23 additions & 1 deletion

File tree

docs/x509.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,28 @@ echo $x509->validateSignature() ? 'valid' : 'invalid';
122122

123123
Certificate authority certificates can be downloaded from [curl - SSL CA Certificates](https://curl.haxx.se/docs/caextract.html). Parsing that is left as an exercise to the reader.
124124

125+
Note that when the certificate being validated is issued by a CA that isn't already in your trust store, phpseclib will, by default, read any caIssuers URL from the certificate's Authority Information Access (AIA) extension and connect to it to try to download the missing intermediate. Because that URL comes from the certificate itself, a maliciously crafted certificate can point it at an address on the host's own network (eg. loopback, a cloud metadata endpoint such as 169.254.169.254, an internal-only service, etc) turning validation into a [server-side request forgery](https://en.wikipedia.org/wiki/Server-side_request_forgery) vector.
126+
127+
You can disable this behavior entirely with `X509::disableURLFetch()`. As of 3.0.54 you can instead keep fetching enabled but restrict where phpseclib will connect, by registering a callback that approves or rejects each destination:
128+
129+
```php
130+
X509::setURLFetchCallback(function (string $host, string $ip, int $port, string $scheme): bool {
131+
if ($scheme !== 'http' && $scheme !== 'https') {
132+
return false;
133+
}
134+
135+
$public = filter_var(
136+
$ip,
137+
FILTER_VALIDATE_IP,
138+
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
139+
);
140+
141+
return $public !== false; // public address -> allow; internal/reserved -> deny
142+
});
143+
```
144+
145+
The callback receives the resolved IP, host, port, and scheme, and returns true to allow the connection or false to block it. The example above permits only publicly-routable addresses. If instead you run an internal CA (eg. its AIA endpoint lives on 10.x.x.x) you'd invert the logic and allow only your specific internal range.
146+
125147
### Self-signed Signatures
126148

127149
```php
@@ -423,4 +445,4 @@ $result = $x509->sign($issuer, $subject);
423445
#-----[ BEFORE, ADD ]-----------------------------------
424446
#
425447
$x509->setExtensionValue($customExtensionName, $customExtensionData);
426-
```
448+
```

0 commit comments

Comments
 (0)