IT Nota

  • Home
  • How To
  • .NET
  • WordPress
  • Contact

How to Enable Secure HttpOnly Cookies in IIS

Session cookies are often seen as one of the biggest problems for security and privacy with HTTP, yet often times, it’s necessary to utilize it to maintain state in modern web applications. By default, it is insecure and vulnerable to be intercepted by an authorized party.

Cookies typically store session identifiers that may offer full access to an account, therefore if a cookie is intercepted, a session can be hijacked by someone who is not the real user but pretending as that user.

For this reason, it’s very important that we need to set parameters on how the cookies are passed and have it encrypted as they get sent/read between a web server and the browser.

In order to make cookies more secure to use, there are two things we need to pay attention to, they are HttpOnly and Secure flags.

HttpOnly Flag

The first flag we need to set up is HttpOnly flag. By default, when there’s no restriction in place, cookies can be transferred not only by HTTP, but any JavaScript files loaded on a page can also access the cookies. This ability can be dangerous because it makes the page vulnerable to cross-site scripting (XSS) attack.

The only way to restrict this is by setting HttpOnly flag, which means the only way cookies are sent is via HTTP connection, not directly through other means (i.e., JavaScript).

Secure Flag

The second flag we need to pay attention to is Secure flag. This flag highlights the second issue that by default cookies are always sent on both HTTP and HTTPS requests. A malicious attacker who can’t see encrypted traffic with HTTPS connection can easily switch to HTTP connection and access the same cookie because it is not encrypted. Therefore, we need to set the Secure flag to ensure that the cookie in encrypted when it’s created.

Enable HttpOnly Flag in IIS

Edit the web.config file of your web application and add the following:

<system.web>
  ...
  <httpCookies httpOnlyCookies="true" requireSSL="true" />
  ...
</system.web>

Enable Secure Flag in IIS

To enable secure flag in IIS, it is better to use URL Rewrite and add the following to your web.config file:

<system.webServer>
  <rewrite>
    <outboundRules>
      <rule name="Use only secure cookies" preCondition="Unsecured cookie">
        <match serverVariable="RESPONSE_SET_COOKIE" pattern=".*" negate="false" />
        <action type="Rewrite" value="{R:0}; secure" />
      </rule>
      <preConditions>
        <preCondition name="Unsecured cookie">
          <add input="{RESPONSE_SET_COOKIE}" pattern="." />
          <add input="{RESPONSE_SET_COOKIE}" pattern="; secure" negate="true" />
        </preCondition>
      </preConditions>
    </outboundRules>
  </rewrite>
...
</system.webServer>

Check Flags Settings

This example demonstrates an ASP.NET website that has HttpOnly flag set, but not the Secure flag using a professional web scan tool.

Scan result for cookie with missing secure flag

The scanner did not detect secure flag in the HTTP header with the following explanations:

Cookie Missing ‘Secure’ Flag

Description

The session ID does not have the ‘Secure’ attribute set. This attribute prevents cookies from being seen in plaintext. It may be possible for a malicious actor to steal cookie data and perform session theft through man-in-the-middle (MITM) or traffic sniffing attacks. The exploitable condition exists for unencrypted cookies to be passed over the network if a user accesses the site through HTTP instead of HTTPS, or if a link to a resource such as an image file or CSS file within the specified domain uses the HTTP protocol.

Risk

Data may be exposed to unauthorized parties during cookie transmission and increases the risk of session theft via man-in-the-middle (MITM) or traffic sniffing attacks.

Recommendation

Change the default ‘Secure’ attribute from FALSE to TRUE to ensure cookies are sent only via HTTPS. The ‘Secure’ attribute should be set on each cookie to prevent cookies from being observed by malicious actors. Implement the ‘Secure’ attribute when using the Set-Cookie parameter during authenticated sessions.

After applying the recommended configuration mentioned above, the scan result is good as shown below.

Scan result after secure flag is activated for cookie

As you may have noticed, in this particular example, the Session Cookie Missing ‘HttpOnly’ Flag was already fixed.

Checking the header using cURL:

$ curl -I https://www.itnota.com

Before

HTTP/1.1 200 OK
Cache-Control: private, no-store, max-age=0, s-maxage=0
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.5
Set-Cookie: ASP.NET_SessionId=o42zbtr1rzzje3wlvwwcnjmv; path=/; HttpOnly
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
Date: Tue, 10 Jul 2018 20:42:03 GMT
Content-Length: 6722

After

HTTP/1.1 200 OK
Cache-Control: private, no-store, max-age=0, s-maxage=0
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.5
Set-Cookie: ASP.NET_SessionId=bhn5qcmggcxdy34g5d4kp3hk; path=/; HttpOnly; secure
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
Date: Tue, 10 Jul 2018 20:46:38 GMT
Content-Length: 6722

Notice the word secure after the HttpOnly at the end of the line of Set-Cookie HTTP header.

Emphasis

Set-Cookie: ASP.NET_SessionId=bhn5qcmggcxdy34g5d4kp3hk; path=/; HttpOnly; secure

Buy me a coffee?

Buy me a coffee If you find this post helpful and would like to buy me a coffee to support the work here, you’ll have our big thanks!
Support IT Nota: Buy me a Coffee

Download

URL Rewrite

Further Reading

HTTP/2 in Action
The Secure Attribute
The HttpOnly Attribute
httpCookies Element (ASP.NET Settings Schema)
Ensuring secure cookies with URL Rewrite
How to Setup HTTP Strict Transport Security (HSTS) on IIS

May 2, 2019 Filed Under: How To Tagged With: IIS, Information Security, Internet, Internet Information Services

How to Create iCloud Mail Email Address

Many people assume that just by creating an Apple ID, they automatically have an iCloud email address. This is not necessarily the case since people typically use a different email address as their Apple ID.

In order to use an @icloud.com (or @mac.com, @me.com for that matter) email address, you must set that up separately and this is actually a required step if you plan to use iCloud Mail.

So here are the steps to do it from your iOS device:

  1. Go to Settings and go to very top until you see your name and tap on it.

    iPhone iCloud settings

  2. On the next screen, type on iCloud.

    iPhone settings iCloud account

  3. Look for Mail under APPS USING ICLOUD and turn it on. If it’s already On, that means you’ve already had and @icloud.com email address.

    Enable iCloud email on iPhone

  4. Once the Mail is On, you see an option to Create it. Just follow the instructions from there.

    Create @icloud.com email address on iPhone

Once you finished setting it up, you can also use that as your Apple ID email address.

Further Reading

iCloud: Set up an iCloud Mail email address

April 5, 2019 Filed Under: How To Tagged With: iOS

How to Import IIS Log to PostgreSQL

If you ever had a need to dump and analyze IIS logs from a database, this post will show you how to do it in PostgreSQL RDBMS.

The assumption is that you’re already familiar with the default installation and setup of PostgreSQL, if not please check the manual link at the bottom of this post. We will use default settings.

Steps to Create IIS Log Table and Import Log File to PostgreSQL

  1. Create a database called mydb.

  2. We need to prepare a table that matches the fields from IIS log, so we need to create a table called iislog by running the following SQL:

    CREATE TABLE public.iislog
    (
        date date,
        "time" time without time zone,
        sip character varying(48) COLLATE pg_catalog."default",
        csmethod character varying(8) COLLATE pg_catalog."default",
        csuristem character varying(255) COLLATE pg_catalog."default",
        csuriquery character varying(2048) COLLATE pg_catalog."default",
        sport character varying(4) COLLATE pg_catalog."default",
        susername character varying(256) COLLATE pg_catalog."default",
        cip character varying(48) COLLATE pg_catalog."default",
        csuseragent character varying(1024) COLLATE pg_catalog."default",
        csreferer character varying(4096) COLLATE pg_catalog."default",
        scstatus integer,
        scsubstatus integer,
        scwin32status bigint,
        timetaken integer
    )
    WITH (
        OIDS = FALSE
    )
    TABLESPACE pg_default;
    
    ALTER TABLE public.iislog
        OWNER to postgres;
    
  3. Go to the location of where the IIS log files are stored. By default, the location is in the following folder:

    %SystemDrive%\inetpub\logs\LogFiles
    

    However, as the best practice, most enterprise applications will have a different location on a different drive for log. In this example, we’ll use C:\Temp\IISLogs\ folder.

  4. We will certainly not going to import each log file one-by-one to the database, so the best thing to do before we do the import is to combine all the log files we want to analyze. Just for the sake of simplicity for this demonstration, we want to include all log files within this folder and combine them into one big log file. We can do this by opening either a Command Prompt or PowerShell Windows. It doesn’t matter which one you prefer, it will work the same way.

  5. In the Command Prompt or PowerShell Window, make sure you’re in the IIS log folder and type in the following command:

    Command only

    type *.log > filename.log
    

    Command with prompt (as in this example)

    C:\Temp\IISLog> type *.log > combinedLogs.log
    

    *The prompt is included to show that you need to be in your IIS log folder to execute this operation.

  6. Now we need to massage the combined log file a bit before we can import it within one operation.

    If you open the new log file (combinedLogs.log) with a text editor, you will see all the headers from every single log file were included as well and it looks something similar to this:

    #Software: Microsoft Internet Information Services 10.0
    #Version: 1.0
    #Date: 2018-08-02 15:08:58
    #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
    
  7. By using a text editor such as Sublime Text, we can clean up this log file by using Regex Find and Replace.

    From the top menu, go to Find and Replace… (CTRL-H in Windows) and make sure the Regex option is activated and type (or copy and paste) the following search string in the Find: box:

    #Software: Microsoft Internet Information Services 10.0\n#Version: 1.0\n#Date: [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\n#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs\(User-Agent\) cs\(Referer\) sc-status sc-substatus sc-win32-status time-taken\n
    

    Remove IIS Log headers using Regex Find and Replace

  8. Press Replace All button to remove all instances of those headers and re-save the file.

  9. Now we will import this log file by using COPY command.

    Go back to PostgreSQL shell and type in the following:

    COPY public.iislog FROM 'c:\temp\iislogs\combinedLogs.log' DELIMITER ' ';
    

    *If you use a different table name and location of IIS log, make sure you change it to match yours.

That’s all there is, now you should be able to query the log and slice and dice the data however you need it.

Caveat

Important: If you have a rather big combined log file (even only a few MB in size), make sure you do the import from the command line. Do not use pgAdmin web interface as it may not be able to handle the load.

Further Reading

PostgreSQL Manuals

Download

PostgreSQL

March 20, 2019 Filed Under: How To Tagged With: IIS, Internet Information Services, PostgreSQL, SQL

How to Add Custom Logging to SSIS Package

This post will demonstrate one way to add custom logging to SSIS Package. This is still considered one of the better practice that comes in handy when we need to troubleshoot SSIS packages and track progress.

There’s no better way to explain the concept other than giving a simple case example on how to add it to a real SSIS package.

For starter, the package in this example does a simple data load from LDAP table to a SQL Server table with some minimal check done with a Script Component.

Setup Global Variables for Logging

Before we do anything else, it’s recommended to setup a few global variables that we can use to keep track of the log variables.

Setup global variables for the log folder and filename with a prefix of gv for Global Variable. The use of prefix is very handy since all those global variables will be sorted nicely and will be easy to find during troubleshooting.

SSIS Global Variables setup
*One of the global variable is made up with an expression to dynamically name the log file according to today’s date.

@[Log::gv_RootPath] + "\\" +  @[Log::gv_LogDir] + "\\" + REPLACE(@[Log::gv_LogFileName], ".log", "") + "-" + SUBSTRING((DT_STR, 50, 1252) GETDATE(), 1, 10) + ".log"

Setup Log File Connection Manager

We are going to write the log to a text file, so create a new connection manager by selecting New Flat File Connection… and name it CM_FF_DST_Log.

Add new Flat File Connection Manager for SSIS Logging

It’s not too important what you want to name the file, because we want to use a dynamic file name based on the date that we’ve already setup with gv_LogFile global variable. Once, it’s setup you can do a right-click on the CM_FF_DST_Log and check on the Properties.

Expand the Expressions and click on the ellipsis in ConnectionString, an Expression Builder window will be opened.

Expand the Variables and Parameters and double-click on the Log::gv_LogFile so it will go to the Expression: box and click OK.

SSIS Connection Manager Properties Expression Builder

Now, when you double-click on the CM_FF_DST_Log connection manager, the log filename will be dynamically populated according to today’s date (see File: below). You can close the window by clicking OK or Cancel as we do not need to modify this setup further.

SSIS File Connection Manager Editor Create File for Logging

Enable SSIS Logging

We finished the connection manager for the log file, but we still need to enable SSIS Logging and associate that with the log connection manager. In order to do this, go to the top menu and click on SSIS and select Logging… as shown below.

SSIS Logging menu

You will next see a new Configure SSIS Logs window. Make sure all checkboxes under the Containers are checked. We also need to make sure that on the right pane of that window, under Details we check at least OnError, OnTaskFailed, and OnWarning.

Important: Make sure this step is done for each container listed on the left side (yes, it’s tedious, but fortunately you only need to set this up once per project).

SSIS Configure SSIS Logs Details

Go to the Providers and Logs, now we want to setup the log provider to use the flat file connection manager CM_FF_DST_Log. If you setup the connection manager correctly, CM_FF_DST_Log should be available on the Configuration drop-down list. This part also needs to be done for each container.

SSIS configure logs with Flat File Connection Managers as the provider

Once this setup is complete, we’re ready to add our log in SSIS workflow.

Write the Log

Try to put the tasks within containers for each task you want to add log to.

SSIS Package Database Load

If you double-click on the SCR Log Start and click on the Edit Script…, here’s the C# script contained in the task:

SCR Log Start

public void Main()
{
  Dts.Log("Package starting...", 99, null);

  foreach(Variable v in Dts.Variables)
  {
    Dts.Log("Name: " + v.Name, 99, null);
    Dts.Log("Value: " + v.Value.ToString(), 99, null);
  }
 
  Dts.TaskResult = (int)ScriptResults.Success;
}

Data Flow Counters

Under the Data Flow tab, you can see that from each data source, there’s a Row Count component that is attached to it. In this process, the values from the Row Count component will be passed on to the global variables we setup. In this example, they are gvCNT_LDAPRowCount and gvCNT_LDAPRowCountBlanks.

SSIS Row Count Component to Global Variable

And we include a detailed count of each count and grand total in a Script Task called SCR LDAP Row Counts. Just make sure we also include the global variables in the ReadOnlyVariables like so, then click on the Edit Script….

SSIS Assign to Global Variables with Script Task

Add the calculation logic and write to the log.

public void Main()
{
  // Get LDAP row count with sAMAccountName row counts
  int rowLDAPCount = (int)Dts.Variables["CNT::gvCNT_LDAPRowCount"].Value;
 
  // Get LDAP row count that are blank
  int rowLDAPBlanks = (int)Dts.Variables["CNT::gvCNT_LDAPRowCountBlanks"].Value;
 
  // Total rows
  int rowTotalLDAPCount = 0;
  rowTotalLDAPCount = rowLDAPCount + rowLDAPBlanks;
 
  // Log if LDAP has no records.
  if (rowTotalLDAPCount > 0)
  {
    Dts.Log(String.Format(" Total records with NT ID accounts: {0}", rowLDAPCount.ToString("###,###,###")), 99, null);
    Dts.Log(String.Format(" Total records without NT ID accounts: {0}", rowLDAPBlanks.ToString("###,###,###")), 99, null);
    Dts.Log(String.Format(" Total records from LDAP source: {0}", rowTotalLDAPCount.ToString("###,###,###")), 99, null);
  } else
  {
    Dts.Log(String.Format(" No record is found in LDAP source. {0}", rowTotalLDAPCount.ToString("###,###,###")), 99, null);
  }
  
  Dts.TaskResult = (int)ScriptResults.Success;
}

At the end of the process flow, just add another script SCR Log Finish to indicate the end of the logging session after the package run.

SCR Log Finish

public void Main()
{
  Dts.Log("~ Log Cleanup Package completed. ~", 99, null);
 
  Dts.TaskResult = (int)ScriptResults.Success;
}

So what does the log file look like? Here’s an example what’s reported. It’s probably easier to read if you look at the raw file instead.

#Fields: event,computer,operator,source,sourceid,executionid,starttime,endtime,datacode,databytes,message
PackageStart,ITNOTA-SERVER,ITNOTA\UserId,SSIS-ITNota,{GUID1},{MACHINEGUID},3/5/2019 3:40:08 AM,3/5/2019 3:40:08 AM,0,0x,Beginning of package execution.

User:ScriptTaskLogEntry,ITNOTA-SERVER,ITNOTA\UserId,SCR_LogStart,{GUID2},{MACHINEGUID},3/5/2019 3:40:08 AM,3/5/2019 3:40:08 AM,99,(null),Package starting...
User:ScriptTaskLogEntry,ITNOTA-SERVER,ITNOTA\UserId,SCR LDAP Row Counts,{GUID3},{MACHINEGUID},3/5/2019 3:41:07 AM,3/5/2019 3:41:07 AM,99,(null), Total records with NT ID accounts: 11,236
User:ScriptTaskLogEntry,ITNOTA-SERVER,ITNOTA\UserId,SCR LDAP Row Counts,{GUID3},{MACHINEGUID},3/5/2019 3:41:07 AM,3/5/2019 3:41:07 AM,99,(null), Total records without NT ID accounts: 10,009
User:ScriptTaskLogEntry,ITNOTA-SERVER,ITNOTA\UserId,SCR LDAP Row Counts,{GUID3},{MACHINEGUID},3/5/2019 3:41:07 AM,3/5/2019 3:41:07 AM,99,(null), Total records from LDAP source: 21,245
User:ScriptTaskLogEntry,ITNOTA-SERVER,ITNOTA\UserId,SCR Log Finish,{GUID4},{MACHINEGUID},3/5/2019 3:41:07 AM,3/5/2019 3:41:07 AM,99,(null),~ Log Cleanup Package completed. ~
PackageEnd,ITNOTA-SERVER,ITNOTA\UserId,SSIS-ITNota,{GUID1},{MACHINEGUID},3/5/2019 3:41:07 AM,3/5/2019 3:41:07 AM,0,0x,End of package execution.

That’s all there is to it to add a custom logging to SSIS package.

This may look like a lot of work initially, but as your SSIS package grows in complexity it will save you so much time in diagnosis and troubleshooting that you will thank yourself later.

Hope it helps.

Further Reading

SSIS Best Practice with Naming Conventions
How to Create SSIS Package in Visual Studio 2017
How to Build SSIS Package for Different SQL Server Version with Visual Studio 2017 and SSDT

March 7, 2019 Filed Under: How To Tagged With: ETL, Microsoft, SSIS

How to Backup IIS Manager Connections List on Windows

You’ve been using IIS Manager to manage remote IIS from your local computer. But how do you export the connections list if you move to a new computer or just to back it up if you lost all data?

IIS Manager Connect Remote Server

This post will show you how you can export and back up IIS Manager connections list on your local PC.

All connections in IIS Manager are saved in a binary file called InetMgr.preferences and it can be found in the following folder:

%APPDATA%\Microsoft\WebManagement\7.0.0.0

Or

C:\Users\{NTID}\AppData\Roaming\Microsoft\WebManagement\7.0.0.0

*Replace the {NTID} with the user id you use to logon to your computer.

IIS Manager preferences file

This is the file you want to backup so copy this file to your backup folder. When you need to restore it, just copy this file back to the above folder and you should be back in business.

Important: Do not try to restore the file when IIS Manager is open. When you quit the application, it will write the last settings on that InetMgr.preferences file.

Further Reading

How to Manage IIS Servers Remotely

March 6, 2019 Filed Under: How To Tagged With: IIS, Internet Information Services, Microsoft, Windows, Windows 10

« Previous Page
Next Page »
Buy me a coffee Support this site
Buy Me a Coffee?

Categories

  • .NET
  • Coding
  • Cybersecurity
  • Database
  • How To
  • Internet
  • Multimedia
  • Photography
  • Programming
  • Resources
  • Review
  • Tips and Tricks
  • Uncategorized
  • Use Case
  • WordPress
  • Writing

Recent Posts

  • How to View Stored Procedure Code in SQL Server
  • How to Find a String in SQL Server Stored Procedures
  • How to Remove Cached Credentials without Rebooting Windows
  • ESP Work Automation: Empowering Enterprises with Streamlined Workflows and Operational Efficiency
  • How to Search for a String in All Tables in a Database

Recent Posts

  • How to View Stored Procedure Code in SQL Server
  • How to Find a String in SQL Server Stored Procedures
  • How to Remove Cached Credentials without Rebooting Windows
  • ESP Work Automation: Empowering Enterprises with Streamlined Workflows and Operational Efficiency
  • How to Search for a String in All Tables in a Database

Tags

.NET .NET Core AdSense ASP.NET Cdonts Dll Classic ASP Code Editor ETL FSharp Genesis Framework Git Google HP Asset Manager HTML5 Hugo IIS Information Security Internet Internet Information Services iOS JAMStack Linux macOS Microsoft Microsoft SQL Server MVC PHP PowerShell Python Simple Mail Transfer Protocol Smtp Server SQL SQL Server SSIS SSMS SSRS Sublime Text Visual Studio Visual Studio Code VPN Windows Windows 8 Windows 10 Windows 2012 Windows Server

Copyright © 2011-2025 IT Nota. All rights reserved. Terms of Use | Privacy Policy | Disclosure