SsrfGuardedClient
in package
implements
ClientInterface
SSRF ガードを挟む PSR-18 クライアントのデコレーター。
委譲先のクライアントへ渡す前に取得先を検証し、リダイレクトもホップごとに 検証したうえで自前で追従する。委譲先には自動追従をさせない設定を与えること。
Table of Contents
Interfaces
- ClientInterface
Constants
- DEFAULT_MAX_REDIRECTS = 10
- 追従を許可するリダイレクト回数の既定値
- REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308]
- リダイレクトとみなすステータスコード
- XML_CONTENT_TYPE_NEEDLE = 'xml'
- XML と判定する Content-Type の部分一致キーワード
Properties
- $guard : SsrfGuard
- $inner : ClientInterface
- $maxRedirects : int
- $uriFactory : UriFactoryInterface
Methods
- __construct() : mixed
- sendRequest() : ResponseInterface
- assertFetchable() : array<string|int, string>
- 取得してよい URI か検証し、検証を通った IP アドレス一覧を返す
- assertSafeXmlBody() : ResponseInterface
- oEmbed の XML 応答に DOCTYPE / ENTITY 宣言が(位置を問わず)含まれていないか検査する。
- resolveRedirectUri() : string
- リダイレクト元 URI と Location ヘッダの値から絶対 URI を組み立てる
Constants
DEFAULT_MAX_REDIRECTS
追従を許可するリダイレクト回数の既定値
private
mixed
DEFAULT_MAX_REDIRECTS
= 10
Why not: 独自に小さい値を決めないのは、それまで curl の自動追従(CURLOPT_MAXREDIRS の 既定 10)で取得できていたページが、ホップ数だけを理由に取得できなくなるのを避けるため。
REDIRECT_STATUS_CODES
リダイレクトとみなすステータスコード
private
mixed
REDIRECT_STATUS_CODES
= [301, 302, 303, 307, 308]
XML_CONTENT_TYPE_NEEDLE
XML と判定する Content-Type の部分一致キーワード
private
mixed
XML_CONTENT_TYPE_NEEDLE
= 'xml'
Properties
$guard
private
SsrfGuard
$guard
$inner
private
ClientInterface
$inner
$maxRedirects
private
int
$maxRedirects
$uriFactory
private
UriFactoryInterface
$uriFactory
Methods
__construct()
public
__construct(ClientInterface $inner, UriFactoryInterface $uriFactory[, SsrfGuard|null $guard = null ][, int $maxRedirects = self::DEFAULT_MAX_REDIRECTS ]) : mixed
Parameters
- $inner : ClientInterface
-
実際に HTTP 取得を行うクライアント(自動リダイレクト追従は無効にしておく)
- $uriFactory : UriFactoryInterface
-
リダイレクト先の URI を組み立てるファクトリ
- $guard : SsrfGuard|null = null
-
null なら既定の設定でガードを組み立てる
- $maxRedirects : int = self::DEFAULT_MAX_REDIRECTS
-
追従を許可するリダイレクト回数の上限
sendRequest()
public
sendRequest(RequestInterface $request) : ResponseInterface
Parameters
- $request : RequestInterface
Tags
Return values
ResponseInterfaceassertFetchable()
取得してよい URI か検証し、検証を通った IP アドレス一覧を返す
private
assertFetchable(string $uri) : array<string|int, string>
Parameters
- $uri : string
Tags
Return values
array<string|int, string> —検証を通った IP アドレス一覧(接続のピンニングに使う)
assertSafeXmlBody()
oEmbed の XML 応答に DOCTYPE / ENTITY 宣言が(位置を問わず)含まれていないか検査する。
private
assertSafeXmlBody(ResponseInterface $response) : ResponseInterface
Why not: embed/embed 側の DOCTYPE 除去(\Embed\OEmbed::extractXML)は文字列先頭に
厳密にアンカーされた正規表現(/^<!DOCTYPE[^>]*+>/i)のため、先頭に XML 宣言や空白がある
応答では除去されずに SimpleXMLElement へそのまま渡り、Billion Laughs / Quadratic Blowup に
よるメモリ枯渇(DoS)を許してしまう。ここでは HTTP レイヤーで位置を問わず検出し、
応答自体を拒否する(vendor 側の直接パッチは CMS アップデートで上書きされるため避ける)。
Parameters
- $response : ResponseInterface
Tags
Return values
ResponseInterfaceresolveRedirectUri()
リダイレクト元 URI と Location ヘッダの値から絶対 URI を組み立てる
private
resolveRedirectUri(string $baseUri, string $location) : string
Parameters
- $baseUri : string
- $location : string