Allowing dangerous query strings - asp.net

I need to be able to allow query strings that contain characters like '<' and '>'. However, putting something like id=mi<ke into the the URL will output an error page saying:
A potentially dangerous Request.QueryString value was detected from the client (id="mi<ke").
If I first url encode the url (to create id=mi%3Cke) I still get the same error. I can get around this by putting ValidateRequest="false" into the Page directive, but I'd prefer not to do that if at all possible.
So is there anyway to allow these characters in query strings and not turn off ValidateRequest?
EDIT: I want to allow users to be able to type the urls in by hand as well, so encoding them in some way might not work.

I ran into a problem similar to this. I chose to base64 encode the query string to work around it.
using
System.Text.ASCIIEncoding.ASCII.GetBytes
to get the string as bytes
and then
System.Convert.ToBase64String
to turn it into a "safe" string.
To get it back, use:
System.Convert.FromBase64String
and then:
System.Text.ASCIIEncoding.ASCII.GetString
to reverse the polarity of the flow.

A little googling and I don't think so.
The exception seems to happen before your code even runs so you can't trap the exception.
I like the encoding as base64 or something idea.

Instead of URL encode, you could encrypt your id value to get around the issue. You will probably then need to URL encode the encrypted string.

I think you have some options. You could do as you indicate and turn off ValidateRequest. You would then need to take care of any input sanitization on your own. Or you could allow only certain characters and either have the user use a meta language to input them, i.e., instead of '<' use '[' and replace '>' with ']' or re-encoding these before submission yourself to the meta language (or Base64). Doing the re-encoding yourself would require Javascript be available for queries that used forbidden characters. You may still need to do input sanitization.
Quick stab at a jquery implementation:
$(document).ready( function() {
$('form').bind('submit', function() {
$('form' > 'input[type=text]').each( function(i) {
if (this.value) {
this.value = encode(this.value);
}
});
});
});
function encode(value) {
return ...suitable encoding...
}

I was working with the same problem, however i stumbled upon this javascript encoding method:
<script type="text/javascript">
var unencodedText = "This is my text that contains whitespaces and characters like and Ø";
var encodedText = "";
var decodedText = "";
alert('unencodedText: ' + unencodedText);
//To encode whitespaces and the 'Ø' character - use encodeURI
encodedText = encodeURI(unencodedText);
//We see that whitespaces and 'Ø' are encoded, but the '' is still there:
alert('encodedText: ' + encodedText);
//If we decode it we should get our unencodedText back
decodedText = decodeURI(encodedText);
alert('decodedText: ' + decodedText);
//To also encode the '' we use the encodeURIComponent
encodedText = encodeURIComponent(unencodedText);
//Now all the characters have been encoded:
alert('encodedText: ' + encodedText);
//To get our unencodedText back we now need to use the decodeURIComponent
decodedText = decodeURIComponent(encodedText);
alert('decodedText: ' + decodedText);
</script>
If you're dealing with more complicated symbols then you might want to use the encodeURIComponent for the url.
And i steal this gem from this link.

Related

query string parameter without value, only key

i have question about query string in asp.net:
standart query string with query string parameter is "www.mysity.url?key1=value1&key2=value2", but i need only check has query string key or not...yes, one of the correct decisions: www.mysite.url?reset=true, but this excess syntax for me.
in markup i use something like "<a href='UrlHelper.GetResetUrl()'>Reset</a>", this method return "www.mysity.url?reset", but in user side markup i have "Reset"
If you do not specify the name for a parameter it is taken as null.
Its value would be reset
So you would have to check it as follows:
if(Request.QueryString[null]=="reset")
{
//Take some reset action
}
a Quick and dirty solution is:
if(Request.Url.Query.Contains("?reset"))
{
// ok we have a reset
}
Assuming that you have a standard reset call ask as: www.mysity.url?reset and the reset url not have other parameters. If you have you can simple check for the reset keyword.
This code HttpContext.Current.Request["reset"] is always return null, so the next best thing if you like to make it hard, is to manual analyze your keys after the url.
All code that handles querystring parameters should be case insensitive. Browsers (or parts of internet infrastructure?) may convert the case.
One way to check if reset parameter is present in querystring:
bool reset = Request.Url.Query.IndexOf("reset", StringComparison.CurrentCultureIgnoreCase) > -1;

Character + is converted to %2B in HTTP Post

I'm adding functionality to a GM script we use here at work, but when trying to post (cross site may I add) to another page, my posting value of CMD is different than what it is on the page.
It's supposed to be Access+My+Account+Info but the value that is posted becomes Access%2BMy%2BAccount%2BInfo.
So I guess my question is: What's escaping my value and how do I make it not escape? And if there's no way to unescape it, does anyone have any ideas of a workaround?
Thanks!
%2B is the code for a +. You (or whatever framework you're using) should already be decoding the POST data server-side...
Just a quick remark: If you want to decode a path segment, you can use UriUtils (spring framework):
#Test
public void decodeUriPathSegment() {
String pathSegment = "some_text%2B"; // encoded path segment
String decodedText = UriUtils.decode(pathSegment, "UTF-8");
System.out.println(decodedText);
assertEquals("some_text+", decodedText);
}
Uri path segments are different from HTML escape chars (see list). Here is an example:
#Test
public void decodeHTMLEscape() {
String someString = "some_text+";
String stringJsoup = org.jsoup.parser.Parser.unescapeEntities(someString, false);
String stringApacheCommons = StringEscapeUtils.unescapeHtml4(someString);
String stringSpring = htmlUnescape(someString);
assertEquals("some_text+", stringJsoup);
assertEquals("some_text+", stringApacheCommons);
assertEquals("some_text+", stringSpring);
}
/data/v50.0/query?q=SELECT Id from Case
This worked for me. Give space instead of '+'

Stop the user entering ' char

I have a search page where I would like to stop the user entering a ' into textboxes, or replace it with a suitable character. Can anyone help me achieve this in asp.net vb ?
For example if a user searches for O'Reilly the search crashes with error:
Line 1: Incorrect syntax near 'Reilly'. Unclosed quotation mark before the character string ' '.
Thanks!
Use parameterized statements properly, and this will be handled for you.
Uh-oh. Use parameterized queries.
Use javascript onKeyDown event for the textbox - if the typed char is an apostrophe, you can simply drop it, so that it is not entered.
On the server side, you should simply replace "'" with "", just to make sure.
Be aware, that this is a very unsecure and unstable solution.
You can escape ' character with two of them '', e.g.
sql += "Surname LIKE '%" & name.Replace("'", "''") & "%' AND "
and SQL will accept it then.
However, I would suggest using parameters.
To actually answer the question, you can put an OnKeyDown javascript event on your textbox, detect the key that was pressed, and potentially cancel the input:
<input class="mainSearchBox" type="text" id="searchTerm" onkeydown="DetectIllegalKeys();">
<script>
function DetectIllegalKeys() {
if (event.keyCode == 222) {
event.returnValue = false;
}
}
</script>
to instead change apostrophes to an alternate character:
<input class="mainSearchBox" type="text" id="searchTerm" onkeyup="ChangeSingleQuote();">
<script>
function ChangeSingleQuote() {
var searchTerm = document.getElementById('searchTerm');
searchTerm.value = searchTerm.value.replace(/'/g, "e");
}
I highly recommend that you not use this approach for this problem!
Far better to fix the application to allow searches for titles of any character string.
You need to understand why the error occurs and not just solve it symptomatically. Read through Microsoft's own document about SQL Injection to find out how to protect yourself from this class of security flaws.
http://msdn.microsoft.com/en-us/library/ms998271.aspx
(As several others pointed out, parameterized statements is the solution.)

ISO-8859-1 to UTF8 in ASP.NET 2

We've got a page which posts data to our ASP.NET app in ISO-8859-1
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<title>`Sample Search Invoker`</title>
</head>
<body>
<form name="advancedform" method="post" action="SearchResults.aspx">
<input class="field" name="SearchTextBox" type="text" />
<input class="button" name="search" type="submit" value="Search >" />
</form>
and in the code behind (SearchResults.aspx.cs)
System.Collections.Specialized.NameValueCollection postedValues = Request.Form;
String nextKey;
for (int i = 0; i < postedValues.AllKeys.Length; i++)
{
nextKey = postedValues.AllKeys[i];
if (nextKey.Substring(0, 2) != "__")
{
// Get basic search text
if (nextKey.EndsWith(XAEConstants.CONTROL_SearchTextBox))
{
// Get search text value
String sSentSearchText = postedValues[i];
System.Text.Encoding iso88591 = System.Text.Encoding.GetEncoding("iso-8859-1");
System.Text.Encoding utf8 = System.Text.Encoding.UTF8;
byte[] abInput = iso88591.GetBytes(sSentSearchText);
sSentSearchText = utf8.GetString(System.Text.Encoding.Convert(iso88591, utf8, abInput));
this.SearchText = sSentSearchText.Replace('<', ' ').Replace('>',' ');
this.PreviousSearchText.Value = this.SearchText;
}
}
}
When we pass through Merkblätter it gets pulled out of postedValues[i] as Merkbl�tter
The raw string string is Merkbl%ufffdtter
Any ideas?
You have this line of code:-
String sSentSearchText = postedValues[i];
The decoding of octets in the post has happen here.
The problem is that META http-equiv doesn't tell the server about the encoding.
You could just add RequestEncoding="ISO-8859-1" to the #Page directive and stop trying to fiddle around with the decoding yourself (since its already happened).
That doesn't help either. It seems you can only specify the Request encoding in the web.config.
Better would be to stop using ISO-8859-1 altogether and leave it with the default UTF-8 encoding. I can see no gain and only pain with using a restrictive encoding.
Edit
If it seems that changing the posting forms encoding is not a possibility then we seem to be left with no alternative than to handle the decoding ourselves. To that end include these two static methods in your receiving code-behind:-
private static NameValueCollection GetEncodedForm(System.IO.Stream stream, Encoding encoding)
{
System.IO.StreamReader reader = new System.IO.StreamReader(stream, Encoding.ASCII);
return GetEncodedForm(reader.ReadToEnd(), encoding);
}
private static NameValueCollection GetEncodedForm(string urlEncoded, Encoding encoding)
{
NameValueCollection form = new NameValueCollection();
string[] pairs = urlEncoded.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (string pair in pairs)
{
string[] pairItems = pair.Split("=".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries);
string name = HttpUtility.UrlDecode(pairItems[0], encoding);
string value = (pairItems.Length > 1) ? HttpUtility.UrlDecode(pairItems[1], encoding) : null;
form.Add(name, value);
}
return form;
}
Now instead of assigning:-
postedValues = Request.Form;
use:-
postValues = GetEncodedForm(Request.InputStream, Encoding.GetEncoding("ISO-8859-1"));
You can now remove the encoding marlarky from the rest of the code.
I think adding your encoding into web.config like that will probably solve your problem :
<configuration>
<system.web>
<globalization
fileEncoding="iso-8859-1"
requestEncoding="iso-8859-1"
responseEncoding="iso-8859-1"
culture="en-US"
uiCulture="en-US"
/>
</system.web>
</configuration>
We had the same problem that you have. The topic is not straight-forward at all.
The first tip is to set the Response encoding of the page that posts the data (usually the same page as the one that receives the data in .NET) to the desired form post encoding.
However, this is just a hint to the user's browser on how to interpret the characters sent from the server. The user might choose to override the encoding manually. And, if the user overrides the encoding of the page, the encoding of the data sent in the form is also changed (to whatever the user has set the encoding to).
There is a small trick, though. If you add a hidden field with the name _charset_ (notice the underscores) in your form, most browsers will fill out this form field with the name of the charset used when posting the form. This form field is also a part of the HTML5 specification.
So, you might think your're good to go, however, when in your page, ASP.NET has already urldecoded all parameters sent in to the form. So when you actually have the value in the _charset_ field, the value of the field containing Merkblätter is already decoded incorrectly by .NET.
You have two options:
In the ASP.NET page in question, perform the parsing of the request string manually
In Application_BeginRequest, in Global.asax, parse the request parameters manually, extracting the _charset_field. When you get the value, set Request.ContentEncoding to System.Text.Encoding.GetEncoding(<value of _charset_ field>). If you do this, you can read the value of the field containing Merkblätter as usual, no matter what charset the client sends the value in.
In either of the cases above, you need to manually read Request.InputStream, to fetch the form data. I would recommend setting the Response Encoding to UTF-8 to have the greatest number of options in which characters you accept, and then treating the special cases when the user has overridden the charset especially, as specified above.
Function urlDecode(input)
inp = Replace(input,"/","%2F")
set conn = Server.CreateObject("MSXML2.ServerXMLHTTP")
conn.setOption(2) = SXH_SERVER_CERT_IGNORE_ALL_SERVER_ERRORS
conn.open "GET", "http://www.neoturk.net/urldecode.asp?url=" & inp, False
conn.send ""
urlDecode = conn.ResponseText
End Function
To speed this up, just create a table on your db for decoded and encoded urls and read them on global.asa application.on_start section. Later put them on the application object.
Then put a check procedure for that application obj. in above function and IF decoded url not exists on app array, THEN request it one time from remote page (tip: urldecode.asp should be on different server see: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316451) and insert it to your db and append to application array object, ELSE return the function from the application obj.
This is the best method I have ever found.
If anybody wants further details on application object, database operations etc. contact me via admin#neoturk.net
You can see above method successfully working at: lastiktestleri.com/Home
I also used, HeliconTech's ISAPI_Rewrite Lite version
usage is simple: url = Request.ServerVariables("HTTP_X_REWRITE_URL")
this will return the exact url directed to /404.asp
That's because you are encoding the string as ISO-8859-1 and decoding it as if it was a string encoded as UTF-8. This will surely mess up the data.
The form isn't posting the data as ISO-8859-1 just because you send the page using that encoding. You haven't specified any encoding for the form data, so the browser will choose an encoding that is capable of handling the data in the form. It may choose ISO-8859-1, but it may just as well choose some other encoding.
The data is send to the server, where it's decoded and put in the Request.Form collection, according to the encoding that the browser specifies.
All you have to do is to read the string that has already been decoded from the Request.Form collection. You don't have to loop through all the items in the collection either, as you already know the name of the text box.
Just do:
string sentSearchText = Request.Form("SearchTextBox");
What I ended up doing was forcing our app to be in ISO-8859-1. Unfortunately the underlying data may contain characters which don't fit nicely into that codepage so we go through the data before displaying it and convert everything about the character code of 127 into an entity. Not ideal but works for us...
I had the same problem, solved like this:
System.Text.Encoding iso_8859_2 = System.Text.Encoding.GetEncoding("ISO-8859-2");
System.Text.Encoding utf_8 = System.Text.Encoding.UTF8;
NameValueCollection n = HttpUtility.ParseQueryString("RT=A+v%E1s%E1rl%F3+nem+enged%E9lyezte+a+tranzakci%F3t", iso_8859_2);
Response.Write(n["RT"]);
A+v%E1s%E1rl%F3+nem+enged%E9lyezte+a+tranzakci%F3t will return "A vásárló nem engedélyezte a tranzakciót" as expected.

Force ASP.NET textbox to display currency with $ sign

Is there a way to get an ASP.NET textbox to accept only currency values, and when the control is validated, insert a $ sign beforehand?
Examples:
10.23 becomes $10.23
$1.45 stays $1.45
10.a raises error due to not being a valid number
I have a RegularExpressionValidator that is verifying the number is valid, but I don't know how to force the $ sign into the text. I suspect JavaScript might work, but was wondering if there was another way to do this.
The ASP.NET MaskedEdit control from the AJAX Control Toolkit can accomplish what you're asking for.
I know an answer has already been accepted, but I wanted to throw out another solution for anyone with the same problem and looking for multiple workarounds.
The way I do this is to use jQuery format currency plugin to bind user input on the client side. Parsing this input on the server side only requires:
// directive
using System.Globalization;
// code
decimal input = -1;
if (decimal.TryParse(txtUserInput.Text, NumberStyles.Currency,
CultureInfo.InvariantCulture, out input))
{
parameter = input.ToString();
}
The only downfall to this is that the user can have javascript turned off, in which case the RegEx validator running server-side would work as a fall-back. If the control is databound, all you have to do is decimalValue.ToString("{0:c}") , as mentioned by others, in order to display the proper currency formatting.
The cool thing about this is that if the user enters the textbox and it shows $0.00 on the client side, the server-side if statement would return false. If your decimal value isn't nullable in the database, just change decimal input = -1 to decimal input = 0 and you'll have a default value of 0.
Another way to do this might be to place the dollar sign outside to the left of the text box. Is there a real need to have the dollar sign inside of the box or will a simple label do?
decimal sValue = decimal.Parse(txtboxValue.Text.Trim());
// Put Code to check whether the $ sign already exist or not.
//Try making a function returning boolean
//if Dollar sign not available do this
{ string LableText = string.Format("{0:c}", sValue); }
else
{ string LableText = Convert.ToString(sValue); }
string sValue = Convert.ToString(txtboxValue.Text.Trim());
// Put Code to check whether the $ sign already exist or not.
//Try making a function returning boolean
//if Dollar sign not available do this
{ string LableText = string.Format("{0:c}", "sValue"); }
else
{ string LableText = Convert.ToString(sValue); }
In the .CS you could do a pattern match along the lines of,
string value = text_box_to_validate.Text;
string myPattern = #"^\$(\d{1,3},?(\d{3},?)*\d{3}(\.\d{0,2})|\d{1,3}(\.\d{2})|\.\d{2})$";
Regex r = new Regex(myPattern);
Match m = r.Match(value);
if (m.Success)
{
//do something -- everything passed
}
else
{
//did not match
//could check if number is good, but is just missing $ in front
}

Resources