Security issues with reading a JS array? - javascript

I'm building a website that will have a JS multi-dimensional array in a .js file in the scripts folder on the server. In the array will be video embed codes (Vimeo iframes) and additional strings for composers, players and piece names. There will about 1000 videos in the array.
var videos = [ ['embed code', 'composer name', 'player name', 'piece name'], ['embed code', 'composer name', 'player name', 'piece name']...];
There will be a search text box for users to do specific searches by composer, player, etc. A jQuery script will iterate through each inner array to find matches to the user's query and present them on the page. It will look basically like this:
function getArray(video) {
if (campyear === video[j]) {
var pos = video.indexOf(video[j]);
$('#searcharea').append('<td>' + video[(pos - pos)] + '</td><td><h3>Composer: ' + video[(pos -pos) + 1] + '</h3><br><h3>Player: ' + video[(pos - pos) + 2] + '</h3><br><h3>Piece: ' + video[(pos - pos) + 3] + '</h3></td>');
}
else
noResultCount++;
if (campyear === video[j] && count % 2 === 0)
$('#searcharea').append('</tr><tr>');
if (campyear === video[j])
count++;
if (i === videos.lenght && j === 4)
$('#searcharea').append('</table>');
if (noResultCount === videos.length * 5)
$('#searcharea').html("<h4>No results found for " + yearvalue + " " + buttonvalue + ". Not all camps have videos for every year.</h4>");
$('#searcharea').fadeIn(500);
} // End of getArray()
...
...
...
for (i = 0; i < videos.length; i++) {
for (j = 0; j < 5; j++) {
getArray(videos[i]);
}
}
I know there are security issues with the traditional SQL databases and PHP that need to be considered, but in this case should I be concerned about any threats to the data or website? My thought was the script can only read the data and print it so there wasn't much someone could do, but I'm not sure. The data isn't sensitive.
Thanks for your time.

The issue is that if someone can alter the file before it gets read in, they can inject any JavaScript code into it. One way to alter the file would be to hack your server, but they could also do it by taking over proxies that don't have to touch your machine at all. They they would have to somehow trick clients into going through the proxy, but you can't stop that from happening.
The easiest fix for this is to use a JSON file instead of a JavaScript file. JSON's syntax is very close to the syntax used for JS literals: as far as I can see from your example, the only changes you'd need to make to the file are to get rid of the "var videos =" at the start and swap your single-quotes for double-quotes. In code, exchange whatever works to this effect:
// Assume that getJS() grabs your JavaScript file
// and returns a String with the text of that file.
var videoCode = getJS();
eval(videoCode);
...for something that works like this:
// Assume that getJSONData() grabs your JSON
// and returns a String with the text of the file.
jsonData = getJSONData();
var videos = JSON.parse(jsonData);
Note that we're using JSON.parse (which has polyfills for old browsers) instead of eval. We do this because that puts the code through a dedicated JSON parser instead of a JavaScript one. JSON doesn't know how to deal with code, so even if an attacker tries to inject code by changing the file, the changed code won't work, because JSON won't know what to do with it. Obviously you don't want your app to just stop in the middle, but it's better than letting the attacker take over.

Related

Sanitizing user input when creating HTML elements

I am trying to make a to-do application in pure HTML5 and Javascript and I have come across the problem of sanitizing the input.
For eg: If user enters <script>alert("XSS")</script>, the code is executed on the page.
Code for adding an element is:
if ($('#TextArea').val() !== "") {
var taskID = new Date().getTime();
var taskMessage = $('#textArea').val();
localStorage.setItem(taskID, taskMessage);
}
while the code for displaying the elements is:
var i = 0;
for (i = localStorage.length; i != 0; i--) {
var taskID = localStorage.key(i - 1);
$('#task').append("<li id='" + taskID + "'>" + localStorage.getItem(taskID) + "</li>");
}
Is there any way to sanitize the data using only HTML5 and Javascript properties?
As with any and all XSS prevention: Don't build HTML from strings, especially not when those strings contain user-supplied values.
jQuery has a convenient facility to build elements safely - you can pass in an object with properties:
$("<li>", {
id: taskID,
text: localStorage.getItem(taskID)
}).appendTo('#task');
In fact, I recommend that you absolutely never use string concatenation to build HTML. For more complex situations than the above, use a well-tested HTML templating library like Mustache or Handlebars.

Dynamically define variable name and assigning value in Google Apps Script

I`m writing a script to generate a form in Google Apps Script.
The idea is, that the user should select his/her name from a dropdown list, and then be transferred to the question block for him/her.
Although the questions are the same, there are slight changes in the choices if the dropdowns for some of the questions.
I have an array with the names of the users, and I've defined the questions for every single user.
This is not ideal, as if there is any change in the questions I have to rewrite every block oone by one.
I want to use a loop which generates the question blocks by creating the variables names using the array of the usernames.
I tried the following (this is not the actual code, but throws the same error)
for (a=0; a < 10; a++)
{
eval('var beginning'+a);
}
for (b=0;b<10; b++)
{
eval('beginning' + b) = 1;
}
The first for loop runs fine, but when I try to assign any value it throws an error. (I use here two for loops for debugging only.)
E.g.:
eval('beginning' + b) = 1; //Throws: We're sorry, a server error occurred. Please wait a bit and try again.
eval('beginning' + b + '= 1;'); //Throws: We're sorry, a server error occurred. Please wait a bit and try again.
eval('beginning' + b = 1); //Throws: Invalid assignment left hand side. (line 1, file "Code")
Using eval like this is also fine: choices = eval('lCountries' + Names[i]).getChoices();.
How can I assign values to these variables in a for loop?
Thank you very much in advance.
As far as I read up so far, eval() is almost always a bad choice, should be handled with caution and mostly never used. Using dynamic variables in such way is also a bad programming logic. I've never seen a case where it is a must, and your case obviously isn't. You can easily get around it with an object, just define a generic object var myVariables = {}, and then start assigning its properties dynamically for your variables.
var myVariables = {};
myVariables[ "beginning" ] = 1;
for( i = 0; i < 10; i++){
myVariables[ ("beginning" + i) ] = i;
}
Logger.log( myVariable[ "beginning5" ] ); //Loggs 5

An efficient way to store and manipulate my variables in Javascript, using Objects?

I have a program which involves taking some user imputed values on a web page. These values are then sent out via a serial port to some control electronics.
There are six different "zones" and these have 6 values associated with each of them which are all set on the page by the user and read and stored by javascript.
I had been using 6 arrays to store the data but I would like to now use objects as I think this will make the code more readable when I refer to and manipulate the data elsewhere on the page.
This gives me 6 objects with 6 properties each, so I have for example zone1.duration - zone1.repeat .... zone6.op
So is this a good and efficient way to store the values? Also I do need to harvest the data from the web page to start with and interpret it for other functions associated with the web page. Before I did this in a simple loop cycling through the different zones and I am not sure how to do this with the objects.
The code below illustrates what I would like to do to get the values loaded from the web page, the document.getElementById part does work as I used that before but I don't know the proper syntax to cycle through the different zones and assign the properties. I have shown my poor attempt on the first line only.
for (i = 1; i < 7; i++){
('zone'+ i )["op"] = document.getElementById('Z' + i + 'Operate').value;
zone1["onHour"] = document.getElementById('Z' + i + 'OnTimeH').value;
zone1["onMinute"] = document.getElementById('Z' + i + 'OnTimeM').value;
zone1["duration"] = document.getElementById('Z' + i + 'Duration').value;
zone1["repeat"] = document.getElementById('Z' + i + 'Repeat').value;
zone1["ex"] = document.getElementById('Z' + i + 'Extra').value;
}
Hopefully this provides an idea of what I am trying to achieve. My questions are: Is this a good way to do it in the first place and if so what to I need to alter to get the above code to work. If not what would be a better way?
Thanks for looking.
I think you're looking for an array of objects. For example:
var zones = [,{},{},{},{},{},{}]; // leading comma indicates element 0 not used.
for (i = 1; i < 7; i++){
zones[i].op = document.getElementById('Z' + i + 'Operate').value;
zones[i].onHour = document.getElementById('Z' + i + 'OnTimeH').value;
// etc
}

example of javascript's eval not being evil?

I read some stackOverflow questions and answers more then ten times per day, and... it looks its first time i feel its okey to post something, as i didnt find accurate enought answer.
Im writing some code in nodeJS. Its web interface for big softswitch based on custom asterisk, where in one place i need to get data from post message from website.
The problem is, that that post message containts numerous info named in fashion:
peer1
peer2
peer3
peer4 etc
Instead of dealing with every single one, i did a loop:
var array = [];
var i = 0;
while (typeof eval("req.body.peer" + i) !== 'undefined' && eval("req.body.peer" + i) !== '') {
console.log('petla wisielca');
//console.log(eval("req.body.peer" + i));
array.push(eval('req.body.peer' + i));
i++;
}
Number filled inputs (actually its html select) is variable.
After creating that array, I deal with rest of things (write peers to file etc) in traditional, non-eval loops.
Am i missing something here, or it's proper way of dealing with such situation?
Thanks in advance!
EDIT:
Looks like i had some kind brain malfunction :).
Solution is very easy,
as kyle cleared it out, to access object variables and for example iterate, all is needed is to use [].
Solution:
var array = []
var i = 0
while (req.body['peer' + i]) {
array.push(req.body['peer' + i])
i++
}
Thanks once more Kyle.
JavaScript objects can be accessed like they're associative arrays:
var array = []
var i = 0
while (req.body['peer' + i]) {
array.push(req.body['peer' + i])
i++
}
Use of eval is ever evitable, i wrote a plugin that make some dynamic calls of functions, you can check how you can access the object without using eval:
https://github.com/HaSuKrOnOs/jquery-dynFn

Is there better way reading values form url in JavaScript

I came across old web application which has the code to read the parameters from the URL of the site. The code is full of string processing.
http://hostname.domain[port number]/application name?arg1=value1...&argN=valueN
Considering that URL parameters are always encoded it is litter difficult to rely on string processing. Also not sure if one can rely 100% on the URLEncode/Decode functions of the JavaScript.
function getURLParameters(){
if (location.search != "")
{
var x = location.search.substr(1).split(";")
for (var i=0; i<x.length; i++)
{
var y = x[i].split("=");
alert("Key '" + y[0] + "' has the content '" + y[1]+"'")
}
}
}
Now that made me think if there is any better way we can read values from URL ? OR should we go ahead and change the approach itself by sending values using POST/dumping JSON object on cliente ? Please help me with this.
I found this little query string plugin that seems to do the job
The example:
http://terenz.io/?test=yes&javascript&something=1
$.getQueryParam("test") returns "yes"
$.getQueryParam("javascript") returns ""
$.getQueryParam("something") returns "1"
$.getQueryParam("somethingelse") returns undefined

Categories