Under a specific set of circumstances you may be able to exploit something with this, but those would be rare circumstances.
We start with a vulnerable ASP.Net WebForms application. The important code is below, but you can download the whole thing.
public partial class Person1 : System.Web.UI.Page { protected int ID; protected override void OnInit(EventArgs e) { base.OnInit(e); if (Request.QueryString["id"] == null || Request.QueryString["id"].Length <= 0 || !int.TryParse(Request.QueryString["id"], out ID)) throw new InvalidOperationException("Must Specify Person"); _fireButton.Click += new EventHandler(_fireButton_Click); } void _fireButton_Click(object sender, EventArgs e) { Database.FirePerson(ID); Response.Redirect("~/Default.aspx", true); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); var p = Database.GetPerson(this.ID); this.Page.Title = p.Name; this._personDetail.DataSource = new Person[] { p }; this._personDetail.DataBind(); _fireButton.Visible = Session["admin"] != null; } }
The worst part about this code that there is no check to see if the user has the authority to Fire a Person. If the user doesn't, the button is hidden. And the developer assumes (or never even considered) what would happen if someone could chant the magical incantations that would cause a control that they couldn't see to fire an event.
Well, let's make it!
So what are those magical incantations?
<input type="hidden" name="__EVENTTARGET" value="" /> <input type="hidden" name="__EVENTARGUMENT" value="" />
That's it. That what tells ASP.Net what controls are firing an event. You can read more about them but the basics of it is you stick the control name in EVENTTARGET and any extra data you need (which you don't if it's just a button) in EVENTARGUMENT. The thing that fills them in is the javascript function __doPostback which in its simplest form looks like:
function __doPostBack(eventTarget, eventArgument) { document.form1.__EVENTTARGET.value = eventTarget; document.form1.__EVENTARGUMENT.value = eventArgument; document.form1.submit(); }
So let's take this magical incantation and use it on our vulnerable web app. There's a live demo here (Live Demo has been removed), running on Mono. When we're not logged in, this is what the Person Detail page looks like.
<html xmlns="http://www.w3.org/1999/xhtml"> <head><title> Jill Peter </title></head> <body> <form name="form1" method="post" action="Person.aspx?id=8" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNTgyODg2Mjc1D2QWAgIDD2QWAgIBDxQrAAIPFgQeC18hRGF0YUJvdW5kZx4LXyFJdGVtQ291bnQCAWRkFgJmD2QWAgIBD2QWAmYPFQMKSmlsbCBQZXRlcgdGaW5hbmNlCDU1NS05NDI3ZBgBBQ1fcGVyc29uRGV0YWlsDzwrAAoCBxQrAAFkCAIBZOfrbGOWSEnM5CkG42/p5JmOFNxh" /> </div> <div> <h2>Jill Peter</h2> <p>Department: Finance</p> <p>Phone: 555-9427</p> <p><a id="HyperLink1" href="Default.aspx">Home</a></p> </div> </form> </body> </html>
There's no javascript here, and no hidden inputs! Doesn't matter. Make it happen.
Now what happens?
ASP.Net Event Validation exists to thwart this exact attack. So that sucks doesn't it. But there's a light at the end of the tunnel here...
Now you may think that's cute, you can turn off security. But it's on by default, and most people don't change defaults do they? You're right, they don't. But there's still that light at the end of the tunnel I mentioned. You see, Event Validation sometimes impedes developers in subtle ways. After a might of googling, they find that flipping this property to off fixes everything. And since this attack I enumerate is a bit out there, it's generally not considered. K. Scott Allen has a two part blog article about Event Validation where he shows the common scenario where a devloper may turn it off.
So under circumstances like these:
- There's an administrative interface or user-interaction layer lurking below a page you can't see
- You have a guess at what the controls may be named *
- The developer has disabled Event Validation
* As an aside about finding the control names: you have two things in your favor. One: You can see other control names in the ID property. These will help you figure out a naming convention. Two: ASP.Net doesn't throw the Event Validation error if you guess wrong:
required, hidden, gravatared
required, markdown enabled (help)
* item 2
* item 3
are treated like code:
if 1 * 2 < 3:
print "hello, world!"
are treated like code: