replace/ encode < and > with jquery/ ajax before submitting - javascript

I have the following code which is part of a comment form in a page.
$.ajax({
type: "POST",
url: "path/to/script.php",
data: $(form).serialize(),
success: function(data) {
$('#comment_form').fadeOut(1000);
var url = 'path/to/script.php';
$('#commenti').load(url + ' .comment');
}
});
On server side all characters like < and > get stripped but i need them to allow displaying code snippets inside the <code></code> tags.
Is there any way with jquery to convert the < to < and > to > before submitting so the comments will display without stripped characters?

I haven't found any good client side solution yet, so here is a little php-serverside function.
For anyone who needs it:
function specialchars($special) {
$replace = array(
'<' => '<',
'>' => '>',
'&' => '&'
);
return strtr($special, $replace);
}
Use the function specialchars based on your needs.

Try this
function htmlEncode(value){
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
function htmlDecode(value){
return $('<div/>').html(value).text();
}
and take a look at this post HTML-encoding lost when attribute read from input field

Using jQuery, you can retrieve a string with < and > replaced by html-entities by using this approach.
var text = "<script>alert('I am XSS');<script> This is regular ol' text!";
var escapedText = $('<i>').text(text).html();
// "<script>alert('I am XSS');<script> This is regular ol' text!"
The output might need additional escaping when posting however, due to the ampersands (?querystring=string&string2=...)
I would recommend you escape the <> characters with encodeURIComponent, and do post-processing on the server, like others have suggested previously:
var text = "<script>alert('I am XSS');<script> This is regular ol' text!";
var escapedText = encodeURIComponent(text);
// "%3Cscript%3Ealert('I%20am%20XSS')%3B%3Cscript%3E%20This%20is%20regular%20ol'%20text!"
// post with AJAX
then on the server
echo htmlentities(rawurldecode($_POST["query"]));
// "<script>alert('I am XSS');<script> This is regular ol' text!"
If your app is facing the WWW, you ought to ensure all input is being properly sanitized before being output to users - OWASP Encoding Project and HTML Purifier are worth checking out!

Related

How to resolve a JavaScript XSS vulnerability issue

I have a JavaScript AJAX call that pulls in HTML code into an MVC form.
Coverity flags that because it wants me to sanitize JavaScript tags. Quite rightly because you don't want some hacker to go in and mess things right up.
I put in a Trusted HTML Policy. That satisfies Coverity. But now the HTML code shows up as plain-text on the screen.
So $(target).html(result) is no longer behaving how I expected it to.
I tried different methods: innerHTML, $.parseHTML() and .text().html() all do not give me the desired results.
I even commented out the TrustedHTML policy and put in a replace function instead. That didn't work.
All I have is a string of HTML showing up as plain text on the screen.
I comment out the TrustedHTML and the replace function and it works as intended. But Coverity hates it.
After a few days of doing some workshopping with this problem, I have used the following and it seems to satisfy Coverity.
Treat this as a bare bones solution. Coverity wants a Trusted HTML policy. The programmer will need to beef it up to remediate any and all security issues that arise.
const escapeHTMLPolicy =
trustedTypes.createPolicy("newEscapePolicy", {
createHTML: (string) => {
const policyWhitelist = [];
// be sure to escape your whitelisted data
policyWhitelist.push("<script type=\"text/javascript\">");
// . . . other functioning to clear up
// other vulnerabilities . . .
// This will now return trusted HTML data along with anything you wish to whitelist.
if (string.includes("<script") && !policyWhitelist.some(item => string === item)) {
string.replace(/<script.*/g, "")
}
return string;
}
});
Use this function like so:
$.ajax({
// something . . .
success: function (response) {
var htmlContent = escapeHTMLPolicy.createHTML(response);
var htmlNode = htmlContent.toString();
$(targetDiv).html(htmlNode);
}
});

Double Quotes Break HTML Attributes and JS

So I have some ajax requests that pull data from our product pages. These product pages can have a " (double quote) in their URL somewhere. This is a necessary evil, I'd explain why, but please just accept that I have to keep the double quotes in these URLs.
In a nutshell, I am pulling stuff from an Excel XML file, then conducting ajax requests with Javascript/jQuery that pull text and data from "Product Pages" and then displaying that stuff on a "Product Listings" page. Again, the URLs of these "Product Pages" sometimes have double quotes in them.
Moving on, these ajax requests are called via a function and the data obtained is returned and utilized by a callback. These functions have worked great until recently when we discovered that " (double quotes) are breaking the functions. These double quotes are being passed in the url variable to these AJAX requests. I have read a bunch of other posts mentioning quotes breaking their scripts, but many have found solutions, and I have not been able to.
I even tried var href = encodeURI( $(this).text() ); and var href = encodeURIComponent( $(this).text() );. These don't seem to fix the issue. Before I go on, let me show you my script.
XML
<Worksheet ss:Name="Recommended">
<Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="5" x:FullColumns="1"
x:FullRows="1" ss:DefaultRowHeight="15">
<Column ss:AutoFitWidth="0" ss:Width="96.75"/>
<Row ss:AutoFitHeight="0">
<Cell><Data ss:Type="String">/2U-12"-Economy-Rack-Shelf-KH-3000100202/</Data></Cell>
</Row>
</Table>
</Worksheet>
JS
$(this).find('Data').each(function(){
var href = $(this).text();
// This is where the 'url' is getting it's value from the 'href' variable
// that is being pulled from the XML file 'Data'
getProductData('name', href, function(val) {
console.log(val);
});
});
// Get data from the product page anywhere (Global)
function getProductData(type, url, callBack) {
$.ajax({
url: url,
method: 'GET',
dataType: 'html',
success: function(data){
var $data = $(data).find('#product-data');
var val = $data.data(type);
return callBack( val );
},
error: function(data) {
console.error( 'getProductData: ' + type + ' = FAIL / URL: ' + url );
}
});
}
HTML
<input type="hidden" id="product-data" data-name="{product['product_name']}">
Any ideas on how I can get these double quotes to work with my script? It seems there is very little on the subject available... I haven't had this issue in all my years in development :(
I just cannot get the quotes (that are actually coded as " in the XML file) to encode properly when the AJAX request uses this string as the url parameter...
The outcome of the above is my getProductData() simply does not return anything. This same function returns data just fine when the url variable does not contain double quotes in the string...
EDIT
I have also tried var href = $(this).text().replace('"', '\"'); btw.
EDIT So I mis-diagnosed my issue. The AJAX requests were working, the values being returned were just corrupted by the quotes. So, the issue was that the quotes made attributes break apart in my HTML, the AJAX requests were doing okay.
I am renaming the post to better label the issue I was having. Sometimes, it's the most basic things that break our stuff right?
You can't put strings with double quotes inside an attribute that is itself enclosed by double quotes. While I do not know what technology you're using to set the value of the data-name attribute, whatever you're using must convert the double quote to ". In PHP you would use the htmlspecialchars function. With JavaScript you could use .replace(/"/g,"&quot");
The end result should look like this
<input type="hidden" id="product-data" data-name="2U-12"-Economy-Rack-Shelf-KH-3000100202"
So ultimately what I had to do was:
Change the the double quotes in my HTML to single quotes
Use var href = encodeURI( $(this).text() ); when passing the href variable to getProductData()
I could have also used .replace('"', '&quote') on the data-name value to resolve the issue as well, but I don't like using javascript unless absolutely necessary... It would be cleaner IMo, but yeah...

How to parse xml with js or jquery, when fields are not known in advance?

I have been searching for the past hour and have not found a solution that is well suited to my situation. I have an event registration form and in order for users to have the form auto populated they can specify an id from a previous registration. There are over 20 fields.
Everything is working pretty well. I have a PHP script that creates an xml response for ajax. The xml is of form
<response>
<field1>f1</field1>
<field1>f2</field1>
etc
</response>
My javascript is
$.ajax({
type : "POST",
url : "myscript.php",
data : $(this).serialize(),
success: function(xml){
$("#field1").val($("field1",xml).text());
$("#field2").val($("field2",xml).text());
}
})
Above works fine but I don't want to manually write out each form field assignment. I want to do it in a loop. So something like this in the success function:
var fields= xmlResponse.getElementsByTagName("response");
for (i = 0; i < fields.length; i++) {
// not sure what to put here...
}
In the for loop I have to index in to the node name and value so that I can simply have a statement that would be of this form: $("#"+fields[i].nodename).val($(fields[i].nodevalue,xml).text());
I tried
$("#" + fields[0].childNodes[i]).val(fields[0].childNodes[i].nodeValue);
But that did not return the values.
Any idea on how best to do this? I feel like I am very close to having this working! Thanks!
You can use $.parseXML, and then loop over the elements with .each().
var $xml = $.parseXML(xml);
$("#response", xml).children().each(function(i, e) {
var field = e.tagName;
var value = e.innerHTML;
$("#" + field).val(value);
});
You're on the right track. What it comes down to is that when you parse an XML file, the parser doesn't care what the fields are, it'll parse it as it sees it. You would basically have to tell the script to pull certain tags with certain text. As far as I know, this is best done using the .tagName property and the tag's value and storing it in an object.
var data={}
$(this).children().each(function() {
data[this.tagName]=$(this).text();
})
You can see how this would work here:
http://jsfiddle.net/dpK7x/1/

How to reload a page with javascript sending both GET and POST, and append additional parameter?

I have a page with an select box, which fires an onChange event. In this Java-Script snippet, I would like to reload the current page, including the GET and POST parameters that where sent during request. AFAIK, this can be achieved by using window.location.reload(), or window.location.href = window.location.href when sending POST data is not required.
However, I need to append an additional value (actually, the value of the select element), additionally to the previously sent element. I do not care whether the data is sent using POST or GET. Is there a way to achieve the desired behavior?
To accomplish this you are going to have to rebuild a request from scratch. In the case of get requests, the arguments are easily accessible in the query string but post requests are a little trickier. You will need to stash all that data in hidden input elements or something so that you can access it.
Then you can try something like this:
var queryString = windlow.location.search; //args from a previous get
var postArgs = $("#myPostArgsForm").serialize(); //args from a previous post... these need to be saved and added to the html by the server
//your additional data... this part you probably need to adapt
//to fit your specific needs. this is an example
var myNewArgName = encodeURIComponent("newArg");
var myNewArgVal = encodeURIComponent("Hello!");
var myNewArgString = myNewArgName + "=" + myNewArgVal;
//if there is no queryString, begin with ?
if(!queryString) {
queryString = "?"
}
//if there is, then we need an & before the next args
else {
myNewArgString = "&" + myNewArgString;
}
//add your new data
queryString += myNewArgString;
//add anything from a previous post
if(postArgs) {
queryString += "&" + postArgs;
}
window.location.href = window.location.hostname + window.location.pathname + querystring
<form id="myPostArgsForm">
<input type="hidden" name="prevQuery" value="whats up?" />
</form>
Pretty simple really; have onChange fire a function that uses getElementById to figure out the selector value and then just use window.location to send the browser to the literal: http://yourdomain.com/yourpage.html?selectval=123
then, in the body onload() method, fire another JS function that checks the "get var" like:
function (GetSelector) {
var TheSelectorWas = getUrlVars()["selectval"];
alert(TheSelectorWas);
}
and do whatever you need to do in that function (document.writes, etc). BTW, posting the actual code you're using is always a good idea.
-Arne

Iteratively obtaining different pages of a query using python

I am trying to parse a sequence of html pages using python, I am having trouble grabbing the pages in iterative fashion. The link to the web page.
Milano Library
After peeking through the source, I found a function that responds to the click event on button element for the next page.
function SaltaAPagina() {
var CalcPag = VAIAPAGINA.value;
if (CalcPag > 0) {
CalcPag=CalcPag;
}
else {
CalcPag="1";
}
document.location = "/OPACMI01/cat/SDW?W=CODICE_BIBLIO+%3D+%27LO1+01%27+AND+EDITORE+PH+WORDS+%27sonzogno%27+AND+DATA_PUBBLICAZIONE+%3C+1943+ORDER+BY+ORDINAMENTO/Ascend&M=" + CalcPag + "&R=Y";
}
I know that I can encode parameters using pythons urllib2 module using the urlencode method. But I am not sure what I should be including as a parameter
lomba_link='http://www.biblioteche.regione.lombardia.it/OPACMI01/cat/SDW?W%3DCODICE_BIBLIO+%3D+%27LO1+01%27+AND+EDITORE+PH+WORDS+%27sonzogno%27+AND+DATA_PUBBLICAZIONE+%3C+1943+ORDER+BY+ORDINAMENTO/Ascend%26M%3D1%26R%3DY'
params = urllib.urlencode([('CalcPag',4)])
# this has not worked.
req = urllib2.Request(lomba_link)
print req
response = urllib2.urlopen(req,params)
html_doc = response.read()
What am I missing here?
Thanks
The javascript function you posted is passing several parameters to the target page:
document.location = "/OPACMI01/cat/SDW" + // This is the path of the page
"?W=CODICE_BIBLIO+%3D+%27LO1+01%27+AND+EDITORE+PH+WORDS+%27sonzogno%27+AND+DATA_PUBBLICAZIONE+%3C+1943+ORDER+BY+ORDINAMENTO/Ascend" + // The first parameter
"&M=" + CalcPag + // The second parameter
"&R=Y"; // The third parameter
In your code, you've encoded all of the & and = symbols in the URL, so you're passing a single, long parameter with no value - changing those symbols back to what they were in the javascript function should do the trick.
lomba_link='http://www.biblioteche.regione.lombardia.it/OPACMI01/cat/SDW'
params = urllib.urlencode([
('W', 'CODICE_BIBLIO+%3D+%27LO1+01%27+AND+EDITORE+PH+WORDS+%27sonzogno%27+AND+DATA_PUBBLICAZIONE+%3C+1943+ORDER+BY+ORDINAMENTO/Ascend'),
('M', 4),
('R', 'Y')
])
It's much easier to work with the brilliant requests library, rather than the urllib2 library...
In regards to urllib2.urlopen the params is for POST requests. Unfortunately you need to append the query string to the url to make a GET request.
eg:
req = urllib2.urlopen(req + '?' + params)
With requests, this would be much simpler:
page = requests.get(some_url, params={'CalcPag': '4'})

Categories

Resources