JSON Security - asp.net

Do Pagemethods and Json have security risks?(I dont use cookies).Forexample i have a pagemethod and i am sending user id as a parameter but i dont want to show it to user.Can user get user id from pagemethod?

yes they can (see the user id). Any communication between the server and client can be seen by the user. Take a look with fiddler or firebug to see what goes on. You can treat it the same as any regular get or post request.
I know of no reason why not to use it. Without knowing any of the background I can't give a definitive answer on whether I would choose it but in general there is no reason not to use it just apply the same security you would use for HTTP get and post requests like in regular form submissions.

It has the same security risks as a regulat GET and POST, it is just another format to send the data back and forth. If you were using a regular POST, anyone would be able to see the userid just the same.
So if you don't want to have people messing up with the userid you could add some sort of encrypted string dependent on the userid to go along with it, for validation, to name one of many possible solutions.

JSON has no security by itself, It's an unencrypted data-format.

JSON can utilize FormsAuthentication security just like pages. What I usually do if I don't want the end-user to see an identifier, is to store that value (or something I can use to lookup that value) in User.Identity.Name.
The most complicated part of this approach is that the JSON may not return anything if you aren't authenticated. To work around this, I tend to include a non-authenticated page for getting JSON to tell you if the user is logged in or not.

I am hiding user id parameter in Hidden Field and just concerned that can it be changed while in that Process.Thanks all of your supports

if the userid is in a hidden form field, then it is completely exposed to anyone who views the source code in the browser. Not only can they see the userId, but they can see how you are sending it to the server.
In general, you never trust the client with sensitive data. Assume that they can always manipulate the response.
The way to securely pass messages is to give the user some session token in the form of a string. This session token should be generated with a fair amount of randomness and includes their username in the algorithm. Take a look at resources regarding md5 and salting. With this token that you give them, the assumption is now that they cannot reverse engineer the contents. Since they do not have the algorithm (it is sitting on the server side), then they cannot tamper with it. Your server will have to decrypt the session token to retrieve the userId of course.
This in itself does not mean your application is completely secure - it only fixes one of potentially many issues.

Related

Ok to pass IDs in query string?

Is it okay to pass IDs in the query string? For example:
example.com/viewperson.aspx?personid=22d62e18-2383-42ca-ba6d-a535355b98bb
Does this change (less risk) for an intranet site?
If a public site, assume anyone can access (shoulder serving, browser logging, etc).. even though we’re under SSL I still assume “out there”. Obviously, security will be applied to disallow an unauthenticated user from viewing page. But still a risk?
An added benefit of using query string is bookmarking a few (e.g. persons in this case) you want to call back up without having to go through the front door and look back up.
Would never pass anything meaningful, but maybe an ID is meaningful enough to not pass?
An alternative would be a cookie or session variable, of course.
Assuming these are resources you want protected its not a risk provided that requests for resources by id are both authenticated and authorised. Meaning you should verify that the request comes from a logged in user and that the user has access to that resource.
So if I belong to company 5 i shouldn't be able to open /companies/4.
Otherwise no issues and there is no alternative approach I am aware of. (by which I mean you must provide an identifier somehow)

Why do I need to perform server side validation?

Thanks to everyone who commented or posted an answer! I've kept my original question and update below for completeness.
[Feb 16, 2011 - Update 2] As some people point out - my question should have been: Given a standard asp.net 4 form, if I don't have any server side validation, what types of malicious attacks am I susceptible to?
Here is my take away on this issue.
If data isn't sensitive (comments on a page) - from an asp.net security standpoint, following standard best practices (SqlParameters, request validation enabled, etc) will protect you from malicious attacks.
For sensitive data/applications - it's up to you to decide what type of server side validation is appropriate for your application. You need to think the end to end solution (webservices, other systems, etc). You can view a number of suggestions below - whitelist validation, etc.
If you are using ajax (xhr requests) to post user input you need to reproduce the protection from the other bullets in your code on the server. Again, lots of solutions below – like ensuring that the data does not contain any html/code, etc. (side note: the .net framework requestValidationMode="4.0" does afford some protection in this regard - but I can't speak to how complete a solution it is)
Please feel free to continue to comment...if any of the above is incorrect please let me know. Thanks!
[Feb 3, 2011 - Update 1] I want to thank everyone for their answers! Perhaps I should ask the reverse question:
Assume a simple asp.net 4.0 web form (formview + datasource with request validation enabled) that allows logged in users to post comments to a public page (comments stored in sql server db table). What type of data validation or cleansing should I perform on the new "comments" on the server side?
[Jan 19, 2011 - Original Question] Our asp.net 4 website has a few forms where users can submit data and we use jquery validate on the client side. Users have to be logged in with a valid account to access these forms.
I understand that our client side validation rules could easily be bypassed and clients could post data without required fields, etc. This doesn’t concern me very much - users have to be logged in and I don’t consider our data very “sensitive” nor would I say any of our validation is “critical”. The input data is written to the database using SqlParameters (to defend against sql injection) and we depend on asp.net request validation to defend against potentially dangerous html input.
Is it really worth our time to rewrite the various jquery validation rules on the server? Specifically how could a malicious user compromise our server or what specific attacks could we be open to?
I apologize as it appears that this question has been discussed a few times on this site – but I have yet to find an answer that cites specific risks or issues with not performing server side validation. Thanks in advance
Hypothetical situation:
Let's say you have a zip code field. On the client-side you validate that it must be in a "00000" or "00000-0000" pattern. Since you're allowing a hyphen, you decide to store the field as a varchar in the database.
So, some evil user comes along and decides to bypass all of your client-side validation and submit something that's not in the correct format and makes it past the request validation.
Ok, no big deal..., you're encoding it before displaying it back to the user later anyway.
But what else are you doing with that zip code? Are you submitting it to web service for some sort of lookup? Are you uploading it to a GPS device? Will it ever be interpreted by something else in the future? Does your zipcode field now contain some JSON or something else weird?
Or something like this: http://www.businessinsider.com/livingsocial-server-flaw-2011-1
Security is a dependability attribute that is defined as the probability that the system resists to an attack, or else the probability a fault is not maliciously activated.
In order to implement security, you must perform a threat analysis. Complex computer systems are subject to deeper analyses (think about an aircraft's o a control tower's equipment) as they become more critical and threats pose business or human life at risk.
You can perform your own threat analysis by questioning yourself what happens if a user bypasses validation?.
Two groups of answers, by examples:
Group 1 (critical)
The user can buy articles paying less than their price
The user can be revealed information about other users
The user obtains privileges he/she is not supposed to have
Group 2 (non critical)
The user is displayed inconsistent data in the next page
Processing continues, but the inconsistency leads to an error that requires human intervention
The user's data (but only of that user, not others) get compromised
A strange error page is returned to the user, with lots of technical information that cannot be used anyway
In the first case, you must definitely fix your validation problem, because you could lose money after an attack, or lose the trust of your public (think about forging Facebook URLs and showing someone's photos even if you are not mutually friends).
In the second case, if you are sure that an inconsistent field doesn't put your business or the data at risk, you may still avoid fixing
The real problem is
How do you prove that any inconsistent data sent to your website is never supposed to have any consequence over the system that may pose a threat?
So that's why you lose less time fixing your validation rather than thinking about it
Honestly, users don't care what you consider "sensitive" or "critical" data. Those criteria are up to them to decide.
I know that if I was a user of your application and I saw my data change without me directly doing something to cause the change...I would close my account up as fast as possible. It would be readily apparent that your system wasn't secure and none of my data was safe.
Keep in mind that you're forcing people to log in so you at least have their passwords somewhere. Whether or not they are easily accessed, a breach is a breach and I have lost my trust.
So...while you may not consider an input injection attack important, your users will and that is why you should still do server side input validation.
Your data may not be worth much, that's fine by me.
BUT, attackers could inject CSRF "cross site request forgery" attack code into your application; users of your site may have their data at other sites compromised. Yes, it would require those 'other sites' to have bugs, but that happens. Yes, it would require that users not use the 'logout' buttons on those sites, but not enough people use them. Think of all the tasty data your users have stored at other web sites. You wouldn't something bad to happen to your users.
Attackers could inject HTML that invites users to download and install 'plugins necessary for viewing this content' -- plugins that are keyloggers, or search hard drives for credit card numbers or tax filings. Maybe a plugin to become spambots or porn hosts. Your users trust your site to not recommend plugins that are owned by the Yakuza, right? They might not feel friendly if your site recommends installing evil things.
Depending upon what kinds of bugs invalid data might trigger, you might find yourself a spambot or a porn host. It heavily depends on how defensively you have coded other aspects of your application. Too many applications blindly trust input data.
And the best part: your users aren't human. Your users are browsers, which might be executing attacks supplied by other sites that didn't bother to perform good input validation and output sanitizing. Your users are viruses or worms that happen to find you by chance or by design. You might trust the individuals, but how far do you trust their computers? Me, not very far.
Please write applications to be as secure as you can -- you may put a large button on the front page to drop all users' data if you want -- but please don't intentionally write insecure programs.
This an excellent and brave question. The short (and possibly brave) answer is you don't. If you are aware of all the security vulnerabilities and you still don't believe it's necessary, then that's your choice.
It really depends on who your users are, who the site is exposed to (in terms of intranet or internet) and how easy it is to obtain an account. You say that your data is not sensitive yet you still require users to log in. How bad would it be if an unauthorised user were to access the system by hopping on another user's machine whilst they were elsewhere?
Bear in mind that relying on the request validation to look for malicious input can never be proved to be 100% safe so security is usually done at multiple levels with a fair bit of redundancy.
However it has to be your choice and you are doing the right thing to find out the consequences of leaving this out.
I believe that you need to validate both on the client side and on the server side, and here's why.
On the client side, you are often saving the user from submitting data that is obviously wrong. They have not filled in a required field. They have put letters in a field that is only supposed to contain numbers. They have provided a date in the future when only a date in the past will do (such as date of birth). And so on. By preventing these kinds of mistakes on the client side, you are avoiding user frustration, and also reducing the number of unnecessary hits to your web server.
On the server side, you should generally repeat all of the validation that you did on the client side. That is because, as you have observed, clever users can get around client-side validation and submit invalid data. In addition, there is some validation that is inefficient or impossible to do on the client side. Sometimes, you check that the data entry adheres to business rules. You might check it against existing data in the database. If you just let users enter anything (especially omitting required fields), the website won't function properly for them.
Check out the Tamper Data extension for firefox. You can feed the server anything you want very easily
Anyone performing HTTP POSTs to your server via your web site (with jQuery validation) can also perform HTTP POSTs via some other means that bypasses the jQuery validation. For example, I could use System.Net.HttpWebRequest to POST some data to your server with the appropriate cookies that injects malicious content into the form fields. I'd have to set up the __EVENT_VALIDATION and __VIEWSTATE fields correctly, but if I succeed, I'd be bypassing the validation.
If you don't have server-side data validation, then you are effectively not validating the inputs at all. The jQuery validation is nice for user experience but not a real line of defense.
This is especially so with inputs like a free-form comments field. You definitely want to ensure that the field does not contain HTML or other malicious script. As an extra measure of defense, you should also escape the comment content when it is displayed in your web app with a library like AntiXss (see http://wpl.codeplex.com/).
In terms of client-side vs. server-side validation, my opinion is that client-side validation is just to make sure the form is filled correctly and a user could tamper with the form and bypass the verifications you do in javascript.
On the server-side you could actually make sure that you actually want to store this data and validate it in depth manner and check relative database tables to ensure that your database is always normalized with any data set that you get from the client. I would say even that the server side is more important than the client side in terms of not showing the user what do you look for in the form and how you validate the data.
to summarize, I recommend verification on both sides, but if I had to choose between the two i would recommend server-side validation , but that could mean that your server could potentially performing additional validations that you could have prevented from validating on the client side
To answer your second question:
You need to use a whitelist to keep malicious input out of the incoming comments.
The .NET Framework request validation does a very good job of stopping XSS payloads in incoming POST requests. It may not, however, prevent other malicious or mischevious HTML from getting into the comments (image tags, hyperlinks, etc.).
So if possible I would set up whitelist validation on the server side for allowed characters. A regex should cover this just fine. You should allow A-Za-z0-9, whitespace, and a few punctuation marks. If the regex fails to match, return an error message to the user and stop the transaction. Regarding SQL Injection: I would allow apostrophes through in this case (unless you like terrible grammar in your comments), but put code comments around your parameterized SQL queries to the effect of: "This is the only protection against SQL, so be careful when modifying." You should also lock down the permissions of the database account used by the web process (read/write only, not database owner permissions). What I wouldn't do is try to do blacklist validation on the input, as that is very time consuming to do correctly (see RSnake's XSS Cheat Sheet at http://ha.ckers.org/xss.html for an idea of the number of things you would need to prevent just for XSS).
Between the .NET framework and your own whitelist validation you should be safe from HTML-based attacks such as XSS and CSRF*. SQL injection will be prevented by using parameterized queries. If the comment data touches any other assets you may need to put more controls in place, but those cover the attacks relevant to the basic data submission form you've outlined.
Also, I wouldn't try to "cleanse" the data at all. It is very difficult to do properly and users (as was mentioned above) hate it when their data is modified without their permission. It is more secure and more usable to give user's a clear error message when your data validation fails. If you put their comment back on the page for them to edit, HTML encode the output so you aren't vulnerable to a Reflected XSS attack.
And as always, OWASP.org (http://www.owasp.org) is a good reference for all things webappsec related. Check out their Top Ten and Development Guide projects.
*CSRF may not be a direct concern of yours, as fraudulent posts to your site may not matter to you, but preventing XSS has the side benefit of keeping CSRF payloads targeting other sites from being hosted from your site.

Stop Direct Page Calls to Ajax Pages

Is there a "clever" way of stopping direct page calls in ASP.NET? (Page functionality, not the page itself)
By clever, I mean not having to add in hashes between pages to stop AJAX pages being called directly. In a nutshell, this is stopping users from accessing the Ajax pages without it coming from one of your websites pages in a legitimate way. I understand that nothing is impossible to break, I am simply interested in seeing what other interesting methods there are.
If not, is there any way that one could do it without using sessions/cookies?
Have a look at this question: Differentiating Between an AJAX Call / Browser Request
The best answer from the above question is to check for a requested-by or custom header.
Ultimately, your web server is receiving requests (including headers) of what the client sends you - all data that can be spoofed. If a user is determined, then any request can look like an AJAX request.
I can't think of an elegant method to prevent this (there are inelegant and probably non-perfect methods whereby you provide a hash of some sort of request counter between ajax and non-ajax requests).
Can I ask why your application is so sensitive to "ajax" pages being called directly? Could you design around this?
You can check the Request headers to see if the call is initiated by AJAX Usually, you should find that x-requested-with has the value XMLHttpRequest. Or in the case of ASP.NET AJAX, check to see if ScriptMAnager.IsInAsyncPostBack == true. However, I'm not sure about preventing the request in the first place.
Have you looked into header authentication? If you only want your app to be able to make ajax calls to certain pages, you can require authentication for those pages...not sure if that helps you or not?
Basic Access Authentication
or the more secure
Digest Access Authentication
Another option would be to append some sort of identifier to your URL query string in your application before requesting the page, and have some sort of authentication method on the server side.
I don't think there is a way to do it without using a session. Even if you use an Http header, it is trivial for someone to create a request with the exact same headers.
Using session with ASP.NET Ajax requests is easy. You may run into some problems, like session expiration, but you should be able to find a solution.
With sessions you will be able to guarantee that only logged-in users can access the Ajax services. When servicing an Ajax request simply test that there is a valid session associated with it. Of course a logged-in user will be able to access the service directly. There is nothing you can do to avoid this.
If you are concerned that a logged-in user may try to contact the service directly in order to steal data, you can add a time limit to the service. For example do not allow the users to access the service more often than one minute at a time (or whatever rate else is needed for the application to work properly).
See what Google and Amazon are doing for their web services. They allow you to contact them directly (even providing APIs to do this), but they impose limits on how many requests you can make.
I do this in PHP by declaring a variable in a file that's included everywhere, and then check if that variable is set in the ajax call file.
This way, you can't directly call the file ever because that variable will never have been defined.
This is the "non-trivial" way, hence it's not too elegant.
The only real idea I can think of is to keep track of every link. (as in everything does a postback and then a response.redirect). In this way you could keep a static List<> or something of IP addresses(and possible browser ID and such) that say which pages are allowed to be accessed at the moment from that visitor.. along with a time out for them and such to keep them from going straight to a page 3 days from now.
I recommend rethinking your design to be sure that this is really needed though. And also note IPs and such can be spoofed.
Also if you follow this route be sure to read up about when static variables get disposed and such. You wouldn't want one of those annoying "your session has expired" messages when they have been using the site for 10 minutes.

How do I send a user ID between different application in ASP.Net?

I have two web applications and both are developed in ASP.NET. Now I want to provide a feature which enables the user to click from one URL in application site (one virtual directory of IIS) A to the other URL in application site B (another virtual directory of IIS).
I have two ideas to implement them, but both of them have issues. I want to know what solution should be optimum solution?
Solution 1: using cookie, so from both application sites, we could retrieve user ID information from reading cookie, but I am afraid if cookie is disabled in browser, this "jump" feature never works.
Solution 2: When the user redirects to an URL in another site, I could append user ID after the URL, I could redirect to this URL in another site http://www.anotherapplicationsite.com/somesuburl?userID=foo, but I am afraird that in this way userID will be exposed easily which raise security issues.
I work with this sort of thing a lot. What you're looking for sounds like a candidate Single Sign-on solution or Federated Security.
You might try doing something similar to the following:
Create a simple db or other sort of table storage with two columns "nonce" and "username"
When you build the link to the other site create a GUID or other unique identifier to use as a one-time nonce, passing it as a querystring ?id=. Insert an entry into the table with the current authenticated username and the unique identifier you created.
When you reach the destination of your link, pass the unique identifier to call a webservice that will will match up the identifier with the username in the database you inserted before jumping to the second site (secure this with ssl).
If the nonce checks out with a valid username, you're all set. The webservice should remove the used entry and the table should stay more or less empty any time you are not in the middle of a transaction.
It is also good to include a datetime in your nonce/username table and expire it in 60 seconds or less to minimize the risk of replay attacks. We also require client certificates for external applications to call the webservice in order to verify the identity of the caller. Internal applications don't really necessitate using client certificates.
A nice thing about this is that it scales fairly well to as many sites as you would like to use
Not perfect security, but we've never had a significant compromise with a such as system.
As long as you have a good authentication system in place on the second website I think solution 2 is the one for you, taking into account the remark Andrew made about the sensitive ID's of course.
For more information on encryption: check the documentation of the FormsAuthentication.Encrypt Method . I think they even do something with writing a value in a cookie in that example.
If you put the userid in a query string and that's all the 2nd app uses to allow login, what's to keep me from manually typing in other users id's? You'd still have to prompt for password on the new site.
I'd use a database to hold login information, and have both sites reference that same db. Use it like you'd use a session.
D
I don't think 1) will work due to browser security (cookies from one domain cannot be read by another domain). I would go with 2), except I would encrypt the querystring value.
EDIT: For more info on cookie privacy/security issues, check out the "Privacy and third-party cookies" section here.
What are you using as the user's id? If you are using their social security number or email (something sensitive) then you are going to want to encrypt the value before you put it on the query string. Otherwise (if the user's id is something ambiguous like an integer or a GUID) it should be fine to put the id on the query string.
using cross domain, you can not SHARE the session, so I was thinking about POST
idea 1
if afraid of "showing" the username in the address, why not sending a POST?
<form name="myForm" action="http://www.mydomain.com/myLandingPage.aspx">
<input type="hidden" id="userid" value="myUsername" />
click here
</form>
but then... off course, "View Source Code" will show it
idea 2
then.. I remembered that I do the same, but sending a Encrypted string like:
http://www.anotherapplicationsite.com/somesuburl?userID=HhN01vcEEtMmwdNFliM8QYg+Y89xzBOJJG+BH/ARC7g=
you can use Rijndael algorithm to perform this, link below has VB and C# code:
http://www.obviex.com/samples/EncryptionWithSalt.aspx
then in site 2, just Decrypt and check if the user exists... if it does, continue, if not saying that the user tried to temper the query string :)

How do I prevent replay attacks?

This is related to another question I asked. In summary, I have a special case of a URL where, when a form is POSTed to it, I can't rely on cookies for authentication or to maintain the user's session, but I somehow need to know who they are, and I need to know they're logged in!
I think I came up with a solution to my problem, but it needs fleshing out. Here's what I'm thinking. I create a hidden form field called "username", and place within it the user's username, encrypted. Then, when the form POSTs, even though I don't receive any cookies from the browser, I know they're logged in because I can decrypt the hidden form field and get the username.
The major security flaw I can see is replay attacks. How do I prevent someone from getting ahold of that encrypted string, and POSTing as that user? I know I can use SSL to make it harder to steal that string, and maybe I can rotate the encryption key on a regular basis to limit the amount of time that the string is good for, but I'd really like to find a bulletproof solution. Anybody have any ideas? Does the ASP.Net ViewState prevent replay? If so, how do they do it?
Edit: I'm hoping for a solution that doesn't require anything stored in a database. Application state would be okay, except that it won't survive an IIS restart or work at all in a web farm or garden scenario. I'm accepting Chris's answer, for now, because I'm not convinced it's even possible to secure this without a database. But if someone comes up with an answer that does not involve the database, I'll accept it!
If you hash in a time-stamp along with the user name and password, you can close the window for replay attacks to within a couple of seconds. I don't know if this meets your needs, but it is at least a partial solution.
There are several good answers here and putting them all together is where the answer ultimately lies:
Block-cipher encrypt (with AES-256+) and hash (with SHA-2+) all state/nonce related information that is sent to a client. Hackers with otherwise just manipulate the data, view it to learn the patterns and circumvent everything else. Remember ... it only takes one open window.
Generate a one-time random and unique nonce per request that is sent back with the POST request. This does two things: It ensures that the POST response goes with THAT request. It also allows tracking of one-time use of a given set of get/POST pairs (preventing replay).
Use timestamps to make the nonce pool manageable. Store the time-stamp in an encrypted cookie per #1 above. Throw out any requests older than the maximum response time or session for the application (e.g., an hour).
Store a "reasonably unique" digital fingerprint of the machine making the request with the encrypted time-stamp data. This will prevent another trick wherein the attacker steals the clients cookies to perform session-hijacking. This will ensure that the request is coming back not only once but from the machine (or close enough proximity to make it virtually impossible for the attacker to copy) the form was sent to.
There are ASPNET and Java/J2EE security filter based applications that do all of the above with zero coding. Managing the nonce pool for large systems (like a stock trading company, bank or high volume secure site) is not a trivial undertaking if performance is critical. Would recommend looking at those products versus trying to program this for each web-application.
If you really don't want to store any state, I think the best you can do is limit replay attacks by using timestamps and a short expiration time. For example, server sends:
{Ts, U, HMAC({Ts, U}, Ks)}
Where Ts is the timestamp, U is the username, and Ks is the server's secret key. The user sends this back to the server, and the server validates it by recomputing the HMAC on the supplied values. If it's valid, you know when it was issued, and can choose to ignore it if it's older than, say, 5 minutes.
A good resource for this type of development is The Do's and Don'ts of Client Authentication on the Web
You could use some kind of random challenge string that's used along with the username to create the hash. If you store the challenge string on the server in a database you can then ensure that it's only used once, and only for one particular user.
In one of my apps to stop 'replay' attacks I have inserted IP information into my session object. Everytime I access the session object in code I make sure to pass the Request.UserHostAddress with it and then I compare to make sure the IPs match up. If they don't, then obviously someone other than the person made this request, so I return null. It's not the best solution but it is at least one more barrier to stop replay attacks.
Can you use memory or a database to maintain any information about the user or request at all?
If so, then on request for the form, I would include a hidden form field whose contents are a randomly generated number. Save this token to in application context or some sort of store (a database, flat file, etc.) when the request is rendered. When the form is submitted, check the application context or database to see if that randomly generated number is still valid (however you define valid - maybe it can expire after X minutes). If so, remove this token from the list of "allowed tokens".
Thus any replayed requests would include this same token which is no longer considered valid on the server.
I am new to some aspects of web programming but I was reading up on this the other day. I believe you need to use a Nonce.
(Replay attacks can easily be all about an IP/MAC spoofing, plus you're challenged on dynamic IPs )
It is not just replay you are after here, in isolation it is meaningless. Just use SSL and avoid handcrafting anything..
ASP.Net ViewState is a mess, avoid it. While PKI is heavyweight and bloated, at least it works without inventing your own security 'schemes'. So if I could, I'd use it and always go for mutual authent. Server-only authentification is quite useless.
The ViewState includes security functionality. See this article about some of the build-in security features in ASP.NET . It does validation against the server machineKey in the machine.config on the server, which ensures that each postback is valid.
Further down in the article, you also see that if you want to store values in your own hidden fields, you can use the LosFormatter class to encode the value in the same way that the ViewState uses for encryption.
private string EncodeText(string text) {
StringWriter writer = new StringWriter();
LosFormatter formatter = new LosFormatter();
formatter.Serialize(writer, text);
return writer.ToString();
}
Use https... it has replay protection built in.
If you only accept each key once (say, make the key a GUID, and then check when it comes back), that would prevent replays. Of course, if the attacker responds first, then you have a new problem...
Is this WebForms or MVC? If it's MVC you could utilize the AntiForgery token. This seems like it's similar to the approach you mention except it uses basically a GUID and sets a cookie with the guid value for that post. For more on that see Steve Sanderson's blog: http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
Another thing, have you considered checking the referrer on the postback? This is not bulletproof but it may help.

Resources