XmlSecureResolver: XXE in .Net

August 22, 2022 by · Comments Off on XmlSecureResolver: XXE in .Net
Filed under: Development, Security, Testing 

tl;dr

  • Microsoft .Net 4.5.2 and above protect against XXE by default.
  • It is possible to become vulnerable by explicitly setting a XmlUrlResolver on an XmlDocument.
  • A secure alternative is to use the XmlSecureResolver object which can limit allowed domains.
  • XmlSecureResolver appeared to work correctly in .Net 4.X, but did not appear to work in .Net 6.

I wrote about XXE in .net a few years ago (https://www.jardinesoftware.net/2016/05/26/xxe-and-net/) and I recently starting doing some more research into how it works with the later versions. At the time, the focus was just on versions prior to 4.5.2 and then those after it. At that time there wasn’t a lot after it. Now we have a few versions that have appeared and I started looking at some examples.

I stumbled across the XmlSecureResolver class. It peaked my curiosity, so I started to figure out how it worked. I started with the following code snippet. Note that this was targeting .Net 6.0.

static void Load()
{
    string xml = "<?xml version='1.0' encoding='UTF-8' ?><!DOCTYPE foo [<!ENTITY xxe SYSTEM 'https://labs.developsec.com/test/xxe_test.php'>]><root><doc>&xxe;</doc><foo>Test</foo></root>";

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.XmlResolver = new XmlSecureResolver(new XmlUrlResolver(), "https://www.jardinesoftware.com");
    
    xmlDoc.LoadXml(xml);
    Console.WriteLine(xmlDoc.InnerText);
    Console.ReadLine();
}

So what is the expectation?

  • At the top of the code, we are setting some very simple XML
    • The XML contains an Entity that is attempting to pull data from the labs.developsec.com domain.
    • The xxe_test.php file simply returns “test from the web..”
  • Next, we create an XmlDocument to parse the xml variable.
    • By Default (after .net 4.5.1), the XMLDocument does not parse DTDs (or external entities).
  • To Allow this, we are going to set the XmlResolver. In This case, we are using the XmlSecureResolver assuming it will help limit the entities that are allowed to be parsed.
    • I will set the XmlSecureResolver to a new XmlUrlResolver.
    • I will also set the permission set to limit entities to the jardinesoftware.com domain.
  • Finally, we load the xml and print out the result.

My assumption was that I should get an error because the URL passed into the XmlSecureResolver constructor does not match the URL that is referenced in the xml string’s entity definition.

https://www.jardinesoftware.com != https://labs.developsec.com

Can you guess what result I received?

If you guessed that it worked just fine and the entity was parsed, you guessed correct. But why? The whole point of XMLSecureResolver is to be able to limit this to only entities from the allowed domain.

I went back and forth for a few hours trying different configurations. Accessing different files from different locations. It worked every time. What was going on?

I then decided to switch from my Mac over to my Windows system. I loaded up Visual Studio 2022 and pulled up my old project from the old blog post. The difference? This project was targeting the .Net 4.8 framework. I ran the exact same code in the above snippet and sure enough, I received an error. I did not have permission to access that domain.

Finally, success. But I wasn’t satisfied. Why was it not working on my Mac. So I added the .Net 6 SDK to my Windows system and changed the target. Sure enough, no exception was thrown and everything worked fine. The entity was parsed.

Why is this important?

The risk around parsing XML like this is a vulnerability called XML External Entities (XXE). The short story here is that it allows a malicious user to supply an XML document that references external files and, if parsed, could allow the attacker to read the content of those files. There is more to this vulnerability, but that is the simple overview.

Since .net 4.5.2, the XmlDocument object was protected from this vulnerability by default because it sets the XmlResolver to null. This blocks the parser from parsing any external entities. The concern here is that a user may have decided they needed to allow entities from a specific domain and decided to use the XmlSecureResolver to do it. While that seemed to work in the 4.X versions of .Net, it seems to not work in .Net 6. This can be an issue if you thought you were good and then upgraded and didn’t realize that the functionality changed.

Conclusion

If you are using the XmlSecureResolver within your .Net application, make sure that it is working as you expect. Like many things with Microsoft .Net, everything can change depending on the version you are running. In my test cases, .Net 4.X seemed to work properly with this object. However, .Net 6 didn’t seem to respect the object at all, allowing DTD parsing when it was unexpected.

I did not opt to load every version of .Net to see when this changed. It is just another example where we have to be conscious of the security choices we make. It could very well be this is a bug in the platform or that they are moving away from using this an a way to allow specific domains. In either event, I recommend checking to see if you are using this and verifying if it is working as expected.

XXE DoS and .Net

May 6, 2019 by · Comments Off on XXE DoS and .Net
Filed under: Development, Security 

External XML Entity (XXE) vulnerabilities can be more than just a risk of remote code execution (RCE), information leakage, or server side request forgery (SSRF). A denial of service (DoS) attack is commonly overlooked. However, given a mis-configured XML parser, it may be possible for an attacker to cause a denial of service attack and block your application’s resources. This would limit the ability for a user to access the expected application when needed.

In most cases, the parser can be configured to just ignore any entities, by disabling DTD parsing. As a matter of fact, many of the common parsers do this by default. If the DTD is not processed, then even the denial of service risk should be removed.

For this post, I want to talk about if DTDs are parsed and focus specifically on the denial of service aspect. One of the properties that becomes important when working with .Net and XML is the MaxCharactersFromEntities property.

The purpose of this property is to limit how long the value of an entity can be. This is important because often times in a DoS attempt, the use of expanding entities can cause a very large request with very few actual lines of data. The following is an example of what a DoS attack might look like in an entity.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY dos 'dos' >
<!ENTITY dos1 '&dos;&dos;&dos;&dos;&dos;&dos;&dos;&dos;&dos;&dos;&dos;&dos;' >
<!ENTITY dos2 '&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;&dos1;' >
<!ENTITY dos3 '&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;&dos2;' >
<!ENTITY dos4 '&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;&dos3;' >
<!ENTITY dos5 '&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;&dos4;' >
<!ENTITY dos6 '&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;&dos5;' >]>

Notice in the above example we have multiple entities that each reference the previous one multiple times. This results in a very large string being created when dos6 is actually referenced in the XML code. This would probably not be large enough to actually cause a denial of service, but you can see how quickly this becomes a very large value.

To help protect the XML parser and the application the MaxCharactersFromEntities helps limit how large this expansion can get. Once it reaches the max amount, it will throw a System.XmlXmlException: ‘The input document has exceeded a limit set by MaxCharactersFromEntities’ exception.

The Microsoft documentation (linked above) states that the default value is 0. This means that it is undefined and there is no limit in place. Through my testing, it appears that this is true for ASP.Net Framework versions up to 4.5.1. In 4.5.2 and above, as well as .Net Core, the default value for this property is 10,000,000. This is most likely a small enough value to protect against denial of service with the XmlReader object.

Open Redirect – Bad Implementation

January 14, 2016 by · 1 Comment
Filed under: Security 

I was recently looking through some code and happen to stumble across some logic that is attempting to prohibit the application from redirecting to an external site. While this sounds like a pretty simple task, it is common to see it incorrectly implemented. Lets look at the check that is being performed.


	string url = Request.QueryString["returnUrl"];

	if (string.IsNullOrWhiteSpace(url) || !url.StartsWith("/"))
	{
		Response.Redirect("~/default.aspx");
	}
	else
	{
		Response.Redirect(url);
	}

The first thing I noticed was the line that checks to see if the url starts with a “/” characters. This is a common mistake when developers try to stop open redirection. The assumption is that to redirect to an external site one would need the protocol. For example, http://www.developsec.com. By forcing the url to start with the “/” character it is impossible to get the “http:” in there. Unfortunately, it is also possible to use //www.developsec.com as the url and it will also be interpreted as an absolute url. In the example above, by passing in returnUrl=//www.developsec.com the code will see the starting “/” character and allow the redirect. The browser would interpret the “//” as absolute and navigate to www.developsec.com.

After putting a quick test case together, I quickly proved out the point and was successful in bypassing this logic to enable a redirect to external sites.

Checking for Absolute or Relative Paths

ASP.Net has build in procedures for determining if a path is relative or absolute. The following code shows one way of doing this.

	string url = Request.QueryString["returnUrl"];
	Uri result;
    bool isAbsolute = false;

    isAbsolute = Uri.TryCreate(returnUrl, UriKind.Absolute, out result);

    if (!isAbsolute)
    {
         Response.Redirect(url);
    }
    else
    {
         Response.Redirect("~/default.aspx");
    }

In the above example, if the URL is absolute (starts with a protocol, http/https, or starts with “//”) it will just redirect to the default page. If the url is not absolute, but relative, it will redirect to the url passed in.

While doing some research I came across a recommendation to use the following:

	if (Uri.IsWellFormedUriString(returnUrl,UriKind.Relative))

When using the above logic, it flagged //www.developsec.com as a relative path which would not be what we are looking for. The previous logic correctly identified this as an absolute url. There may be other methods of doing this and MVC provides some other functions as well that we will cover in a different post.

Conclusion

Make sure that you have a solid understanding of the problem and the different ways it works. It is easy to overlook some of these different techniques. There is a lot to learn, and we should be learning every day.

.Net EnableHeaderChecking

November 9, 2015 by · Comments Off on .Net EnableHeaderChecking
Filed under: Security 

How often do you take untrusted input and insert it into response headers? This could be in a custom header or in the value of a cookie. Untrusted user data is always a concern when it comes to the security side of application development and response headers are no exception. This is referred to as Response Splitting or HTTP Header Injection.

Like Cross Site Scripting (XSS), HTTP Header Injection is an attack that results from untrusted data being used in a response. In this case, it is in a response header which means that the context is what we need to focus on. Remember that in XSS, context is very important as it defines the characters that are potentially dangerous. In the HTML context, characters like < and > are very dangerous. In Header Injection the greatest concern is over the carriage return (%0D or \r) and new line (%0A or \n) characters, or CRLF. Response headers are separated by CRLF, indicating that if you can insert a CRLF then you can start creating your own headers or even page content.

Manipulating the headers may allow you to redirect the user to a different page, perform cross-site scripting attacks, or even rewrite the page. While commonly overlooked, this is a very dangerous flaw.

ASP.Net has a built in defense mechanism that is enabled by default called EnableHeaderChecking. When EnableHeaderChecking is enabled, CRLF characters are converted to %0D%0A and the browser does not recognize it as a new line. Instead, it is just displayed as characters, not actually creating a line break. The following code snippet was created to show how the response headers look when adding CRLF into a header.

    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.AppendHeader("test", "tes%0D%0At\r\ntest2");
            Response.Cookies.Add(new HttpCookie("Test-Cookie", "Another%0D%0ATest\r\nCookie"));
        }
    }

When the application runs, it will properly encode the CRLF as shown in the image below.

EnableHeader1

My next step was to disable EnableHeaderChecking in the web.config file.

	 <httpRuntime targetFramework="4.6" enableHeaderChecking="false"/>

My expectation was that I would get a response that allowed the CRLF and would show me a line break in the response headers. To my surprise, I got the error message below:

EnableHeader2

So why the error? After doing a little Googling I found an article about ASP.Net 2.0 Breaking Changes on IIS 7.0. The item of interest is “13. IIS always rejects new lines in response headers (even if ASP.NET enableHeaderChecking is set to false)”

I didn’t realize this change had been implemented, but apparently, if using IIS 7.0 or above, ASP.Net won’t allow newline characters in a response header. This is actually good news as there is very little reason to allow new lines in a response header when if that was required, just create a new header. This is a great mitigation and with the default configuration helps protect ASP.Net applications from Response Splitting and HTTP Header Injection attacks.

Understanding the framework that you use and the server it runs on is critical in fully understanding your security risks. These built in features can really help protect an application from security risks. Happy and Secure coding!

I did a podcast on this topic which you can find on the DevelopSec podcast.

Potentially Dangerous Request.Path Value was Detected…

November 4, 2015 by · Comments Off on Potentially Dangerous Request.Path Value was Detected…
Filed under: Development, Security 

I have discussed request validation many times when we see the potentially dangerous input error message when viewing a web page. Another interesting protection in ASP.Net is the built-in, on by default, Request.Path validation that occurs. Have you ever seen the error below when using or testing your application?

Pdc1

The screen above occurred because I placed the (*) character in the URL. In ASP.Net, there is a default set of defined illegal characters in the URL. This list is defined by RequestPathInvalidCharacters and can be configured in the web.config file. By default, the following characters are blocked:

  • <
  • >
  • *
  • %
  • &
  • :
  • \\

It is important to note that these characters are blocked from being included in the URL, this does not include the protocol specification or the query string. That should be obvious since the query string uses the & character to separate parameters.

There are not many cases where your URL needs to use any of these default characters, but if there is a need to allow a specific character, you can override the default list. The override is done in the web.config file. The below snippet shows setting the new values (removing the < and > characters:

	<httpruntime requestPathInvalidCharacters="*,%,&,:,\\"/>

Be aware that due the the web.config file being an xml file, you need to escape the < and > characters and set them as &lt; and &gt; respectively.

Remember that modifying the default security settings can expose your application to a greater security risk. Make sure you understand the risk of making these modifications before you perform them. It should be a rare occurrence to require a change to this default list. Understanding the platform is critical to understanding what is and is not being protected by default.

Securing The .Net Cookies

October 13, 2015 by · Comments Off on Securing The .Net Cookies
Filed under: Development, Security 

I remember years ago when we talked about cookie poisoning, the act of modifying cookies to get the application to act differently.  An example was the classic cookie used to indicate a user’s role in the system.  Often times it would contain 1 for Admin or 2 for Manager, etc.  Change the cookie value and all of a sudden you were the new admin on the block.   You really don’t hear the phrase cookie poisoning anymore, I guess it was too dark.

There are still security risks around the cookies that we use in our application.  I want to highlight 2 key attributes that help protect the cookies for your .Net application: Secure and httpOnly.

Secure Flag

The secure flag tells the browser that the cookie should only be sent to the server if the connection is using the HTTPS protocol.  Ultimately this is indicating that the cookie must be sent over an encrypted channel, rather than over HTTP which is plain text.

HttpOnly Flag

The httpOnly flag tells the browser that the cookie should only be accessed to be sent to the server with a request, not by client-side scripts like JavaScript.  This attribute helps protect the cookie from being stolen through cross-site scripting flaws.

Setting The Attributes

There are multiple ways to set these attributes of a cookie. Things get a little confusing when talking about session cookies or the forms authentication cookie, but I will cover that as I go.  The easiest way to set these flags for all developer created cookies is through the web.config file.  The following snippet shows the httpCookies element in the web.config.

  
<system.web>
    <authentication mode="None" />
    <compilation targetframework="4.6" debug="true" />
    <httpruntime targetframework="4.6" />
    <httpcookies httponlycookies="true" requiressl="true" />
 </system.web>

As you can see, you can set httponlycookies to true to se the httpOnly flag on all of the cookies.  In addition, the requiressl setting sets the secure flag on all of the cookies with a few exceptions.

Some Exceptions

I stated earlier there are a few exceptions to the cookie configuration.  The first I will discuss is the session cookie. The session cookie in ASP.Net is defaulted/hard-coded to set the httpOnly attribute.  This should override any value set in the httpCookies element in the web.config.  The session cookie does not default to requireSSL and setting that value in the httpCookies element as shown above should work just find for it.

The forms authentication cookie is another exception to the rules.  Like the session cookie, it is hard-coded to httpOnly.  The Forms element of the web.config has a requireSSL attribute that will override what is found in the httpCookies element.  Simply put, if you don’t set requiressl=’true’ in the Forms element then the cookie will not have the secure flag even if requiressl=’true’ in the httpCookies element.

This is actually a good thing, even though it might not seem so yet.  Here is the next thing about that Forms requireSSL setting.. When you set it, it will require that the web server is using a secure connection.  Seems like common sense, but imagine a web farm where the load balancers offload SSL.  In this case, while your web app uses HTTPS from client to server, in reality, the HTTPS stops at the load balancer and is then HTTP to the web server.   This will throw an exception in your application.

I am not sure why Microsoft decided to make the decision to actually check this value, since the secure flag is a direction for the browser not the server.  If you are in this situation you can still set the secure flag, you just need to do it a little differently.  One option is to use your load balancer to set the flag when it sends any responses.  Not all devices may support this so check with your vendor.  The other option is to programmatically set the flag  right before the response is sent to the user.  The basic process is to find the cookie and just sent the .Secure property to ‘True’.

Final Thoughts

While there are other security concerns around cookies, I see the secure and httpOnly flag commonly misconfigured.  While it does not seem like much, these flags go a long way to helping protect your application.  ASP.Net has done some tricky configuration of how this works depending on the cookie, so hopefully this helps sort some of it out.   If you have questions, please don’t hesitate to contact me.  I will be putting together something a little more formal to hopefully clear this up a bit more in the near future.

ASP.Net Insufficient Session Timeout

October 6, 2015 by · Comments Off on ASP.Net Insufficient Session Timeout
Filed under: Development, Security, Testing 

A common security concern found in ASP.Net applications is Insufficient Session Timeout. In this article, the focus is not on the ASP.Net session that is not effectively terminated, but rather the forms authentication cookie that is still valid after logout.

How to Test

  • User is currently logged into the application.
  • User captures the ASPAuth cookie (name may be different in different applications).
    • Cookie can be captured using a browser plugin or a proxy used for request interception.
  • User saves the captured cookie for later use.
  • User logs out of the application.
  • User requests a page on the application, passing the previously captured authentication cookie.
  • The page is processed and access is granted.

Typical Logout Options

  • The application calls FormsAuthentication.Signout()
  • The application sets the Cookie.Expires property to a previous DateTime.

Cookie Still Works!!

Following the user process above, the cookie still provides access to the application as if the logout never occurred. So what is the deal? The key is that unlike a true “session” which is maintained on the server, the forms authentication cookie is self contained. It does not have a server side component to stay in sync with. Among other things, the authentication cookie has your username or ID, possibly roles, and an expiration date. When the cookie is received by the server it will be decrypted (please tell me you are using protection = all) and the data extracted. If the cookie’s internal expiration date has not passed, the cookie is accepted and processed as a valid cookie.

So what did FormsAuthentation.Signout() do?

If you look under the hood of the .Net framework, it has been a few years but I doubt much has changed, you will see that FormsAuthentication.Signout() really just removes the cookie from the browser. There is no code to perform any server function, it merely asks the browser to remove it by clearing the value and back-dating the expires property. While this does work to remove the cookie from the browser, it doesn’t have any effect on a copy of the original cookie you may have captured. The only sure way to really make the cookie inactive (before the internal timeout occurs) would be to change your machine key in the web.config file. This is not a reasonable solution.

Possible Mitigations

You should be protecting your cookie by setting the httpOnly and Secure properties. HttpOnly tells the browser not to allow javascript to have access to the cookie value. This is an important step to protect the cookie from theft via cross-site scripting. The secure flag tells the browser to only send the authentication cookie over HTTPS, making it much more difficult for an attacker to intercept the cookie as it is sent to the server.

Set a short timeout (15 minutes) on the cookie to decrease the window an attacker has to obtain the cookie.

You could attempt to build a tracking system to manage the authentication cookie on the server to disable it before its time has expired. Maybe something for another post.

Understand how the application is used to determine how risky this issue may be. If the application is not used on shared/public systems and the cookie is protected as mentioned above, the attack surface is significantly decreased.

Final Thoughts

If you are facing this type of finding and it is a forms authentication cookie issue, not the Asp.Net session cookie, take the time to understand the risk. Make sure you understand the settings you have and the priority and sensitivity of the application to properly understand “your” risk level. Don’t rely on third party risk ratings to determine how serious the flaw is. In many situations, this may be a low priority, however in the right app, this could be a high priority.

Future of ViewStateMac: What We Know

December 12, 2013 by · Comments Off on Future of ViewStateMac: What We Know
Filed under: Development, Security, Testing 

The .Net Web Development and Tools Blog just recently posted some extra information about ASP.Net December 2013 Security Updates (http://blogs.msdn.com/b/webdev/archive/2013/12/10/asp-net-december-2013-security-updates.aspx).

The most interesting thing to me was a note near the bottom of the page that states that the next version of ASP.Net will FORBID setting ViewStateMac=false. That is right.. They will not allow it in the next version. So in short, if you have set it to false, start working out how to work it to true before you update.

So why forbid it? Apparently, there was a Remote Code Execution flaw identified that can be exploited when ViewStateMac is disabled. They don’t include a lot of details as to how to perform said exploit, but that is neither here nor there. It is about time that something was critical enough that they have decided to take this property out of the developer’s hands.

Over the years I have written many posts discussing attacking ASP.Net sites, many of which rely on ViewStateMac being disabled. I have written to Microsoft regarding how EventValidation can be manipulated if ViewStateMac is disabled. The response was that they think developers should be using the secure settings. I guess that is different now that there is remote code execution. We have reached a new level.

So what does ViewStateMac protect? There are three things that I am aware of that it protects (search this site for any of these and you will find articles with much more detail):

  • ViewState – protects this from parameter tampering
  • EventValidation – protects this from parameter tampering
  • ViewStateUserKey – Used to protect requests from CSRF

So why do developers disable ViewStateMac? Great question. I believe that in most cases, it is disabled because the application is deployed in a web farm and when the web.config is not configured properly, an error is thrown. When some developers search for the error, many forums recommend disabling the ViewStateMac to fix the problem. Unfortunately, that is WRONG!!. Here is a Microsoft KB article that explains in detail how to properly configure a system to allow ViewStateMac to be enabled (http://support.microsoft.com/kb/2915218).

Is this a good thing? For developers, yes!. This will definitely help increase the protection for ViewState, EventValidation and CSRF if ViewStateUserKey is set. For Penetration Testers, Yes/No. Yes, because we get to say you are doing a good job in this category. No, because some easy pickings are going to be wiped off the plate.

I think this is a pretty bold move by Microsoft to remove control over this, but I do think it is a good thing. This is an important control in the WebForm ecosystem and all too often mis-understood by developers. This should bring many sites one step closer to being a little more secure when this change rolls out.

ASP.Net: Tampering with Event Validation – Part 2

February 10, 2012 by · 1 Comment
Filed under: Development, Security, Testing 

In part 1 of this series I demonstrated how to modify the values of a list box and access data I was not given access to by manipulating the view state and event validation parameters.  Remember, the key to this is that ViewStateMac must be disabled.  In this post, I will be demonstrating triggering button events that are not available to me. 

Target Application

The target application has a simple screen that has a drop down list with some transactions and a button to view the selected transaction.

Image 1

When a user selects a transaction and clicks the “View Transaction” button, the transaction is loaded (see Image 2).

Image 2

As seen in Image 1 above, some users have access to delete the selected transaction.  Image 3 shows what happens when we delete the transaction. (For this demo, the transaction is actually not deleted, a message is just displayed to make things simple.

Image 3

Unfortunately, the account I am using doesn’t allow me to delete transactions.  Lets take a look at how we can potentially bypass this so we can delete a transaction we don’t want.

Tools

I will only be using Burp Suite Pro and my custom Event Validation tool for this.  Other proxies can be used as well.

The Process

Lets take a look at the page as I see it (See Image 4).  I will click the “View Transaction” button and view a transaction.  Notice that there is no “Delete” button available.

Image 4

When I view the source of the page (Tools…View Source) I can see that the id of the “Get Transaction” button is ctl00$MainContent$cmdGetTransaction.  In some cases, I may have access to the details of the delete button (that is currently invisible).  In most cases, I may be stuck just making educated guesses as to what it might be.  In this case I do know what it is called (ctl00$MainContent$cmdDelete), but one could easily make simple guesses like cmdDelete, cmdRemove, cmdDeleteTransaction, etc..

I like to avoid doing any url encoding myself, so my first step is to change my proxy into intercept mode and select a transaction to view.  I want to intercept the response so that I can modify my __EVENTVALIDATION field before it goes to my page.  I need to add in my button to the __EVENTVALIDATION so that ASP.Net will accept it as valid.  I will use the custom Event Validation tool to do this.  Image 5 shows the Event Validation application with the needed changes.

Image 5

After modifying the __EVENTVALIDATION field, I will update that in my intercepted response and then let the page continue.

Original __EVENTVALIDATION

/wEWBgKo4+wkAu7T+jAC79P6MALs0/owAu3T+jACo/P//wU=

 

Modified __EVENTVALIDATION

/wEWBwKo4+wkAu7T+jAC79P6MALs0/owAu3T+jACo/P//wUCzLeukgU=

 

Now that I have modified the data on my current page, the next step is to Click the “View Transaction” button again to trigger a request.  The triggered request is shown in Image 6. 

Image 6

This request is triggering a “View Transaction” request, which is what we do not want.  We need to change this request so that it is calling the “Delete” command instead.  You can see the change in Image 7 below.

Image 7

When I continue the request and turn my intercept off I can see that my delete button click did fire and I get the message alerting me that the item was deleted (Image 8).

Image 8

Additional Notes

Since this is using a drop down list to define the transaction we are dealing with, I could combine the concepts from Part 1 in this series to delete other transactions that may not even be mine.  There are a lot of possibilities with tampering with the Event Validation and View State that can cause big problems.

Conclusion

This is an overly simplified example of how events that are meant to be hidden from users can be triggered when ViewStateMac is disabled.  It is important that if you are changing the visibility of buttons or other controls that trigger events based on users roles, that the actual event checks to make sure that the current user is authorized to perform its function.  I personally like all of the built in security features that .Net has, but no one should rely solely on them.  Of course, there are multiple factors that go into this vulnerability, so if things are not just right, it may not work. 

This information is provided as-is and is for educational purposes only.  There is no claim to the accuracy of this data.  Use this information at your own risk.  Jardine Software is not responsible for how this data is used by other parties. 

ASP.Net Webforms CSRF Workflow

February 7, 2012 by · Comments Off on ASP.Net Webforms CSRF Workflow
Filed under: Security, Testing 

An important aspect of application security is the ability to verify whether or not vulnerabilities exist in the target application.  This task is usually outsourced to a company that specializes in penetration testing or vulnerability assessments.  Even if the task is performed internally, it is important that the testers have as much knowledge about vulnerabilities as possible.  It is often said that a pen test is just testing the tester’s capabilities.  In many ways that is true.  Every tester is different, each having different techniques, skills, and strengths. Companies rely on these tests to assess the risk the application poses to the company.

In an effort to help add knowledge to the testers, I have put together a workflow to aid in testing for Cross Site Request Forgery (CSRF) vulnerabilities.  This can also be used by developers to determine if, by their settings, their application may be vulnerable.  This does not cover every possible configuration, but focuses on the most common.  The workflow can be found here: CSRF Workflow.  I have also included the full link below.

Full Link: http://www.jardinesoftware.com/Documents/ASP_Net_Web_Forms_CSRF_Workflow.pdf

Happy Testing!!

 

The information is provided as-is and is for educational purposes only.  Jardine Software is not liable or responsible for inappropriate use of this information.

Next Page »