According to MDN document:
To prevent cross-site scripting (XSS) attacks, HttpOnly cookies are inaccessible to JavaScript's Document.cookie API; they are only sent to the server.
I found a scenario to replace HttpOnly cookie by JavaScript, here's the PoC in ASP.NET:
<%@Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
if (Request["m"] == "check")
{
Response.Write("Cookie=" + Request.Cookies["C"].Value);
Response.End();
}
else
{
Response.AppendCookie(new HttpCookie("C")
{
Value = "ByServer",
HttpOnly = true
});
}
}
</script>
<html>
<body>
<div>
document.cookie -> <span id=t></span>
</div>
<script>
document.getElementById("t").innerHTML = document.cookie;
document.cookie="C=ByClient";
</script>
<a href="?m=check">Check Cookie</a>
</body>
</html>
In the test of Chrome, reading document.cookie gets nothing proves that the HttpOnly cookie is indeed unreadable to JavaScript. But by setting document.cookie = "C=ByClient", two cookies with different paths exist concurrently.
Then check the cookie from server side, Request.Cookies["C"] returns "ByClient" given by JavaScript, but not "ByServer" assigned by server. The HttpOnly cookie is overwriten by client.
The result will be different if we set the exact HttpCookie.Path:
Response.AppendCookie(new HttpCookie("C")
{
Value = "ByServer",
HttpOnly = true,
Path = "/asp/httponlycookie"
});
Now document.cookie="ByClient" failed to add or change the cookie, the HttpOnly cookie is protected.
Can I reach a conclusion: that HttpOnly property only guarantees the cookie not readable to JavaScript, the HttpOnly cookie is still possible to be replaced or overwriten by JavaScript?