Category Archives : Security

A general category for security and information system securiity


Identity Server – An Introduction

Introduction

In recent times, I’ve become very intimately acquainted with OpenID Connect, OAuth2 as well as SAML, JWT, WS-Federation and more.  It’s a complicated world.

Since I dwell amongst the Microsoft ecosystem, I’m very experienced with Active Directory Federation Services (AD FS) which in its latest version supports OAuth2 endpoints as well as the more traditional (and dated) SAML 2.0 and WS-Federation protocols.

AD FS 3.0’s OAuth2 implementation is fairly limited, to be polite.  As modern applications such as Single Page Applications (SPA), WebAPI services and mobile applications advance, security capabilities must scale accordingly.  To augment AD FS there are two additional options – .NET DotNetOpenAuth and Thinktecture IdentityServer of which the current version is Identity Server 3.

Identity Server 3 (ID3) is the platform we’ve selected recently to help expand ADFS authentication capabilities, and the basis for this article.  ID3 already has very decent documentation, but I’ll need to borrow some of it to help frame the introduction in this article.

The following diagram neatly illustrates the role that ID3 plays between users, clients and applications/resources:

OpenID Connect
Source: http://identityserver.github.io/Documentation/docs/overview/terminology.html

The next few headings help to define the roles involved in applying security principles using ID3 and identity providers.  I’ve referenced a limited scope here as in my next article I’m going to paint a scenario and document an interesting solution I designed recently to solve a tricky problem involving ID3 and scope access.

The text below in italics comes direct from the Identity Server documentation.

Identity Server Concepts

OpenID Connect Provider (OP)

IdentityServer is an OpenID Connect provider – it implements the OpenID Connect protocol (and OAuth2 as well).  Different literature uses different terms for the same role – you probably also find security token service, identity provider, authorization server, IP-STS and more.

But they are in a nutshell all the same: a piece of software that issues security tokens to clients.IdentityServer has a number of jobs and features – including:

- authenticate users using a local account store or via an external identity provider
-
provide session management and single sign-on
-
manage and authenticate clients
-
issue identity and access tokens to clients
-
validate tokens

User

A user is a human that is using a registered client to access his or her data

Client

A client is a piece of software that requests tokens from IdentityServer – either for authenticating a user or for accessing a resource (also often called a relying party or RP). A client must be registered with the OP.Examples for clients are web applications, native mobile or desktop applications, SPAs, server processes etc.

Scope

Scopes are identifiers for resources that a client wants to access. This identifier is sent to the OP during an authentication or token request.

Resource scopes

Resource scopes identify web APIs (also called resource servers) – you could have e.g. a scope named calendar that represents your calendar API.

Access Token

An access token can be validated by a resource.  Clients request access tokens and forward them to an API. Access tokens contain information about the client and the user (if present). APIs use that information to authorize access to their data.

OAuth Concepts

Right, now that we’ve got that cleared up we can take a quick browse through some OAuth2 concepts..  First off here’s a link to the OAuth2 Specification in case you want to read the whole enchilada.  The text below in italics is directly from the OAuth2 specification itself.

What I’m going to be focusing on are Authorization Grants.  First, let’s take a look at how this is all intended to flow:

image
Figure 1 (my edition)

The abstract OAuth 2.0 flow illustrated in Figure 1 describes the interaction between the four roles and includes the following steps:

(A)  The client requests authorization from the resource owner.  The authorization request can be made directly to the resource owner (as shown), or preferably indirectly via the authorization server as an intermediary.

(B)  The client receives an authorization grant, which is a credential representing the resource owner’s authorization, expressed using one of four grant types defined in this specification or using an extension grant type.  The authorization grant type depends on the method used by the client to request authorization and the types supported by the authorization server.

(C)  The client requests an access token by authenticating with the authorization server and presenting the authorization grant.

(D)  The authorization server authenticates the client and validates the authorization grant, and if valid, issues an access token.

1.3.  Authorization Grant

An authorization grant is a credential representing the resource owner’s authorization (to access its protected resources) used by the client to obtain an access token.  This specification defines four grant types –
- authorization code,
- implicit,
- resource owner password credentials, and,
- client credentials
as well as an extensibility mechanism for defining additional types.

1.3.1.  Authorization Code

The authorization code is obtained by using an authorization server as an intermediary between the client and resource owner.  Instead of requesting authorization directly from the resource owner, the client directs the resource owner to an authorization server (via its user-agent as defined in [RFC2616]), which in turn directs the resource owner back to the client with the authorization code.

Before directing the resource owner back to the client with the authorization code, the authorization server authenticates the resource owner and obtains authorization.  Because the resource owner only authenticates with the authorization server, the resource owner’s credentials are never shared with the client.

The authorization code provides a few important security benefits, such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner’s user-agent and potentially exposing it to others, including the resource owner.

1.3.2.  Implicit

The implicit grant is a simplified authorization code flow optimized for clients implemented in a browser using a scripting language such as JavaScript.  In the implicit flow, instead of issuing the client an authorization code, the client is issued an access token directly (as the result of the resource owner authorization).  The grant type is implicit, as no intermediate credentials (such as an authorization code) are issued (and later used to obtain an access token).

When issuing an access token during the implicit grant flow, the authorization server does not authenticate the client.  In some cases, the client identity can be verified via the redirection URI used to deliver the access token to the client.  The access token may be exposed to the resource owner or other applications with access to the resource owner’s user-agent.

Implicit grants improve the responsiveness and efficiency of some clients (such as a client implemented as an in-browser application), since it reduces the number of round trips required to obtain an access token.  However, this convenience should be weighed against the security implications of using implicit grants, such as those described in Sections 10.3 and 10.16, especially when the authorization code grant type is available.

1.3.3.  Resource Owner Password Credentials

The resource owner password credentials (i.e., username and password) can be used directly as an authorization grant to obtain an access token.  The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g., the client is part of the device operating system or a highly privileged application), and when other authorization grant types are not available (such as an authorization code).

Even though this grant type requires direct client access to the resource owner credentials, the resource owner credentials are used for a single request and are exchanged for an access token.  This grant type can eliminate the need for the client to store the resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.

1.3.4.  Client Credentials

The client credentials (or other forms of client authentication) can be used as an authorization grant when the authorization scope is limited to the protected resources under the control of the client, or to protected resources previously arranged with the authorization server.  Client credentials are used as an authorization grant typically when the client is acting on its own behalf (the client is also the resource owner) or is requesting access to protected resources based on an authorization previously arranged with the authorization server.

Summary

Hopefully what I’ve presented here makes sense.  I realise that most of the text is a boilerplate lift directly from source, but it’s important to understand the key concepts and terminology before we get stuck into working with identity providers, scopes and clients.

The next article will build upon the info introduced in this article – and hopefully will provide food for thought as you navigate the tricky waters of identity management and security concepts.


Programmatically Reading Event Logs

Welcome, 2015 – may you be an improvement on your predecessor.

Today’s article focuses on the deceptively non-trivial task of reading from the Windows Event Logs using the Microsoft .NET Framework.  For those who haven’t looked there in a while, here’s a quick look at the Event Viewer:

image
The Windows Event Viewer

Now there are the usual suspects like the Application, Security and System logs of course, but on more recent editions of Windows, you might make note of the category beneath the standard “Windows Logs”, namely “Applications and Services Logs”.  We can read from those as well as the standard logs.

image

Windows Event Log Tree

My Scenario – Viewing Log File Content

At the moment, we don’t have a logging approach which consolidates system logs and rolling log files into a single location.  While we are waiting for that capability, I decided to quickly roll an ASP.NET MVC site which would effectively publish the content of local log files for remote users to view without the hassle of having to log on or RDP to the machine.

The “Log View” web application needed to do the following:

  • Through configuration, read log files contained in (one to many) specified local directories
  • Through configuration, read (one or more) log files based on a specific path/filename
  • Read the Security, System and Application system logs, displaying the most recent 100 entries
  • Through configuration, read the AD FS admin log when installed on an AD FS server
  • Allow anonymous authentication

This web application is meant for development/test environments, hence the anonymous authentication requirement.

index
Index page

Different Approaches – Reading Logs

The standard Windows Logs – a well beaten path – have special support in the .NET Framework.  Provided you have the appropriate permissions, reading log entries is relatively straightforward:

var eventLogItem = System.Diagnostics.EventLog(“Application”);
var numberOfItems = eventLogItem.Entries.Count;

Of course, reading from the log is just as simple:

foreach (EventLogEntry entry in eventLogItem.Entries)
{
    // read the individual event
}

read-system
Reading the system log

You don’t (seem) to require any special permissions as a local user to read from the Application and System logs, a standard user account seems to have read permissions by default – even on Windows Server 2012 R2.  This does not apply to the Security log, which would seem to require special permissions or policy – see more on this below.

However, things change when you want to read from a non-standard system log.  In my case, I wished to read from the AD FS/Admin log on a Windows Server 2012 R2 machine which had the Active Directory Federation Services (AD FS 3.0) role installed.

Reading Non-system Logs

Once we veer away from the standard ‘System’ and ‘Application’ logs, the implementation gets a tad trickier – and more brittle in terms of functionality.  You have to abandon the friendly EventLog class and instead have to use the EventLogQuery class, as below:

string LogName = “AD FS/Admin”;
var query = new EventLogQuery(LogName, PathType.LogName, “*[System/Level=2]”);
query.ReverseDirection = true;

Note that “log name” seems to need to match the “path” of the log if it resides under subfolders in the “Applications and Services Logs” section.  Note that I’ve used the “ReverseDirection” property to show the most recent log files first.  To actually read entries from the log, you invoke the tastefully named EventLogReader class, like so:

using (var reader = new EventLogReader(query))
{
    // implementation here
}

You might be wondering how one would consume the EventLogReader?  Happily, I can provide you with the implementation I’ve put together for my AD FS log reader:

var sb = new StringBuilder();
for (EventRecord eventInstance = logReader.ReadEvent();
       null != eventInstance; eventInstance = logReader.ReadEvent())
{
     sb.AppendLine(“<hr/>”);
     sb.AppendFormat(“Event ID: {0}<br/>”, eventInstance.Id);
     sb.AppendFormat(“Publisher: {0}<br/>”, eventInstance.ProviderName);
     sb.AppendFormat(“Time Created: {0}<br/>”, eventInstance.TimeCreated.Value);

     try
     {
        sb.AppendFormat(“Description: {0}<br/>”,  eventInstance.FormatDescription());
     }
     catch (EventLogException e)
     {
         // The event description contains parameters, and no parameters were
         // passed to the FormatDescription method, so an exception is thrown.
         sb.AppendFormat(“EventLogException: {0}”, e.Message);
     }
}

There are obviously more properties available, don’t limit yourself to what I’ve included above.  Also note that it’s possible to have an exception thrown when invoking the FormatDescription() function – it’s worth catching unless you want your logic to die when it can be reasonably anticipated.

Errors at Runtime

The first few times i deployed and ran my web application, I encountered some nasty exceptions being thrown.  I was running with the default ApplicationPool identity, which I decided I needed to replace with a dedicated local user.  I created a local user called ‘svc_adfs_logs’ and made it a member of the local IIS_IUSRS group as well as making it the identity of my web application’s application pool.

adfs-error-release

adfs-error-debug

The errors occurred when accessing the Security and the AD FS logs.  I had to dig deeper.

Permissions and Settings

This is where things get interesting – aside from the standard System and Application logs, pretty much every other log I tried to read from, I’d encounter a permissions – or registry – issue.

File Permissions (ACLS)

One place to check are file permissions themselves.  The logs are files residing under the Windows directory (by default) which is usually this path: C:\Windows\System32\winevt\Logs

If you’re unsure,in Event Viewer, just right click on the log name and select properties:

image
Log Properties in Event Viewer

In my case, I assigned basic read access to the app pool identity of my web application:

acls
Assigning read access to the web application identity

Group Membership

The next obvious step is to ensure that your process’s identity (the account which the application is running under) is a member of a local, built-in security group called (aptly) ‘Event Log Readers’.  You administer this membership via the local Groups in Computer Management:

user-properties
Ensure your application’s identity/account is a member of the ‘Event Log Readers’ group

Which should resolve the following exception (if you encounter it):

Attempted to perform an unauthorized operation.

at System.Diagnostics.Eventing.Reader.EventLogException.Throw(Int32 errorCode) at System.Diagnostics.Eventing.Reader.NativeWrapper.EvtQuery(EventLogHandle session, String path, String query, Int32 flags) at System.Diagnostics.Eventing.Reader.EventLogReader..ctor(EventLogQuery eventQuery, EventBookmark bookmark) at LogView.Controllers.LogsController.ReadNonSystemLog(LogModel item)

Summary

Well, aside from writing some pretty simple boiler plate code, it was really quite easy to put together a well articulated log file viewing web application.  I may consider publishing the source for this web application at a later time, once I’ve cleaned up the implementation a little bit (it’s a bit messy).

You should never be assigning local Administration rights when reading or writing to system logs – it’s worth the time investigating permissions and policies before going to those kinds of extremes.

There was one last avenue which I was exploring which involved setting SDDLs in the registry, but it turns out this was not necessary.  I’ve included the links though in case you’d like to find out more.

Further Reading/References

Basic “how to” query event messages – http://msdn.microsoft.com/en-us/library/bb671200(v=vs.110).aspx
Permissions to read event logs – http://geekswithblogs.net/TimH/archive/2005/10/05/56029.aspx 
How to set event log security – http://support.microsoft.com/kb/323076

Which leads us to….

Introduction to SDDL – http://msdn.microsoft.com/en-us/library/aa379570.aspx
The file ACL trick to get an SDDL: http://stackoverflow.com/questions/9907510/is-there-a-tool-to-generate-sddl-security-descriptor-definition-language-strin


Getting to know Cross-Origin Resource Sharing (CORS)

Hello there.  I’ve been spending a lot of time of late trying to develop a solution to a very obscure problem scenario.  The entire problem itself is outside the scope of this article – and to be honest, probably wouldn’t be terribly relevant to many – however, I felt there was value in articulating my recent experiences with Cross-Origin Resource Sharing, or CORS for short.

So what is CORS? 

 

To quote from Wikipedia:

Cross-origin resource sharing (CORS) is a mechanism that allows many resources (e.g., fonts, JavaScript, etc.) on a web page to be requested from another domain outside the domain from which the resource originated.[1] In particular, JavaScript’s AJAX calls can use the XMLHttpRequest mechanism.

Such “cross-domain” requests would otherwise be forbidden by web browsers, per the same-origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request.[2] It is more useful than only allowing same-origin requests, but it is more secure than simply allowing all such cross-origin requests.”

Now that we’ve cleared that up…  my take – a web site makes use of resources which are hosted on another site outside of its domain.  This is an important distinction owing primarily due to cross-site scripting (XSS) and cross-site request forgery (CSRF) vulnerabilities.

 

What does something like CORS address exactly?

Well, the concept is fairly straightforward.  What CORS aims to do is have two websites (sites, pages, APIs etc.) agree on what kind of resources and types of requests one website will provide to another.  Both must agree exactly on what is being shared and how.

 

How is this accomplished?

There’s a few parties who need to participate to enable CORS – the two parties involved, of course, and the user’s browser.  Both sites need to request and respond to each other in an expected manner, and browsers need to be aware of, and in some cases make special requests to ensure CORS works correctly.

In essence, what happens is that both websites agree on how resources will be shared.  The requesting site must be known as an “allowed origin” by the site providing the resources.  The response also must contain headers which contain scope for acceptable resource sharing, e.g. naming allowable methods (e.g. GET, PUT) and whether credentials are supported.  Browsers themselves are the last key – they must respect the restrictions established by the requesting site and the resource site.

 

What is a “pre-flight request”?

In some cases, a browser might make a special type of request known as an OPTIONS request, which is sort of like an initial handshake before performing the actual request specified (e.g. a GET request). 

In essence, an OPTIONS request attempts to determine what supported methods and other information is available from a resource sharing server.  In browser terms, this is known as a “pre-flight” request and is often attempted automatically by the browser.

The first time a cross-site request might fail (and in subsequent attempts) the browser’s JavaScript console might log something similar to the following error:

XMLHttpRequest cannot load https://<TARGETSERVER>/p?ReadViewEntries&outputformat=json. The request was redirected to ‘https://<ANOTHERSERVER>’, which is disallowed for cross-origin requests that require preflight.

Here’s an example of a browser (Chrome) attempting an OPTIONS pre-flight request and failing:

failed

Let’s take a look at a pre-flight HTTP(S) request example.

Remote Address:<IPADDRESS>:443

Request Headers URL:https://<TARGETSERVER>/p?ReadViewEntries&outputformat=json

Request Method:OPTIONS

Status Code:200 OK

Request Headers

OPTIONS /p?ReadViewEntries&outputformat=json
HTTP/1.1

Host: <TARGETSERVER>

Connection: keep-alive

Access-Control-Request-Method: GET

Origin: https://<ORIGINSERVER>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36

Access-Control-Request-Headers: accept, content-type

Accept: */*

Referer: https://<ORIGINSERVER>/Home/Test

Accept-Encoding: gzip,deflate,sdch

Accept-Language: en-US,en;q=0.8

Query String Parametersview sourceview URL encoded

ReadViewEntries:

outputformat:json

count:4000

r:0.88333622

charset:utf-8

 

Under normal circumstances, a target server which honours this request would respond with something similar to this:

HTTP/1.1 200 OK

Date: Tue, 11 Nov 2014 03:35:05 GMT

Access-Control-Allow-Origin: https://<ORIGINSERVER>

Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept,Access-Control-Request-Headers,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Credentials

Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT, HEAD

Access-Control-Allow-Credentials: true

Content-Length: 495

Keep-Alive: timeout=10, max=100

Connection: Keep-Alive

Content-Type: text/html; charset=iso-8859-1

 

The most important thing in this response isn’t probably what you’d expect it to be.  It’s actually the HTTP STATUS CODE (i.e. 200).  For CORS pre-flight to work, the resource target must respond with a Status Code of 200 to a HTTP OPTIONS request – and it must do so for unauthenticated requests!

 

Why must the pre-flight/OPTIONS requests be unauthenticated?

It’s actually a requirement direct from the respective W3C specification regarding pre-flight requests:

Otherwise, make a preflight request. Fetch the request URL from origin source origin with the manual redirect flag and the block cookies flag set, using the method OPTIONS, and with the following additional constraints:

[1] https://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#preflight-request

Therefore, a response status code of 302 (Found – Redirect, usually to authenticate) or 401 (unauthorised) will clearly fail pre-flight.  Note that the resource (target) server doesn’t have to honour all OPTIONS requests, you could lock down the server’s security to only respond (Status 200) to requests on certain paths, for example.

In the example screenshot earlier, the pre-flight was failing because the resource server had authentication enabled for the OPTIONS request, and it was redirecting to a security token service (STS) for authentication.

 

Now that that’s all cleared up, how about some sample code? 

Here’s a pretty straightforward request which sets the appropriate header values for cross-domain and with credentials for a GET request, which is expecting a JSON response:

var aQuery = function()

{

     var url = ‘https://<TARGETSERVER>/p?ReadViewEntries&outputformat=json';

    
$.ajax(url, {

            type: “GET”,

            contentType: “application/json; charset=utf-8″,

            success: function(data, status, xhr) {

                alert(data);

            },

            xhrFields: {

                withCredentials: true

            },

            crossDomain: true

        });

}

In many cases though, this is not enough.  Some browsers, particularly older versions for example Internet Explorer 8 and 9 simply don’t support CORS well enough.  A more version sensitive approach might be something like this:

var basicQuery = function ()

{    

      var url = ‘https://<TARGETSERVER>/p?ReadViewEntries&outputformat=json';

      var method = ‘GET';

      var xhr = new XMLHttpRequest();

       

      if (“withCredentials” in xhr) {           

           // Most browsers.       

            xhr.open(method, url, true);

            xhr.setRequestHeader(“Access-Control-Allow-Origin”, “https://<ORIGINSERVER>)”);

            xhr.setRequestHeader(“Access-Control-Allow-Credentials”, “true”);

            xhr.setRequestHeader(“Access-Control-Allow-Methods”, “GET”);

      } else if (typeof XDomainRequest != “undefined”) {

                 // IE8 & IE9      

           xhr = new XDomainRequest();

           xhr.open(method, url);

      } else {

           // CORS not supported.

           xhr = null;

      }

 

      if (xhr != null)

      {                

            xhr.followsRedirect=false;          

            xhr.withCredentials=true;

 

            xhr.onreadystatechange  = function() {

                  if(xhr.readyState==4)

                  {

                        if(xhr.status == 200)

                        {

                              alert(xhr.responseText);                 

                        }

                        else

                        {

                              alert(“error”);

                        }

                  }

            }

            xhr.send();

      }

}

 

Finally, let’s see that gratifying successful CORS request:

success

 

Some notes about setting headers

  • CORS header values in a request must be supported on the resource server for a given request to succeed, i.e. for a request which specifies Access-Control-Allow-Credentials, the target server must respond with Access-Control-Allow-Credentials listed in the Access-Control-Allow-Headers. 
  • The same applies to methods, e.g. a GET method must be listed in the response Access-Control-Allow-Methods
  • When you set the Access-Control-Allow-Origin value, it should be the name of the origin server (the origin of the request) it really shouldn’t be asterisk (*) which is often used in sample code.  The target resource server also must recognise/honour the origin.