Tag Archives: Controller

Fixing CSRF Vulnerability

One way that your web-site might be vulnerable to an attack is via Cross Site Request Forgery (CSRF or XSRF).

If you’ve ever been logged into a web-site – say Twitter for example – and you open a separate tab, then type in a twitter account, for example: https://www.twitter.com/paul_michaels, you’ll notice that when the site opens, it opens already logged in for you – which is very helpful. Imagine having to re-log-in every single time you wanted to view a tweet or a profile.

Okay, now imagine that, instead of typing that into the browser, you click the link above – try it! What – it didn’t take you to Twitter, but it took you to the home page of this blog? In fact, that’s exactly how a CSRF attack would work in practice. If you were already logged into that site, the link could have executed a CSRF attack.

Cross Site Request Forgery works on the premise that the victim of the attack is actually logged into a given website with valid credentials, and the attacker knows the exact format of a valid request. So, for example, I can take you to my Twitter profile, because the format of that is well known. Nobody, least of all Twitter themselves, want you to have to mess around logging in again.

But what about if you want to actually post a Tweet? Here’s the Url that gets called:

It’s a little difficult to demonstrate, because Twitter operates over HTTPS, so the traffic is encrypted, but the gist is that, even if I managed to create a site that copied this message exactly, the Tweet would not get created. Let’s have a look at replicating such an attack.

To Reproduce

Your first step is to create a really bog standard web site – the default MVC template will do. It might also help to demonstrate if you don’t use HTTPS.

Launch the web-site with F12 tools and make a given request. For example, click the “Contact” link on the default site. Make a note of the URL and the form data for the request:

Leave the app running and logged in.

Now Attack

Create a new web app with the following code:

<h1>Run CSRF Attack on MyApp</h1>
<form action="https://localhost:12312/SendLoadsOfMoney" method="post">
    <input type="hidden" name="values" 
           value="{'BankName': 'Big Bank', 'Amount': '1234.12' }">
    <input type="submit" value="Attack Now!">
</form>

Obviously, don’t use that code – otherwise you’ll cause over a thousand pounds to be transferred from my account to yours! Replace the URL with whatever the URL from the above site was, and the values with whatever values were behind your grey box above. You can use POST or GET or whatever else you like. What you’ll notice is that clicking your button interacts with the site you created in the same way as it would if you were on your site. The “SendLoadsOfMoney” is obviously an example that takes it to the extremes, but the principle is correct.

Fix

To fix this in MVC is very easy.

Add:

[ValidateAntiForgeryToken]

If you add this to the controller method, you should start seeing this error:

The required anti-forgery cookie “__RequestVerificationToken” is not present.

Your calling code might look like this:

<form action="Test" method="post">
    <input type="submit" value="Test3">
</form>

The next step is to add a call into the client; for example:

<form action="Test" method="post">
    @Html.AntiForgeryToken()
    <input type="submit" value="Test3">
</form>

So far, so good. This works for Asp.Net Mvc Core and Framework, but not for ApiControllers! The decorator [ValidateAntiForgeryToken] has no effect on an ApiController out of the box (and worse, you’ll never know it without launching a specific attack on your ApiController). So what can you do?

One option is to implement a custom token as described here. I would treat this as a specific case for ApiControllers only, though.

References

https://github.com/zaproxy/zaproxy/wiki/Downloads

https://www.owasp.org/index.php/OWASP_Testing_Project

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-2.1

https://www.devexpress.com/Support/Center/Question/Details/KA18920/how-to-use-antiforgerytoken-during-devexpress-callbacks

Asp.Net Core 2.0 – Passing data into a Model Using DI

Imagine you have an Asp.Net Core web page, and you would like to edit some data in a form, but you’d like to default that data to something (maybe initially specified in the Web.Config).

I’m sure there’s dozens of ways to achieve this; but this is one.

Let’s start with a bog standard MVC web app:

Step one is to define a model in which to hold your data; here’s mine:

public class CurrentAppData
{
    public string DataField1 { get; set; }
}

Let’s register that in the IoC container:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
 
 
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
 
    services.AddTransient<CurrentAppData, CurrentAppData>(
        a => new CurrentAppData()
        {
            DataField1 = "test value"
        });

Next thing we’ll need is a View, and a corresponding view model to edit our data; here’s the view:

@model EditDataViewModel
@{
    ViewData["Title"] = "Edit Data";
}
 
<h2>@ViewData["Title"]</h2>
 
<div>
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
 
</div>

And now the view model (that is, the model that is bound to the view):

public class EditDataViewModel
{
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The final step here is to adapt the controller so that the CurrentAppData object is passed through the controller:

public class EditDataController : Controller
{
    private readonly CurrentAppData _currentAppData;
 
    public EditDataController(CurrentAppData currentAppData)
    {
        _currentAppData = currentAppData;
    }
 
    public IActionResult EditData()
    {
        return View(new EditDataViewModel(_currentAppData));
 
 
    }
}

That works as far as it goes, and we now have the data displayed on the screen:

The next step is to post the edited data back to the controller; let’s change the HTML slightly:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
</form>

We’ve added a submit button, which should cause the surrounding form element to execute whichever “method” it’s been told to (in this case, POST). It will look for an action on the controller called UpdateData, so we should create one:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    System.Diagnostics.Debug.WriteLine(editDataViewModel.EditData.DataField1);
    return View("EditData", editDataViewModel);
}

Here, we’re accepting the EditDataViewModel from the view. However; when we run this, we get the following error:

Error:

InvalidOperationException: Could not create an instance of type ‘WebApplication14.Models.EditDataViewModel’. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the ‘editDataViewModel’ parameter a non-null default value.

Let’s first implement a fix for this, and then go into the whys and wherefores. The fix is actually quite straightforward; simply give the view model a parameterless constructor:

public class EditDataViewModel
{
    public EditDataViewModel()
    {
        
    }
 
    public EditDataViewModel(CurrentAppData editData)
    {
        EditData = editData;
    }
    public CurrentAppData EditData { get; set; }
}

The problem that we had here is that the `EditDataViewModel` that is returned to UpdateData is a new instance of the model. We can prove this by changing our code slightly:

Here, we’ve added a field called TestField1 to the model, and populated it just before we pass the model to the view; and on the post back, it’s gone. I’m not completely sure why the view model can’t be created by the middleware in the same way that the controller is; but that’s the subject of another post.

Finally, show the value back to the screen

To wrap up, we’ll just show the same value back to the screen; we’ll add an extra value to the model:

public class CurrentAppData
{
    public string DataField1 { get; set; }
 
    public string DisplayField1 { get; set; }
}

And we’ll just display it in the view:

<form asp-action="UpdateData" asp-controller="EditData" method="post" enctype="multipart/form-data">
    <label>Change data here:</label>
    <input type="text" asp-for="EditData.DataField1" />
    <br />
    <button type="submit" class="btn-default">Submit Changes</button>
    <br />
    <label>@Model.EditData.DisplayField1</label>
    <br />
</form>

Finally, we’ll copy that value inside the controller (obviously, this is simulating something meaningful happening), and then display the result:

public IActionResult UpdateData(EditDataViewModel editDataViewModel)
{
    editDataViewModel.EditData.DisplayField1 = editDataViewModel.EditData.DataField1;
    return View("EditData", editDataViewModel);
}

Let’s see what that looks like:

Web API Routing – The Basics

Working with API projects, it’s easy to miss some key rules about the routing. This post is basically the result of some that I missed, and subsequent the investigation. It covers some very basic routing rules, and it certainly not intended to be an exhaustive guide.

.Net Framework

Starting with a .Net Framework Web API, let’s create a new web app:

And add a new controller:

Here’s the code for the controller; as you will see, it’s massively complex, but the good news is that you only need to pay attention to the name of the action, and the code inside it:

public class TestController : ApiController
{
    [HttpGet]
    public IHttpActionResult TestAction()
    {
        return Ok("TestAction Performed");
    }
}

Let’s run the project and navigate to the URL:

How did I know that was the URL? It’s magic, and you can buy some of that magic by sending a cheque for the low, low price of $25 to the address shown at the bottom of the screen.

Actually, it’s defined in WebApiConfig.cs:

Parameters

Where there is more than a single function, one surprising (to me) feature is that the parameters that it accepts is more important to the routing than the name of the controller. Here’s a second action with a parameter:

[HttpGet]
public IHttpActionResult TestAction2(string test)
{
    return Ok("TestAction2 Performed");
}

… and here’s it working:

However, should I not give it the parameter that it craves, it hides away, and instead, we get the first function that’s no too fussy about parameters:

It doesn’t even matter whether I just put some drivel as the controller name; the first criteria is the parameter:

This is because, according to this it follows these criteria:

The default implementation is provided by the ApiControllerActionSelector class. To select an action, it looks at the following:
• The HTTP method of the request.
• The “{action}” placeholder in the route template, if present.
• The parameters of the actions on the controller.

So, if we add the {action} placeholder, that ensures that it uses the correct method:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services
 
    // Web API routes
    config.MapHttpAttributeRoutes();
 
    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        //routeTemplate: "api/{controller}/{id}",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Otherwise, we get a best guess based on the parameters.

.Net Core Web API

The rules have changed since switching to .Net Core; WebApiConfig has gone and, in its place, it a localised routing system.

Here, you tell the class how to handle routing; for example, the following:

[Route("api/[controller]")]

Will result anything decorated with HttpGet being called when the controller is called. The parameters must be explicitly decorated; so passing no parameters would look like this:

[HttpGet]
public string OneTest()
{
    return "TestOne";
}

Whereas, a single parameter would look like this:

[HttpGet("{id}")]
public string aaa(int id)
{
    return "value aaa";
}

If you duplicate the signatures then they are not found. As with the framework version, you can simply tell it to look to the action name that you give it:

[Route("api/[controller]/[action]")]
public class TestController : Controller
{
    [HttpGet]
    public IEnumerable<string> TestActionOne()
    {
        return new string[] { "one value1", "value2" };
    }
 
    [HttpGet]
    public string TestActionTwo()
    {
        return "two value";
    }

But, again, it pays no attention to parameters until you decorate it correctly.

References

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing

Mocking IPrinciple.Identity and Claims in NSubstitute

In ASP.Net, there is a concept of an identity. Built on top of this is an authentication system based on claims; allowing applications to implement a claims based authentication system. That is, I can determine if my user has “Administrator” privileges in the following syntax:

var claim = ClaimsIdentity.FindFirstValue("Administrator");

For more information about how claims work, see this excellent explanation. This post is not really concerned with how claims work, but rather, how to mock them out; which is much more difficult than you might guess.

In the references below, you’ll see a number of different strategies to mock out the claims and principle objects. There also seems to be a loose consensus that even attempting to do this is folly. However, I’ve cobbled together a set of mocks using NSubstitute that work. I’m not claiming that they work in all cases, or that they will work in any situation other than the specific one that I am trying to solve; but it did work for that, and so I thought it useful enough to share.

var myController = new MyController();
 
var mockClaim = new Claim("Administrator", "test");
 
var identity = Substitute.For<ClaimsIdentity>();
identity.Name.Returns("test");
identity.IsAuthenticated.Returns(true);
identity.FindFirst(Arg.Any<string>()).Returns(mockClaim);
 
var claimsPrincipal = Substitute.For<ClaimsPrincipal>();
claimsPrincipal.HasClaim(Arg.Any<string>(), Arg.Any<string>()).Returns(true);
claimsPrincipal.HasClaim(Arg.Any<Predicate<Claim>>()).Returns(true);
claimsPrincipal.Identity.Returns(identity);
 
var httpContext = Substitute.For<HttpContextBase>();            
httpContext.User.Returns(claimsPrincipal);
 
var controllerContext = new ControllerContext(
    httpContext, new System.Web.Routing.RouteData(), myController);           
 
myController.ControllerContext = controllerContext;
 
// Act
var result = myController.TestMethod();
 
// Assert
// . . .

Remember that this is only necessary if you are trying to access claims based on the identity within the `TestMethod()`. Also, I’ll remind the reader that I assert only that this worked in the specific situation that I needed it to, but it’s probably a good starting point for others.

References

https://volaresystems.com/blog/post/2010/08/19/Dont-mock-HttpContext

http://nsubstitute.github.io/help/set-return-value/

https://stackoverflow.com/questions/1389744/testing-controller-action-that-uses-user-identity-name

https://stackoverflow.com/questions/13579519/mock-authenticated-user-using-moq-in-unit-testing

https://stackoverflow.com/questions/14190066/is-there-any-way-i-can-mock-a-claims-principal-in-my-asp-net-mvc-web-application

https://stackoverflow.com/questions/22762338/how-do-i-mock-user-identity-getuserid/23960592

https://dotnetcodr.com/2013/02/11/introduction-to-claims-based-security-in-net4-5-with-c-part-1/