Protecting against XSS with dynamically generated JavaScript - javascript

I have to pass a jQuery plugin some data. I could either pass it a URL where it will use a GET request to fetch the data, or directly pass it an array which will eliminate one server request. The data in question is user provided and not sanitized upon database entry.
The below script doesn't show the plugin, but does show how I might pass the data to the client so it may be directly passed to the plugin. As seen, the dynamically generated JS approach is suspect to XSS, however, the Ajax/JSON approach doesn't seem to be.
For this scenario, how should the dynamically generated JavaScript approach be secured, and is there risk to the Ajax/JSON approach?
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>XSS Testing</title>
<script src="getStuff.php?type=js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
console.log(stuff);
$.get( "getStuff.php", function( data ) {
console.log(data);
},'json');
});
</script>
</head>
<body>
</body>
</html>
getStuff.php
<?php
$getFromDB=array(
'Mary',
'x"];alert(\'xss2\');x=["x',
'John'
);
if(isset($_GET['type']) && $_GET['type']=='js') {
header('Content-Type: application/javascript;');
$s='var stuff=[';
foreach($getFromDB as $row) {
$s.='"'.$row.'",';
}
$s=substr($s, 0, -1).'];';
echo($s);
}
else {
header('Content-Type: application/json;');
echo(json_encode($getFromDB));
}
?>

if you expect to work with JSON, why not first and foremost verify that's what you're working with?
$.get(...)
.success(function(data) {
try {
JSON.parse(data)
} catch (e) {
console.error("this isn't actually JSON");
}
})
JSON cannot contain functions, nor function calls, so just asking the browser to see if it can be parsed should be enough to make it go "there is stuff in here that isn't real JSON data".
The same goes for your PHP of course. Never build a string if you need a specific serialization. In this case, construct your key/map object the usual PHP way, and then use the built in json_encode function for converting that to a legal JSON serialization, instead.

It's almost like you've designed your example to be susceptible to hacking. You're doing nothing in the "js" case to ensure that the data is output with proper escaping, you're only doing it in the "json" case.
If you're going to include a JavaScript file that's purely data, like this:
<script src="getStuff.php?type=js"></script>
Then getStuff.php needs to ensure what it sends back is properly escaped as data:
<?php
$getFromDB=array(
'Mary',
'x"];alert(\'xss2\');x=["x',
'John'
);
if(isset($_GET['type']) && $_GET['type']=='js') {
header('Content-Type: application/javascript');
echo('var data = ');
echo(json_encode($getFromDB));
echo(';');
}
else {
header('Content-Type: application/json');
echo(json_encode($getFromDB));
}
?>
And boom: No alert.
Side note: You shouldn't have the ; on the end of the Content-Type strings. I've removed them in the above.

Related

JavaScript EventSource listening for a Webhook pushed to PHP script

I've been searching and experimenting and I just can't seem to figure this out. I would appreciate any insight. Thank you!
So I have a Shopify store and I have an Webhook that triggers when I make a sale, meaning it pushes JSON data of that sale to a PHP script on my server. Right now I'm having that PHP script insert the relevant data into a database and mark that sale as "unread." Then, I would have a separate HTML/JavaScript page that I would run separately, polling the server to check for unread sales ever 10 seconds or so. There's a little more to that, but that's the general idea. It's clunky and I would like to modernize this.
Here's what I've been trying and can't seem to get working.
Set up an EventSource page that's listening to a separate PHP script.
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sales Notification!</title>
</head>
<body>
<div id="widget">
<div id="notification_box"></div>
</div>
<script type="text/javascript">
if (!!window.EventSource) {
var source = new EventSource('alert_listener.php');
} else {
console.log("Window.EventSource fail!");
}
source.addEventListener('message', function(e) {
console.log(e.data);
}, false);
source.addEventListener('open', function(e) {
// Connection was opened.
}, false);
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
// Connection was closed.
}
}, false);
</script>
</body>
</html>
That actually works well when I do something simple like this example. Anyway, here's my PHP code listening for the JSON sent from the Websocket (some of this code is provided by Shopify):
<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
error_reporting(0);
define('SHOPIFY_APP_SECRET', 'NOT_PUBLIC_HAR_HAR');
function verify_webhook($data, $hmac_header) {
$calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPIFY_APP_SECRET, true));
return ($hmac_header == $calculated_hmac);
}
function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
while (1) {
if ($data !== "") {
sendMsg("test id", "Data: " . $data);
}
sleep(1);
}
?>
When I push data from Shopify to this PHP script, the first JavaScript example is supposed to be listening for this data, but nothing happens. Not a thing. I have no idea why. I have no idea how to tell the PHP script to say, "Hey! An order came in! Yo JavaScript, do something!" and then the JavaScript go, "New order received! Let's do a thing!"
TLDR:
Shopify pushes JSON to a PHP script (via a webhook)
Separate JavaScript file listens to this PHP script via EventSource object and reacts accordingly
I can't get this to work. Please help.
That is all. Thank you.
I saw this on Twitter - and no, this can be answered.
First of I have to admit that I am not familiar all too well with EventSource - but from what I see, you are using exactly one script to do two things at once; obtaining the Shopify data and immediately exporting it to JS. However, each PHP script ran has exactly one request and response context - and in this case, you have been echo'ing your data all the way back to Shopify.
You will need two endpoints:
The first endpoint acts as the receipient to Shopify's webhooks (shopify_webhook.php). Each time it receives data, you might store it in a database for fire-and-forget actions like Redis, where you set a possibly low TTL. As far as I know, Redis also has queues - so this would probably be a better approach.
The second endpoint is your event source that keeps streaming incoming queue entries to your requesting JavaScript (i.e. shopify_eventsource.php).
Redis here is just a suggestion - but one way or another, you will have to use an intermediate storage to be able to move the incoming data to another output channel. You can write all this in one PHP file where you validate the incoming request to see if it is a Shopify request (and stream) or if it is your JavaScript code requesting the output. But using two endpoints and thus separating code might make it more readable and adjustable should Shopify change APIs or you your own JavaScript receipient.
TL;DR:
Shopify -> Your endpoint -> intermediate storage.
Intermediate storage -> your endpoint -(stream)> your javascript.

PHP Undefined POST variables and unable to execute INSERT function [duplicate]

I know there a fair few entries on SO and the web on this however I just can't get to work - any help would be appreciated.
So i have an array in Javascript which I'm trying to pass on to PHP.
I've got a little JS function to first POST it, so:
function sendToPHP() {
$.post("index.php", { "variable": toSearchArray });
}
Then down the page, I have the PHP:
<?php
$myval = $_POST['variable'];
print_r ($myval);
?>
*The prints just there for me to check.
Any ideas - fyi I'm using MAMP so its localhost:8888/index.php. Could this be causing issues in that the URL is not correct?
Thanks.
You have a misunderstanding about how ajax works. Although jquery makes it easy, it is still not automatic. You should just find a tutorial about ajax with jquery, but if you want to just send an array to php and see the output on screen, something like this would work:
index.php
<html>
<head>
<title>Test</title>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
//attach to the button a click event
$('#btn').click(function(){
//get the value from the textbox
var txt=$('#txt').val();
//if txt is blank, alert an error
if(txt == ''){
alert("Enter some text");
} else {
//send txt to the server
//notice the function at the end. this gets called after the data has been sent
$.post('catcher.php', {'text':txt}, function(data){
//now data is an object, so put the message in the div
$('#response').text(data.message);
}, 'json');
}
});
});
</script>
</head>
<body>
<input type="text" id="txt">
<input type="button" id="btn">
<pre id="response" style="overflow:auto;width:800px;height:600px;margin:0 auto;border:1px solid black;"> </pre>
</body>
</html>
catcher.php:
<?php
//if something was posted
if(!empty($_POST)){
//start an output var
$output = array();
//do any processing here.
$output['message'] = "Success!";
//send the output back to the client
echo json_encode($output);
}
It is better to use 2 files, one for the user to load that initiates the ajax call and one page to handle the ajax call. Sending an array works the same, just replace getting the textbox value with sending an array.
Instead of declaring variable toSearchArray as array. consider it an javascript object.
var toSearchArray = {}.
This is what happens when you open your page (index.php)
A GET request is issued to index.php and the content is returned. There are no values in the $_POST array so your print_r() line does nothing.
Javascript is executed that sends a POST request to index.php via AJAX. Note that this is an entirely new request, separate to the original GET. The $_POST array will be populated on this request however the response is discarded.
Hopefully this will illustrate what you can do.
ajax.php
<?php
header("content-type: application/json");
exit(json_encode($_POST));
index.php
<script>
const toSearchArray = ['some', 'array', 'with', 'values'];
$.post('ajax.php', {
variable: toSearchArray
}).done(data => {
console.log(data) // here you will see the result of the ajax.php script
})
</script>
Well I don't think thats the right way to do it when it comes to arrays, see you need to use JSON encode in javascript then JSON decode in php
Refer to this question Pass Javascript Array -> PHP

How to call php function from JavaScript using Ajax?

In my Wordpress site, I want to create a dropdown menu with all the tags, but since it has more then 7.000, it needs to load only after the user click. I now it is only possible using Ajax, and I have started, but not accomplished yet.
http://jsfiddle.net/7kf1r9vw/2/
In this Fiddle, after the click, this javascript file is loaded:
/echo/js/?js=hello%20world!.
The second example in Fiddle is just to show my actual code. I want that the results populated by the php funcion only starts after the user click.
But I don't know how to change it to a PHP function. Also, is it possible to add plain PHP script in the output or only with it embedded in a file?
As Draco18s said, in your case, Javascript is executed client-side and PHP is executed server side.
In this case what you can do is a request to the server using Ajax.
For example, if you have the following html:
<select name="tag-dropdown" id="selectTags">
<option value="#">Select an artist</option>
</select>
You can use Ajax to make a POST request to a PHP script:
$( document ).ready(function() {
$.ajax({ url: 'merge2.php',
data: {operationName: "tagsNames"},
type: 'post',
success: function(output) {
tagNamesres = JSON.parse(output);
jQuery.each(tagNamesres, function(name, val) {
$("#selectTags").append('<option value="'+val+'">'+name+'</option>');
});
}
});
});
The PHP script can contain something like:
<?php
if (isset($_POST['operationName']) && !empty($_POST['operationName']) && $_POST["operationName"]=="tagsNames") {
$resultarray = array();
$resultarray["tagName1"] = "tagValue";
$resultarray["tagName2"] = "tagValue2";
echo json_encode($resultarray);
return;
}
?>
In order to return something from the PHP function you need to print or use echo.
This is just an example so you could start working with this :)
For more information about how Ajax request works, read this http://thisinterestsme.com/simple-ajax-request-example-jquery-php/
Your question appears to be "how do I call a php function on the server from my browser javascript code". In your code, you have the following function where the first parameter is the server side request:
function getSuccessOutput() {
getRequest(
'/echo/js/?js=hello%20world!', // demo-only URL
drawOutput,
);
return false;
}
To change that to call a server php routine, you would change '/echo/js/?js=hello%20world!' to the url on your server you want to have executed: e.g. '/myPHPFolder/someRoutine.php' . The results will be delivered back to your req object.
In your initial html file (e.g. index.html, or where ever you start your flow), include the onload option on the body tag:
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="yada yada yada">
<meta name="author" content="you">
<title>title for browser tab</title>
</head>
<body class="tutorial" onLoad="initPage()">
<select id="optionList"></select>
</body>
</html>
This tells the browser to run the "initPage()" function with no parameters. The initPage() function then issues an async call and loads up your data, perhaps saving it to a local variable in the process.
function initPage()
{
$('#optionList').empty(); // this ensures that you don't duplicate the info in the select list.
$.when($.get('/myPHPFolder/someRoutine.php').done(function(res)
{ // if of interest, save the results to a cookie or variable.
// you could also include a check to see if the data has already been downloaded.
// This is a 'happy path' example, which does not include error checking from the host
// build the optionList select HTML element
for (let each in res)
{(function(_idx, _arr)
{
// append the correct value to the select list.
// this example is based on returning a JSON object with an
// element called "id" which has the value I want to display in the options list
$('#optionList').append('<option value="'+_arr[_idx].id+'">' +_arr[_idx].id+'</option>');})(each, res);
}
// create a function to execute when the user selects a different buyer
$('#buyer').on('change', function() { /* do something useful here */ });
}
}

How to pass data from JavaScript to PHP and then on to MySQL [duplicate]

This question already has answers here:
How do I pass JavaScript variables to PHP?
(16 answers)
Closed 2 years ago.
How do I pass have a Javascript script request a PHP page and pass data to it? How do I then have the PHP script pass data back to the Javascript script?
client.js:
data = {tohex: 4919, sum: [1, 3, 5]};
// how would this script pass data to server.php and access the response?
server.php:
$tohex = ... ; // How would this be set to data.tohex?
$sum = ...; // How would this be set to data.sum?
// How would this be sent to client.js?
array(base_convert($tohex, 16), array_sum($sum))
Passing data from PHP is easy, you can generate JavaScript with it. The other way is a bit harder - you have to invoke the PHP script by a Javascript request.
An example (using traditional event registration model for simplicity):
<!-- headers etc. omitted -->
<script>
function callPHP(params) {
var httpc = new XMLHttpRequest(); // simplified for clarity
var url = "get_data.php";
httpc.open("POST", url, true); // sending as POST
httpc.onreadystatechange = function() { //Call a function when the state changes.
if(httpc.readyState == 4 && httpc.status == 200) { // complete and no errors
alert(httpc.responseText); // some processing here, or whatever you want to do with the response
}
};
httpc.send(params);
}
</script>
call PHP script
<!-- rest of document omitted -->
Whatever get_data.php produces, that will appear in httpc.responseText. Error handling, event registration and cross-browser XMLHttpRequest compatibility are left as simple exercises to the reader ;)
See also Mozilla's documentation for further examples
I run into a similar issue the other day. Say, I want to pass data from client side to server and write the data into a log file. Here is my solution:
My simple client side code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
<title>Test Page</title>
<script>
function passVal(){
var data = {
fn: "filename",
str: "this_is_a_dummy_test_string"
};
$.post("test.php", data);
}
passVal();
</script>
</head>
<body>
</body>
</html>
And php code on server side:
<?php
$fn = $_POST['fn'];
$str = $_POST['str'];
$file = fopen("/opt/lampp/htdocs/passVal/".$fn.".record","w");
echo fwrite($file,$str);
fclose($file);
?>
Hope this works for you and future readers!
I'd use JSON as the format and Ajax (really XMLHttpRequest) as the client->server mechanism.
Using cookies is a easy way. You can use jquery and a pluging as jquery.cookie or create your own.
Using Jquery + jquery.cookie, by example
<script>
var php_value = '<?php echo $php_variable; ?>';
var infobar_active = $.cookie('php_value');
var infobar_alert = any_process(infobar_active);
//set a cookie to readit via php
$.cookie('infobar_alerta', infobar_alerta );
</script>
<?php
var js_value = code to read a cookie
?>
I've found this usefull Server-Side and Hybrid Frameworks:
http://www.phplivex.com/
http://www.ashleyit.com/rs/
I've been using Ashley's RSJS Script to update values in HTML without any problem for a long time until I met JQuery (ajax, load, etc.)
There's a few ways, the most prominent being getting form data, or getting the query string. Here's one method using JavaScript. When you click on a link it will call the _vals('mytarget', 'theval') which will submit the form data. When your page posts back you can check if this form data has been set and then retrieve it from the form values.
<script language="javascript" type="text/javascript">
function _vals(target, value){
form1.all("target").value=target;
form1.all("value").value=value;
form1.submit();
}
</script>
Alternatively you can get it via the query string. PHP has your _GET and _SET global functions to achieve this making it much easier.
I'm sure there's probably more methods which are better, but these are just a few that spring to mind.
EDIT: Building on this from what others have said using the above method you would have an anchor tag like
<a onclick="_vals('name', 'val')" href="#">My Link</a>
And then in your PHP you can get form data using
$val = $_POST['value'];
So when you click on the link which uses JavaScript it will post form data and when the page posts back from this click you can then retrieve it from the PHP.
You can pass data from PHP to javascript but the only way to get data from javascript to PHP is via AJAX.
The reason for that is you can build a valid javascript through PHP but to get data to PHP you will need to get PHP running again, and since PHP only runs to process the output, you will need a page reload or an asynchronous query.
the other way to exchange data from php to javascript or vice versa is by using cookies, you can save cookies in php and read by your javascript, for this you don't have to use forms or ajax

Parsing Json data in JQuery/Javascript

I saw a similar discussion here. But my returned data format is a bit different.
I have a Json string returned from server as shown below
<!DOCTYPE HTML>
<html>
<head>
<style>
</style>
</head>
<body>
{"error":false}</body>
</html>
I need to extract data "error":false from the Json string.
I tried as below
(1)Say the Json message is in result variable, then I checked as
if(result.error == false)
It doesn't work.
(2) I also used jQuery.parseJSON as discussed in this link.
It doesn't work also.
How can I parse Json data?
Json data is parsed in Jquery.ajax for the returned message as follow
jQuery.ajax({
url: "registrationdatavalidationatserver.php",
type: "POST",
data: $("form").serialize(), /*grab all elements in your form and serialize them */
success: function(result){
//To parse result
},
error: function(){
// the AJAX request failed as in timed out / bad url etc.
}
});
(3) How to return message from server just Json data without
<html>, <head>, <style>, etc. tags?
I returned from server as echo json_encode($data);
I have a Json string returned from server as shown below.
No, you need to have only the following returned from the server:
{"error": false}
Say the Json message is in result variable, then I checked as if(result.error == false)
It will never work because it is a HTML. Not a JSON.
How to return message from server just Json data without <html>, <head>
Even before you send the output, please make sure you are not sending anything to browser. Have these defined in the PHP headers:
<?php
header("Content-type: application/json");
die(json_encode($arrayData));
?>
There must not be anything other than this. It is wise to have a dedicated file for JSON output too, if you are confused in making this kind of setup.

Categories

Resources