{"id":153,"date":"2010-04-05T22:53:44","date_gmt":"2010-04-06T02:53:44","guid":{"rendered":"http:\/\/www.peteonsoftware.com\/?p=153"},"modified":"2024-03-01T17:46:11","modified_gmt":"2024-03-01T22:46:11","slug":"asp-net-request-collections","status":"publish","type":"post","link":"https:\/\/www.peteonsoftware.com\/index.php\/2010\/04\/05\/asp-net-request-collections\/","title":{"rendered":"Asp.Net Request Collections"},"content":{"rendered":"<p>Today on Twitter, <a href=\"http:\/\/blah.winsmarts.com\/\">Sahil Malik<\/a> asked the question &#8220;Is there any reason ever to use Request.QueryString over Request.Params?&#8221; (<a href=\"http:\/\/twitter.com\/sahilmalik\/status\/11650071551\">link<\/a> &#8211; for as long as it persists on Twitter).  <\/p>\n<p>For QueryString itself, there is practically no reason not to use the less specific collection, as QueryString is always checked first.  That means that there is a small performance hit in Request.Params as it will check all collections regardless and not one in just calling Request, as it returns the first one it finds.  <\/p>\n<p>If you are trying to get at the Forms, Cookies, or ServerVariables collections, there is a performance hit (albeit small) no matter which way you turn.  (Information on the happenings inside the .Net Framework are available on <a href=\"http:\/\/www.hanselman.com\/blog\/ASPNETParamsCollectionVsQueryStringFormsVsRequestindexAndDoubleDecoding.aspx\">this<\/a> Hanselman post from a few years ago.<\/p>\n<p>There is an issue, however, if you want to access any of the other collections by using either Request[] or Request.Params[].  And really, this is the code smell that I was worried about when responding to Sahil earlier today.  Let&#8217;s make an example page here.  I made this using Asp.Net WebForms (to hopefully have the widest base of understanding).<\/p>\n<p>Here is the meat of the .aspx page.<\/p>\n<pre>\r\n    &lt;form id=\"form1\" runat=\"server\"&gt;\r\n    &lt;div&gt;\r\n        &lt;asp:Button runat=\"server\" Text=\"Submit\" OnClick=\"submitButton_Click\" ID=\"submitButton\" \/&gt;\r\n    &lt;\/div&gt;\r\n    &lt;asp:Panel runat=\"server\" Visible=\"false\" ID=\"adminPanel\"&gt;\r\n    You shouldn't see me unless you are an admin.\r\n    &lt;\/asp:Panel&gt;\r\n    &lt;\/form&gt;\r\n<\/pre>\n<p>Here is the code behind<\/p>\n<pre>\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Web;\r\nusing System.Web.UI;\r\nusing System.Web.UI.WebControls;\r\n\r\nnamespace Params\r\n{\r\n    public partial class _Default : System.Web.UI.Page\r\n    {\r\n        protected void Page_Load(object sender, EventArgs e)\r\n        {\r\n            Response.Cookies.Add(new HttpCookie(\"IsAdmin\", \"false\"));\r\n        }\r\n\r\n        protected void submitButton_Click(object sender, EventArgs e)\r\n        {\r\n            var value = Request[\"IsAdmin\"];\r\n\r\n            if (Convert.ToBoolean(value))\r\n            {\r\n                adminPanel.Visible = true;\r\n            }\r\n            else\r\n            {\r\n                Response.Write(\"You aren't an admin\");\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/www.peteonsoftware.com\/images\/April2010\/InitialPage.jpg\" alt=\"The initial page load.\" title=\"The initial page load.\" \/><\/p>\n<p>When we click the button, the cookie value is checked and since it is false, we get the sad news that we aren&#8217;t an admin.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.peteonsoftware.com\/images\/April2010\/FirstClick.jpg\" alt=\"After the first click.\" title=\"After the first click.\" \/><\/p>\n<p>Okay, let&#8217;s now assume that someone is curious if you are using simple cookie checks, so they look inside Firefox to see what the cookies are on your site.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.peteonsoftware.com\/images\/April2010\/Cookie.jpg\" alt=\"Our site's cookie.\" title=\"Our site's cookie.\" \/><\/p>\n<p>Now, let me take a chance that the operator of this site is being sloppy and is using Request[] instead of calling the value from the cookie collection explicitly.  I&#8217;ll add ?IsAdmin=true onto the querystring to mirror the cookie and then click the button.  Since the QueryString collection is checked first, I&#8217;ll be overriding the cookie in this instance.<\/p>\n<p>Here is our result<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.peteonsoftware.com\/images\/April2010\/AdminHacked.jpg\" alt=\"Our site has now been compromised.\" title=\"Our site has now been compromised.\" \/><\/p>\n<p>Well, that&#8217;s not good.  What if we actually just check the cookie value instead of being lazy?<\/p>\n<pre>\r\n        protected void submitButton_Click(object sender, EventArgs e)\r\n        {\r\n            var value = Request.Cookies[\"IsAdmin\"].Value;\r\n\r\n            if (Convert.ToBoolean(value))\r\n            {\r\n                adminPanel.Visible = true;\r\n            }\r\n            else\r\n            {\r\n                Response.Write(\"You aren't an admin\");\r\n            }\r\n        }\r\n<\/pre>\n<p>Now when I try the QueryString hack, the page is safe.<br \/>\n<img decoding=\"async\" src=\"https:\/\/www.peteonsoftware.com\/images\/April2010\/NoHack.jpg\" alt=\"Crisis averted.\" title=\"Crisis averted.\" \/><\/p>\n<p>This doesn&#8217;t solve all of the problems with this page, though.  I&#8217;m not pushing this off as some airtight secure solution.  What I&#8217;m hoping to point out is that coding hard and even though we are given certain shortcuts, you <em>really<\/em> have to understand the ramifications of your code before throwing it out in the wild.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today on Twitter, Sahil Malik asked the question &#8220;Is there any reason ever to use Request.QueryString over Request.Params?&#8221; (link &#8211; for as long as it persists on Twitter). For QueryString itself, there is practically no &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[86,15],"tags":[5,89],"class_list":["post-153","post","type-post","status-publish","format-standard","hentry","category-code-optimization","category-code-tips","tag-code-optimization","tag-code-tips"],"_links":{"self":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/comments?post=153"}],"version-history":[{"count":0,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/posts\/153\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/media?parent=153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/categories?post=153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.peteonsoftware.com\/index.php\/wp-json\/wp\/v2\/tags?post=153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}