Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HMAC/IP support for different remote IP's through proxies & Cloud… #49

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions src/AntiCSRF.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,7 @@ public function getTokenArray(string $lockTo = ''): array
$token = Base64UrlSafe::encode(
\hash_hmac(
$this->hashAlgo,
isset($this->server['REMOTE_ADDR'])
? (string) $this->server['REMOTE_ADDR']
: '127.0.0.1',
$this->getRemoteIP(),
(string) Base64UrlSafe::decode($token),
true
)
Expand Down Expand Up @@ -407,9 +405,7 @@ public function validateRequestOrThrow()
$expected = Base64UrlSafe::encode(
\hash_hmac(
$this->hashAlgo,
isset($this->server['REMOTE_ADDR'])
? (string) $this->server['REMOTE_ADDR']
: '127.0.0.1',
$this->getRemoteIP(),
(string) Base64UrlSafe::decode((string) $stored['token']),
true
)
Expand Down Expand Up @@ -548,4 +544,34 @@ protected static function noHTML(string $untrusted): string
{
return \htmlentities($untrusted, ENT_QUOTES, 'UTF-8');
}

/**
* Wrapper to support different sources of remote IP addresses.
*
* @return string
*/
protected function getRemoteIP(): string
{
if (isset($this->server["HTTP_CF_CONNECTING_IP"]) && filter_var($this->server["HTTP_CF_CONNECTING_IP"], FILTER_VALIDATE_IP))
{
return $this->server["HTTP_CF_CONNECTING_IP"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if an attacker specifies a fake header here after discovering the server's real IP?

What if an attacker specifies this header for a non-CloudFlare IP?

Etc.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you suggest validating against the REMOTE_ADDR to the CloudFlare IP ranges? https://www.cloudflare.com/ips/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and this can be hard-coded. We can update it in the future if their list of IPs widens.

}

if (isset($this->server["HTTP_X_FORWARDED_FOR"]) && filter_var($this->server["HTTP_X_FORWARDED_FOR"], FILTER_VALIDATE_IP))
{
return $this->server["HTTP_X_FORWARDED_FOR"];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attackers can lie about X-Forwarded-For. This should be guarded by a configuration setting.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you suggest? A configuration setting as in hmac_ip_allow_x_forwarded_for? Or something more general that would include both this option as well as CloudFlare for example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a configuration setting would be a good idea. Let people opt into this behavior.


if (isset($this->server["HTTP_CLIENT_IP"]) && filter_var($this->server["HTTP_CLIENT_IP"], FILTER_VALIDATE_IP))
{
return $this->server["HTTP_CLIENT_IP"];
}

if (isset($this->server['REMOTE_ADDR']))
{
return $this->server['REMOTE_ADDR'];
}

return '127.0.0.1';
}
}