European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Hosting - Amsterdam :: Commenting Server Controls in ASP.NET

clock July 10, 2012 07:39 by author Scott

How often do you just use an HTML comment to remove old code, or new functionality that isn’t ready yet? Are HTML comments effective for ASP.Net server controls? From a pure development context, they probably are. When we factor in security, they no longer provide the functionality that was intended. This post will explain an issue with how ASP.Net handles this situation and why it is not sufficient from a security perspective.

I am going to use a very simplistic example to make it easier to understand and to save space. Please do not let this simple example downplay the significance of this issue. In this example, I have added two label controls and a button control. I will walk through a few different scenarios to explain what is happening. Here is what the relevant part of the html page looks like:


  1: <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
  2:     <h2>
  3:         HTML Comment Test Page
  4:     </h2>
  5:     <p>
  6:         <asp:Label ID="lblUserName" runat="server" />
  7:         <asp:Label ID="lblAcctNum" runat="server" />
  8:         <asp:Button ID="cmdSubmit" runat="server" Text="Submit"
  9:             onclick="cmdSubmit_Click" />
 10:     </p>
 11: </asp:Content>

Below is the relevant code from the default.aspx.cs code behind file.  This is the code that contains the button click event that will be important throughout this post.

  1: protected void Page_Load(object sender, EventArgs e)
  2: {
  3:     lblUserName.Text = "joeUser";
  4:     lblAcctNum.Text = "933-3222222-939239";
  5: }
  6: protected void cmdSubmit_Click(object sender, EventArgs e)
  7: {
  8:     lblUserName.Text = "This shouldn't have happened.";
  9: }

When we run the page, the following output is exactly what we expect.  The labels are populated with their respected values and the button is there. 

  1: <h2>
  2:     HTML Comment Test Page
  3: </h2>
  4: <p>
  5:     <span id="MainContent_lblUserName">joeUser</span>
  6:     <span id="MainContent_lblAcctNum">933-3222222-939239</span>
  7:     <input type="submit" name="ctl00$MainContent$cmdSubmit" value="Submit" id="MainContent_cmdSubmit" />
  8: </p>

I would like to call out separately the EventValidation value.  It is beyond the scope of this post to fully explain EventValidation within .Net, but the short explanation is that it is used to only allow expected events to be triggered on the server.  The value is a hash of the allowed values and events.  Here is the value for this page:

  1: /wEWAgLFs4viAgKP5u6DCOTYhw/mo3AHFQHnB8XMEMHlrATJQZUNTjLevOMdQoay

Now lets comment out the button control and a label control and see what happens.  I will comment out the account number because I realized there are some problems with it.  It is displaying sensitive information and it is vulnerable to cross-site scripting.  I want to remove the button, because it is old functionality and I don’t want anyone to be able to perform that action going forward.  Here is what the new HTML data looks like:

  1: <h2>
  2:     HTML Comment Test Page
  3: </h2>
  4: <p>
  5:     <asp:Label ID="lblUserName" runat="server" />
  6:
  7:     <!--<asp:Label ID="lblAcctNum" runat="server" />-->
  8:     <!--<asp:Button ID="cmdSubmit" runat="server" Text="Submit"
  9:         onclick="cmdSubmit_Click" />-->
 10: </p>

It is important to note that I did not make any changes to the code behind file, because it was a) easier to update the html document and b) it doesn’t require me to change compiled code.  Although neither of these are good reasons, they are just used for the example.

Here is what the new HTML output looks like:


  1: <h2>
  2:      HTML Comment Test Page
  3: </h2>
  4: <p>
  5:      <span id="MainContent_lblUserName">joeUser</span>
  6:
  7:      <!--<span id="MainContent_lblAcctNum">933-3222222-939239</span>-->
  8:      <!--<input type="submit" name="ctl00$MainContent$cmdSubmit" value="Submit" id="MainContent_cmdSubmit" />-->
  9: </p>

The good news is that the elements are commented out, as we expected, but do you see a problem?  On line 7, the account number is still being populated and on line 8 the button was processed as well to a proper HTML button, rather than the asp:control that we commented out.  I would have expected that the controls would not have been processed because they were commented out. 

The .Net framework does not detect that the ASP.Net server controls are within HTML comments and still processes them as if they were not commented out.  Now, that sensitive data I was trying to remove, is just not displayed on the page, but still available in the source of the page.  All a user would have to do is View Source to see it. 

Remember I also mentioned I wanted to remove this label because it was vulnerable to cross-site scripting.  Well, unfortunately, it still is.  Just because it lives inside of HTML comments doesn’t mean if the proper values are sent down it is still protected.  It is possible for an attacker to submit data that will break out of the comment and then add their own execution steps.

Also, notice that the button looks valid.  What would happen if the end user decided to remove the comments around the button?  In this case, the button would still fire as it did in the first example.  There are other ways to trigger this button, but re-enabling it with a proxy or browser add-in is the easiest.  Lets take another look at our EventValidation value:

  1: /wEWAgLFs4viAgKP5u6DCOTYhw/mo3AHFQHnB8XMEMHlrATJQZUNTjLevOMdQoay

This value is the same as the last time we checked it before commenting out the button control.
  Since it is the same, we know that the same events are available to us and the button will be accepted.  This could cause a problem if the code is not ready for prime time, or has been removed due to issues of some sort.

A better way to resolve this issue is to set the Visible property for each of the server controls you no longer want to exist on the page, or just remove them if you are using source control.
  By setting the visible property to “False”, the .Net framework will not process that control and send it to the browser.  This also effects the EventValidation.  Lets look and see what happens when we set the Visible property in the HTML.

  1: <h2>
  2:     HTML Comment Test Page
  3: </h2>
  4: <p>
  5:     <asp:Label ID="lblUserName" runat="server" />
  6:
  7:     <asp:Label ID="lblAcctNum" Visible="false" runat="server" />
  8:     <asp:Button ID="cmdSubmit" runat="server" Visible="false" Text="Submit"
  9:         onclick="cmdSubmit_Click" />
 10: </p>

Here is the output:


  1: <p>
  2:     <span id="MainContent_lblUserName">joeUser</span>
  3:
  4:    
  5:    
  6: </p>

Notice how the button and label are no longer being output to the browser at all.
  This is much better and more secure.  Lets check the EventValidation value just to make sure it has changed. Oh, wait, because there are no other events on this page, EventValidation not longer exists.  That means that no events would be accepted by our page.  If other events existed, or if a listbox existed, then our value would have been different.  If we tried to then submit the button click event, an ASP.Net error would have been raised. 

As you can see, there are some issues when just using HTML comments for your server controls.
  ASP.Net has an issue, maybe a bug, that doesn’t detect this behavior and processes the controls as if they were allowed.  Remember, it is easy to re-enable a commented out control, so make sure you avoid that situation.  Just because a controls is commented, doesn’t mean it will represent a security risk, but any instance of this should be examined for potential security problems.




 



European ASP.NET 4 Hosting - Amsterdam :: Call ASP.NET Page Methods using your own AJAX

clock February 17, 2012 07:18 by author Scott

Microsoft has introduced JQuery as a primary javascript development tool for client end application. Even though there is a number of flexibility in ASP.NET AJAX applications, many developers do seek place to actually call a page using normal AJAX based application. In this post I will cover how you can invoke an ASP.NET page method directly from your own AJAX library.

What are page methods?

A Page method is a method that is written directly in a page. It is generally called when the actual page is posted back and some event is raised from the client. The pageMethod is called directly from ASP.NET engine.


What is a WebMethod?

A WebMethod is a special method attribute that exposes a method directly as XML service. To implement PageMethod we first need to annotate our method as WebMethod.

Steps to Create the application :

1. Start a new ASP.NET Project.
2. Add
JQuery to your page. I have added a special JQuery plugin myself which stringify a JSON object. The post looks like below :


(function ($) {
$.extend({
toJson: function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"' + obj + '"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof (v);
if (t == "string") v = '"' + v + '"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
}
});
// extend plugin scope
$.fn.extend({
toJson: $.toJson.construct
});
})(jQuery);

The code actually extends JQuery to add a method called toJSON to its prototype.


3. Add the server side method to the Default.aspx page. For simplicity we actually return the message that is received from the client side with some formatting.

[WebMethod]
public static string DisplayTime(string message)
{
// Do something

return string.Format("Hello ! Your message : {0} at {1}", message,
DateTime.Now.ToShortTimeString());
}

Remember : You should make this method static, and probably should return only serializable object.

4. Add the following Html which actually puts one TextBox which takes a message and a Button to call server.

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
Write Your message Here : <input type="text" id="txtMessage" />
</p>
<p>
<input type="button" onclick="javascript:callServer()" value="Call Server" />
</p>
</asp:Content>

Once you add this html to your default.aspx page, add some javascript to the page. We add the JQuery and our JSONStringify code to it.

<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="Scripts/JSONStringify.js" type="text/javascript"></script>

<script type="text/javascript">
function callServer() {
var objdata = {
"message" : $("#txtMessage").val()
};
$.ajax({
type: "POST",
url: "Default.aspx/DisplayTime",
data: $.toJson(objdata),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert(msg.d);
},
error: function (xhr, ajaxOptions) {
alert(xhr.status);
}
});
}
</script>

The above code actually invokes a normal AJAX call to the page. You can use your own library of AJAX rather than JQuery to do the same. On success, it returns the serializable object to msg.d.



European Ajax Hosting - Amsterdam :: 3 Mistakes to Avoid when Using jQuery with ASP.NET AJAX

clock February 7, 2012 08:16 by author Scott

In this post, I’m going to detail three of the problems that were discovered as a result of those previous two posts:

-          An extra requirement when making a read-only request to IIS6+.

-          An oddity in Internet Explorer 7′s XmlHttpRequest class.

-          A common mistake when passing JSON parameters through jQuery.

Finally, I’ll suggest what I now believe to be a best practice usage, taking all of these issues into account.

Security requirements when POSTing to IIS

This error message was the most common problem that was reported:

Length Required

The underlying issue is that most installations of IIS6+ require a content-length be provided with all POST requests, even if there is no content (POST data).

The content-length for a request with no data should be 0, but jQuery doesn’t set that header automatically unless there is a data parameter. Since ASP.NET AJAX’s JSON serialized services require a POST request, this becomes a stumbling block for read-only requests.

The easiest way I’ve found to work around this is to use an empty JSON object as a parameter on read-only requests. For example, if you were calling a page method:

$.ajax({
  type: "POST",
  url: "PageMethod.aspx/PageMethodName",
  data: "{}",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

This will cause jQuery to correctly set a content-length of 2, while your web service or page method will happily ignore the empty parameter and treat the request as read-only.

A problem with Internet Explorer and XmlHttpRequest

Previously, to call ASP.NET AJAX services with jQuery, I suggested this usage:

$.ajax({
  type: "POST",
  url: "WebService.asmx/WebMethodName",
  beforeSend: function(xhr) {
    xhr.setRequestHeader("Content-type",
                         "application/json; charset=utf-8");
  },
  dataType: "json"
});

The reason for the beforeSend delegate is due a quirk in jQuery which causes it to send a specified content-type only if there is also a data parameter specified.


For security reasons, ASP.NET AJAX will not provide a JSON serialized response unless the proper content-type is provided. By using the beforeSend delegate as shown, the content-type will be manually set on the XmlHttpRequest object, before the request.

However, the new XmlHttpRequest class in Internet Explorer 7 doesn’t implement setRequestHeader very intuitively. Instead of setting the specified header, it appends the value.

This becomes a problem when you make a request that includes a data parameter. When POST data is provided, jQuery will automatically set the content-type to its default of application/x-www-form-urlencoded. In the beforeSend delegate, the required application/json; charset=utf-8 will be appended after jQuery’s default.

End result? Because this amalgamation of content-types isn’t what ASP.NET AJAX expects, the web service will not return JSON serialized content and jQuery will be unable to parse it.

Solution? If you’re sending data in your request, use jQuery’s contentType parameter to set the content-type, so that the default is never added:

$.ajax({
  type: "POST",
  url: "WebService.asmx/WebMethodName",
  data: "{'fname':'dave', 'lname':'ward'}",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

JSON, objects, and strings

ASP.NET AJAX script services and page methods understand and expect input parameters to be serialized as JSON strings. These parameters are parsed out of the POST data and used as arguments to the method you’ve called.

However, if you directly provide a JSON object as the data parameter for an $.ajax call, jQuery will attempt to URL encode the object instead of passing it on to your web service.

Take this sample request, for example:

$.ajax({
  type: "POST",
  url: "WebService.asmx/WebMethodName",
  data: {'fname':'dave', 'lname':'ward'},
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

Because that data parameter is a valid object literal, calling the web service this way won’t throw any JavaScript errors on the client-side. Unfortunately, it won’t have the desired result either. Instead of passing that object through to the web service as JSON, jQuery will automatically URL encode it and send it as:

fname=dave&lname=ward

To which, the server will respond with:

Invalid JSON primitive: fname.

This is clearly not what we want to happen. The solution is to make sure that you’re passing jQuery a string for the data parameter, like this:

$.ajax({
  type: "POST",
  url: "WebService.asmx/WebMethodName",
  data: "{'fname':'dave', 'lname':'ward'}",
  contentType: "application/json; charset=utf-8",
  dataType: "json"
});

It’s a small change in syntax, but makes all the difference. Now, jQuery will leave our JSON object alone and pass the entire string to ASP.NET for parsing on the server side.

Taking these three caveats into account, I think this is the best practice for calling read-only ASP.NET AJAX web services via jQuery:

$.ajax({
  type: "POST",
  url: "ServiceName.asmx/WebMethodName",
  data: "{}",
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  success: function(msg) {
    // Do interesting things here.
  }
})
;

When consuming web services that require parameters, the usage is similar. Just make sure that you’re passing a JSON object in a string:

$.ajax({
  type: "POST",
  url: "ServiceName.asmx/WebMethodName",
  data: "{'fname':'dave','lname':'ward'}",
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  success: function(msg) {
    // Do magic here.
  }
});

In either of these cases, substitute PageName.aspx for ServiceName.asmx and PageMethodName for WebMethodName if you want to call a page method instead of a web service.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in