Set HttpOnly for all outbound cookies in Apache, .Net and Classic ASP

Posted: November 19, 2013 in .Net/C#, Web Server
Tags: , , , ,

we are required to enable HttpOnly in all our servers because it presents a potential XSS vulnerability. For more information on httpOnly, please read https://www.owasp.org/index.php/HttpOnly.

It’s very easy to enable it globally in .Net and Apache/PHP.

.Net 2.0+

//add the following line to the web.config system.web section
<httpCookies httpOnlyCookies="true">

Apache

//add the following line to the http.conf. Make sure mod_headers is enabled
Header edit Set-Cookie ^(.*)$ $1;HttpOnly

 

The sad story is that, one of our legacy server is running classic ASP…

I googled a few days and cannot find a working solution. Microsoft has one example on how to set cookie to httponly through ISAPI Filter (http://msdn.microsoft.com/en-us/library/ms972826), but only works for one cookie situation, which means no cookie because there is already one by default: ASPSESSIONIDxxxx.

After reading some documentation, I modified the Microsoft example to make it work for multiple cookies.

First, you need create a new Win32 Dynamic-Link Library project in Visual C++ 6.0 and create two files: httponly.cpp and httponlydef. Below are the source code for both files.

httponly.cpp

#define STRSAFE_NO_DEPRECATE

#include <windows.h>
#include <httpfilt.h>
#include "tchar.h"
#include "strsafe.h"


BOOL WINAPI GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
    pVer->dwFlags =  SF_NOTIFY_PREPROC_HEADERS  | SF_NOTIFY_SEND_RESPONSE;

    pVer->dwFilterVersion = HTTP_FILTER_REVISION;

    strcpy(pVer->lpszFilterDesc, "HttpOnly Filter, Version 1.0"); 

    return TRUE;
}


// Portion of HttpOnly
DWORD WINAPI HttpFilterProc(
   PHTTP_FILTER_CONTEXT pfc,
   DWORD dwNotificationType,
   LPVOID pvNotification) {

   // Hard coded cookie length (2k bytes)
   CHAR szCookie[2048];
   DWORD cbCookieOriginal = sizeof(szCookie) / sizeof(szCookie[0]);
   DWORD cbCookie = cbCookieOriginal;
	
      HTTP_FILTER_SEND_RESPONSE *pResponse = 
         (HTTP_FILTER_SEND_RESPONSE*)pvNotification;

      CHAR *szHeader = "Set-Cookie:";
      CHAR *szHttpOnly = "; HttpOnly";
      if (pResponse->GetHeader(pfc,szHeader,szCookie,&cbCookie)) {
         /*if (SUCCEEDED(StringCchCat(szCookie,
                                    cbCookieOriginal,
                                    szHttpOnly))) {
            if (!pResponse->SetHeader(pfc,
                                      szHeader,
                                      szCookie)) {
                        // Fail securely - send no cookie!
                        pResponse->SetHeader(pfc,szHeader,"");
               }
            } else {
               pResponse->SetHeader(pfc,szHeader,"");
	 }*/
	 pResponse->SetHeader(pfc,szHeader,"");
	 CHAR outCookie[2048];
	 char * token;
	 // the last occurence of semicolon
	 char * semi; 
	 token = strtok (szCookie,",");
	 while (token != NULL)
	 {
		strcpy(outCookie, "");
		strcat (outCookie, token);

		semi = strrchr(token, ';');
		//if the last character is ;
		if(semi - token == strlen(token) - 1){
			strcat (outCookie, " HttpOnly");
		}
		else{
			strcat (outCookie, "; HttpOnly");
		}

		pResponse->AddHeader(pfc, szHeader, outCookie);
			
		memset(outCookie, 0, 2048);
		token = strtok (NULL, ",");
	 }
   }

   return SF_STATUS_REQ_NEXT_NOTIFICATION;
}

httponly.def

LIBRARY HttpOnly
EXPORTS
    GetFilterVersion
    HttpFilterProc

For information on how to create a ISAPI filter using Visual C++, you can refer to http://blogs.msdn.com/b/david.wang/archive/2005/12/19/howto-compile-and-use-my-isapi-code-samples.aspx.

Comments
  1. Shane says:

    Can I get a copy of this compiled ISAPI DLL emailed to me?

  2. Muthukaruppan says:

    Hi,
    I tried above code.But my issue not resolved. And I checked in Event log,It’s shows like,
    “The HTTP Filter DLL D:\….\ISAPIFilter.dll failed to load.  The data is the error.”
    “Could not load all ISAPI filters for site/service.  Therefore startup aborted”

Leave a comment