In .NET, how do I prevent, or handle, tampering wi

2019-08-04 19:23发布

问题:

If a disabled drop-down list is dynamically rendered to the page, it is still possible to use Firebug, or another tool, to tamper with the submitted value, and to remove the "disabled" HTML attribute. This code:

protected override void OnLoad(EventArgs e) {
    var ddlTest = new DropDownList() {ID="ddlTest", Enabled = false};
    ddlTest.Items.AddRange(new [] { new ListItem("Please select", ""), new ListItem("test 1", "1"), new ListItem("test 2", "2") });
    Controls.Add(ddlTest);
}

results in this HTML being rendered:

<select disabled="disabled" id="Properties_ddlTest" name="Properties$ddlTest">
    <option value="" selected="selected">Please select</option>
    <option value="1">test 1</option>
    <option value="2">test 2</option>

</select>

The problem occurs when I use Firebug to remove the "disabled" attribute, and to change the selected option.
On submission of the form, and re-creation of the field, the newly generated control has the correct value by the end of OnLoad, but by OnPreRender, it has assumed the identity of the submitted control and has been given the submitted form value.
.NET seems to have no way of detecting the fact that the field was originally created in a disabled state and that the submitted value was faked. This is understandable, as there could be legitimate, client-side functionality that would allow the disabled attribute to be removed.

Is there some way, other than a brute force approach, of detecting that this field's value should not have been changed?

I see the brute force approach as being something crap, like saving the correct value somewhere while still in OnLoad, and restoring the value in the OnPreRender. As some fields have dependencies on others, that would be unacceptable to me.

回答1:

Use ViewState. It is encrypted enough to stop the average hacker.



回答2:

If this is truly a concern then persist a value on the server somewhere (in session perhaps) that indicates that the control was set as disabled on the initial render of the page. If the control is not still in a disabled state when the page posts back then you know the form was tampered with.

Edit

This is secure against client tampering because a disabled control is never submitted by the form and as such the modified data will never reach the server. Please see http://w3.org/TR/html401/interact/forms.html#h-17.12.



回答3:

A general rule for building secure webb applications: Don't ever trust any input from the client. Assume that each request has been handbuilt in order to break through your security system.

The only thing safe is to ignore any data coming back from the disable fields. That data will have to be stored in the session, or reloaded from the database (or whatever data storage you use).



回答4:

Going back through some old questions, I realised at least one simple approach exists: Use the page's viewstate as mentioned by @Mark Hurd.

This is a quick hack, but something like this:

    private const string defaultValue = "Hack me!"; // from original data source
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        ViewState[txtTest.ClientID] = false;
    }
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if(ViewState[txtTest.ClientID] != null && !(bool)ViewState[txtTest.ClientID])
            txtTest.Text = defaultValue;

        string x = txtTest.Text;
    }

I can't even remember what I was doing with this problem... Anyway, it would be good if there was a .NET attribute meaning "really disabled" that wasn't rendered to the client. I guess that's what this solution represents a hack-approximation of.



回答5:

Just dont process that data and you would do fine. If you are displaying some constants then they should be stored server side.



回答6:

Replace the input fields with labels.

In other words, instead of disabling a TextBox or DropDown, just hide them and show a label instead.