I've two PHP apps one on localhost:8080
(vuln) and the other on localhost:42069
(attacker).
8080
has a login page, which on login saves a cookie.
42069
sets no cookies (has no PHP code) and only has an HTML form that logs the user out of 8080
using a logout POST request.
When I log document.cookie
at 42069
after logging into 8080
I get to see the same cookie as 8080
.
What's going on here?
App sources repo. Run the app with start.sh
.
This is because both sites have the same domain localhost
. Your Browser stores cookies for each domain which is determined by the part after the protocol(http
, https
) and before the first /
. In your case localhost:8080
and localhost:42069
are considered to be the same domain. Cookies set by on page will be available to the other page as well.
This behavior is defined in RFC6265
1.Introduction
[...]
For historical reasons, cookies contain a number of security and privacy infelicities. For example, a server can indicate that a given cookie is intended for "secure" connections, but the Secure attribute does not provide integrity in the presence of an active network attacker. Similarly, cookies for a given host are shared across all the ports on that host, even though the usual "same-origin policy" used by web browsers isolates content retrieved via different ports.
And
8.5. Weak Confidentiality
Cookies do not provide isolation by port. If a cookie is readable by a service running on one port, the cookie is also readable by a service running on another port of the same server.
If you want the two apps to have separate cookies you could try to use subdomains or different top-level domains: E.g. app1.localhost:8080
and app2.localhost:42069
. This may cause the browser to store the cookies separatly.
Note this is not guaranteed to work see here
8.6. Weak Integrity
Cookies do not provide integrity guarantees for sibling domains (and their subdomains). For example, consider foo.example.com and bar.example.com. The foo.example.com server can set a cookie with a Domain attribute of "example.com" (possibly overwriting an existing "example.com" cookie set by bar.example.com), and the user agent will include that cookie in HTTP requests to bar.example.com. In the worst case, bar.example.com will be unable to distinguish this cookie from a cookie it set itself. The foo.example.com server might be able to leverage this ability to mount an attack against bar.example.com.
You can run one page on localhost
and the other on 127.0.0.1
or 127.0.0.2
, etc. Because these are two different domains. Means a cookie on localhost
cannot be shared with 127.0.0.x
and vice versa.
#!/bin/bash
if ! ( which php > /dev/null ); then
echo 'error: php not installed'
exit 1
fi
php -S localhost:8080 --docroot=website-vuln/public/ 2>> vuln.log >> vuln.log &
php -S 127.0.0.1:42069 --docroot=website-evil/public/ 2>> evil.log >> evil.log &
echo vuln server @ http://localhost:8080
echo evil server @ http://127.0.0.1:42069
On Linux /etc/hosts
can be used to create more cookie domains for 127.0.0.1
than localhost
. And as many meaningfull names for 127.0.0.x
E.g. /etc/hosts
127.0.0.1 app1
127.0.0.1 app2
Then you can modify your script to:
#!/bin/bash
if ! ( which php > /dev/null ); then
echo 'error: php not installed'
exit 1
fi
php -S app1:8080 --docroot=website-vuln/public/ 2>> vuln.log >> vuln.log &
php -S app2:42069 --docroot=website-evil/public/ 2>> evil.log >> evil.log &
echo vuln server @ http://app1:8080
echo evil server @ http://app2:42069
Now you have to change the link in your form:
<form method="POST" action="http://app1:8080/">
In Windows 10 the hosts file is located at c:\Windows\System32\Drivers\etc\hosts
.