Javascript crashes on special characters from query string - javascript

To use this value in my TypeScript I am getting it from my query string like this:
var UserName = #Request.QueryString["UserName"];
But I get a Unexpeted Identifier error on it because if in DevTool if I go to where it breaks that query string has a value like this:
var UserName = ANT -- ANT 37690 / THIRD PARTY
So is there a way to do some kind of sanitation on it so it wouldn't crash? I guess there are illegal characters in that value for JS?

The error has nothing to do with "special" characters, but with the fact that the right side of the assignment - unwrapped in quotes - contains what js engine views as unknown identifier[s].
One way to properly format data that becomes part of javascript code is to use JavaScriptSerializer class from System.Web.Script.Serialization namespace.
var UserName = #new System.Web.Script.Serialization.JavaScriptSerializer().Seria‌​lize(Request.Query‌​St‌​ring["UserName"]);
The shorter version of this for a string is:
var UserName = "#System.Web.HttpUtility.JavaScriptStringEncode(Request.Query‌​St‌​ring["UserName"])";
or overloaded version that wraps the result in double quotes:
var UserName = #System.Web.HttpUtility.JavaScriptStringEncode(Request.Query‌​St‌​ring["UserName"], true);

You need to include quotes for the value.
var UserName = "#(Request.QueryString["UserName"])";
Otherwise the name will come through verbatim in your code and cause the problems you are seeing.
There is no need to protect against an attack vector here as the user can alter the page as they see fit at any time with a user script, and the QueryString is entered by them and only seen as a result by them in this scenario.
If there was a need to scrub the user input, it should be done prior to it actually reaching the view on server side. However, if still concerned about scrubbing output into a view in this type of scenario in general, it would be prudent to include an encode from razor's library.
var sanitizedJsVariable = "#System.Web.HttpUtility.JavaScriptStringEncode(model.VariableFromServer)";

Related

Remove last 3 letters of div (hidde also in browser page source)

this is my HTML
<div id="remove">Username</div>
and this is my JS code
function slice() {
var t = document.getElementById("remove");
t.textContent = t.textContent.slice(0, -3);
}
slice();
Username load from foreach
{foreach from=$last_user item=s}
{$s.date}
{$s.username}
{/foreach}
This code working and remove 3 letter but when right click on browser and look at page sources i can see "Username" !
I need remove three letter because of privacy and security .
something like
*** name or usern ***
Thank for help me !
The only secure way to make sure the client can't see a particular piece of information is to never send it to the client in the first place. Otherwise, there will always be a way for the client to examine the raw payloads of the network requests and figure out the information they aren't supposed to know.
You'll need to fix this on your backend - either hard-code in
<div id="remove">Usern</div>
or, for a more dynamic approach, use a template engine (or whatever's generating the HTML) and look up how to change strings with it. For example, in EJS, if user is an object with a username property, you could do
<div id="remove"><%= user.username.slice(0, -3) %></div>
Changing the content only with client-side JavaScript will not be sufficient, if you wish to keep some things truly private.
With Smarty, you can define a modifier that takes a string and returns all but the last three characters of it.
function smarty_modifier_truncate_three($string)
{
return substr($string, 0, -3);
}
and then in your template, replace
{$s.username}
with
{$s.username|truncate_three}
If you want only the first three characters, it's easier because you can use the built-in truncate.
{$s.username|truncate:3}
JS doesn't change the source, it can only change the DOM, so what you can do is to keep the element empty and add a value to it using js, but don't forget that js runs on the client's side so its better here to send the string from the server without the last 3 characters.

"Fixing" JSON coming out of MySQL

I'm fetching JSON code stored in MySQL and it has extra slashes, which I have to remove in order to parse it in JavaScript, after I print it on the page. Right now I'm doing the following:
$save = str_replace("\n", "<br>", $save); // Replace new line characters with <br>
$save = str_replace('\\"', '"', $save); // top-level JSON
$save = str_replace('\\\\"', '\"', $save); // HTML inside top level JSON
$save = str_replace('\\\\\\\\\\"', '\\\\\"', $save); // HTML inside second level JSON
Here is an example JSON code, as it comes out from MySQL:
{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}
And here is how it's supposed to look in order to get parsed correctly (using jsonlint.com to test):
{"id":2335,"editor":{"selected_shape":"spot-7488"},"general":{"name":"HTML Test","shortcode":"html-test","width":1280,"height":776},"spots":[{"id":"spot-7488","x":9.9,"y":22.6,"default_style":{"use_icon":1},"tooltip_content":{"content_type":"content-builder","plain_text":"<p class=\"test\">Test</p>","squares_json":"{\"containers\":[{\"id\":\"sq-container-293021\",\"settings\":{\"elements\":[{\"settings\":{\"name\":\"Paragraph\",\"iconClass\":\"fa fa-paragraph\"},\"options\":{\"text\":{\"text\":\"<p class=\\\"test\\\">Test</p>\"}}}]}}]}"}}]}
Please note that I have HTML code inside JSON, which is inside another JSON and this is where it gets a bit messy.
My question - is there a function or library for PHP (for JS will work too) which covers all those corner cases, because I'm sure someone will find a way to break the script.
Thanks!
The short answer, which is woefully inadequate, is for you to use stripslashes. The reason this answer is not adequate is that your JSON string might have been escaped or had addslashes called on it multiple times and you would have to call stripslashes precisely once for each time this had happened.
The proper solution is to find out where the slashes are being added and either a) avoid adding the slashes or b) understand why the slashes are there and respond accordingly. I strongly believe that the process that creates that broken JSON is where the problem lies.
Slashes are typically added in PHP in a few cases:
magic_quotes are turned on. This is an old PHP feature which has been removed. The basic idea is that PHP used to auto-escape quotes in incoming requests to let you just cram incoming strings into a db. Guess what? NOT SAFE.
add_slashes has been called. Why call this? Some folks use it as an incorrect means of escaping data before sticking stuff in a db. Others use it to keep HTML from breaking when echoing variables out (htmlspecialchars should probably be used instead). It can also come in handy in a variety of other meta situations when you are defining code in a string.
When escaping data input. The most common escaping function is mysqli_real_escape_string. It's very important to escape values before inserting them in a db to prevent sql injection and other exploits but you should never escape things twice.
So there's a possibility that your code is double-escaping things or that addslashes is getting called or something like magic_quotes is causing the problem, but I suspect it is another problem: some JS code might be supplying this JSON not as a proper JSON string, but one that has been escaped so to define a string within javascript.
If you take your example JSON string above, and slap some quotes around it:
var myJSON = "<put your string here>";
then SURPRISE your javascript is not broken and the var myJSON contains a string that is actually valid JSON and can be parsed into an a valid JSON object:
var myJSON = "{\"id\":2335,\"editor\":{\"selected_shape\":\"spot-7488\"},\"general\":{\"name\":\"HTML Test\",\"shortcode\":\"html-test\",\"width\":1280,\"height\":776},\"spots\":[{\"id\":\"spot-7488\",\"x\":9.9,\"y\":22.6,\"default_style\":{\"use_icon\":1},\"tooltip_content\":{\"content_type\":\"content-builder\",\"plain_text\":\"<p class=\\\"test\\\">Test</p>\",\"squares_json\":\"{\\\"containers\\\":[{\\\"id\\\":\\\"sq-container-293021\\\",\\\"settings\\\":{\\\"elements\\\":[{\\\"settings\\\":{\\\"name\\\":\\\"Paragraph\\\",\\\"iconClass\\\":\\\"fa fa-paragraph\\\"},\\\"options\\\":{\\\"text\\\":{\\\"text\\\":\\\"<p class=\\\\\\\"test\\\\\\\">Test</p>\\\"}}}]}}]}\"}}]}";
console.log(JSON.parse(myJSON)); // this is an actual object
The key here is to examine the point of entry where this JSON arrives in your system. I suspect some AJAX request has created some object and rather than sending valid JSON Of that object, it is sending instead an escaped string of a JSON object.
EDIT:
Here's a simple example of what happens when you have too many encodings. Try running this JS in your browser and observe the console output:
var myObj = {"key":"here is my value"};
console.log(myObj);
var myJSON = JSON.stringify(myObj);
console.log(myJSON);
var doubleEncoded = JSON.stringify(myJSON);
console.log(doubleEncoded);

Javascript var with a newline using MVC Model property

I have to set a Javascript variable to equal a property in my MVC model.
I am doing this to detect if any changes were made to a textbox, this is setting the "original" value.
My Javascript code looks like this:
var initVal = '#Model.ReferralHistoryDetail[1].ReferralComments';
I am getting an error, which I assume is due to this containing carriage returns in the comments.
Uncaught SyntaxError: Unexpected token ILLEGAL
The HTML being rendered in this case is putting the closing quote on a newline, and that is the error being shown in the developer console.
For example, the rendered HTML is:
var initVal = 'blah blah blah
';
What is the proper way to handle this?
You want to use the JavaScriptStringEncode command to encode the string in a javascript compatible way.
var initVal = '#HttpUtility.JavaScriptStringEncode(Model.ReferralHistoryDetail[1].ReferralComments)';
If you replace \n character by \,
you will have a valid syntax for multiple lines string.
So that should work
var initVal = '#Model.ReferralHistoryDetail[1].ReferralComments.Replace("\n","\\")';
I found other ways to allow multiple line string in javascript,
in this answer.
You need to create an extension method that replaces the new line character with tags.
Or use the method HtmlEncode
like this:
var initVal = #Html.Raw(HttpUtility.HtmlEncode(#Model.ReferralHistoryDetail[1].ReferralComments).Replace("\n", "<br />"))
You cannot access Model properties from JavaScript like that, JavaScript cannot do anything with your model.
Create a variable up the page
#{ var value = #Model.ReferralHistoryDetail[1].ReferralComments;
Then access value in javascript, though not sure why you don't just render directly on page why do you need javascript unless I am missing something

How do I put SAFEARRAY (array of bytes) to HTML Hidden field

I'd like to get array of bytes from active-x component, store that in html-form input hidden field and then pass it to server via form-submit. How can I do that?
MIDL:
HRESULT Data([out, retval] SAFEARRAY(VARIANT) *pArray);
C++/ATL
STDMETHODIMP MyActiveX::get_Data(SAFEARRAY **pArray)
{
CComSafeArray<BYTE> arr;
for (int i = 0; i < 10; i++)
{
CComVariant a;
a = (BYTE)i;
arr.Add(a);
}
arr.CopyTo(pArray);
return S_OK;
}
Javascript:
$("#hiddenField").val(myActiveX.Data);
Browser tells me: type mismatch
Although I am not familiar with your exact situation, I have seen some similar situations before.
You are correct to put your data in a field using $('#hiddenField'). If you've put a name attribute on that field so that it becomes part of the HTTP submit, that part is good.
As for myActiveX.Data, I imagine that this is some sort of JavaScript object. Remember that only a string can be put into an HTML input; it does not hold binary data.
What I would do is put a breakpoint before $("#hiddenField").val(myActiveX.Data);
. Use the debugger keyword if you're not familiar with it. Run the code in your debugger and look at the structure of the value of myActiveX.Data. It probably has some sort of wrapper field.
Alternatively, if you don't have access to a good JavaScript debugger, try the following"
for(x in myActiveX.Data)
alert(x + ": " + myActiveX.Data[x]);
I'm assuming the C++ code is the server side code.
The best way to handle this is to serialise the SAFEARRAY. From there you can handle it in two ways.
Firstly, the serialisation. I've looked at MSDN and I think using LPSAFEARRAY_Marshal and LPSAFEARRAY_Unmarshal (with an optional IDispatch or IUnknown IID to specify the type, but the documentation doesn't say how it's used) or LPSAFEARRAY_UserMarshal and LPSAFEARRAY_UserUnmarshal to convert the SAFEARRAY to/from a serialised format.
Secondly, handling the data transfer.
Option 1: Save the serialised data on the server side and put a token representing the saved file into the hidden field.
Option 2: Use Hex, Base64, etc. to encode the data into a printable format and putting that data into the hidden field.
Either way, when you need to get the data back, just de-serialise it with the matching function.

Best way to safely read query string parameters?

We have a project that generates a code snippet that can be used on various other projects. The purpose of the code is to read two parameters from the query string and assign them to the "src" attribute of an iframe.
For example, the page at the URL http://oursite/Page.aspx?a=1&b=2 would have JavaScript in it to read the "a" and "b" parameters. The JavaScript would then set the "src" attribute of an iframe based on those parameters. For example, "<iframe src="http://someothersite/Page.aspx?a=1&b=2" />"
We're currently doing this with server-side code that uses Microsoft's Anti Cross-Scripting library to check the parameters. However, a new requirement has come stating that we need to use JavaScript, and that it can't use any third-party JavaScript tools (such as jQuery or Prototype).
One way I know of is to replace any instances of "<", single quote, and double quote from the parameters before using them, but that doesn't seem secure enough to me.
One of the parameters is always a "P" followed by 9 integers.
The other parameter is always 15 alpha-numeric characters.
(Thanks Liam for suggesting I make that clear).
Does anybody have any suggestions for us?
Thank you very much for your time.
Upadte Sep 2022: Most JS runtimes now have a URL type which exposes query parameters via the searchParams property.
You need to supply a base URL even if you just want to get URL parameters from a relative URL, but it's better than rolling your own.
let searchParams/*: URLSearchParams*/ = new URL(
myUrl,
// Supply a base URL whose scheme allows
// query parameters in case `myUrl` is scheme or
// path relative.
'http://example.com/'
).searchParams;
console.log(searchParams.get('paramName')); // One value
console.log(searchParams.getAll('paramName'));
The difference between .get and .getAll is that the second returns an array which can be important if the same parameter name is mentioned multiple time as in /path?foo=bar&foo=baz.
Don't use escape and unescape, use decodeURIComponent.
E.g.
function queryParameters(query) {
var keyValuePairs = query.split(/[&?]/g);
var params = {};
for (var i = 0, n = keyValuePairs.length; i < n; ++i) {
var m = keyValuePairs[i].match(/^([^=]+)(?:=([\s\S]*))?/);
if (m) {
var key = decodeURIComponent(m[1]);
(params[key] || (params[key] = [])).push(decodeURIComponent(m[2]));
}
}
return params;
}
and pass in document.location.search.
As far as turning < into <, that is not sufficient to make sure that the content can be safely injected into HTML without allowing script to run. Make sure you escape the following <, >, &, and ".
It will not guarantee that the parameters were not spoofed. If you need to verify that one of your servers generated the URL, do a search on URL signing.
Using a whitelist-approach would be better I guess.
Avoid only stripping out "bad" things. Strip out anything except for what you think is "safe".
Also I'd strongly encourage to do a HTMLEncode the Parameters. There should be plenty of Javascript functions that can this.
you can use javascript's escape() and unescape() functions.
Several things you should be doing:
Strictly whitelist your accepted values, according to type, format, range, etc
Explicitly blacklist certain characters (even though this is usually bypassable), IF your whitelist cannot be extremely tight.
Encode the values before output, if youre using Anti-XSS you already know that a simple HtmlEncode is not enough
Set the src property through the DOM - and not by generating HTML fragment
Use the dynamic value only as a querystring parameter, and not for arbitrary sites; i.e. hardcode the name of the server, target page, etc.
Is your site over SSL? If so, using a frame may cause inconsistencies with SSL UI...
Using named frames in general, can allow Frame Spoofing; if on a secure site, this may be a relevant attack vector (for use with phishing etc.)
You can use regular expressions to validate that you have a P followed by 9 integers and that you have 15 alphanumeric values. I think that book that I have at my desk of RegEx has some examples in JavaScript to help you.
Limiting the charset to only ASCII values will help, and follow all the advice above (whitelist, set src through DOM, etc.)

Categories

Resources