Is it safe to do this? PHP's json_encode and javascript - javascript

I've been searching around for security concerns about using PHP json_encode inside javascript context but I'm not exactly satisfied with the results
I got a lot of warnings about doing this but they always assume that I was going to inject data from the json_encode object directly to HTML without any type of sanitizing at all
So, I want to know if this and only this little snippet presents any security issues (like xss attacks etc)
<?php
$obj = isset($_POST['js']) ? json_encode($_POST['js']) : false;
if ($obj === false) $obj = '{}';
?>
<script>var x = <?php echo $obj ?>;</script>
EDIT:
Changed the snippet to handle json_encode returning false

With that line of code
var x = <?php echo $obj ?>;
...the server application echoes back the data that was submitted to it via the "js" key. It will be client that sent it that will receive it, so if in some way it is malicious, it will be that same client dealing with the consequences.
The actual sending to the server is in fact the irrelevant part of the chain: if one has the data to submit, one can also assign it to the variable x directly without the server's interference (e.g. through browser's dev tools).
It would be a different story if in PHP you would use the data to manipulate a server database, call a service, or otherwise change the application's state, and you would not first validate that data.
As to the use of json_encode: if indeed you verify that the argument is valid JSON (by checking that the return value is not false), it will produce a valid JavaScript object literal. The known cases of incompatibility (characters U+2028 and U+2029) will not occur, as by default json_encode escapes these characters.

It is correct as per coding. However you have to validate the variable x should not be empty or the posted value.
<script>var x = "<?php if(isset($_POST['js']))
{
echo json_encode($_POST["js"]);
}";
</script>

Sometimes json_encode returns false, if return it that js expression will broke. this will works safer.
<script>var x = JSON.parse(<?php echo (json_encode($_POST["js"]) ? json_encode($_POST["js"]) : '{}'));</script>
if json_encode returns false, var x will get just empty object.

Related

jQuery $.post returns arrow with variable

The image below shows a debugging of a function in Chrome DevTools:
I realized that the data returned from the PHP file always has an arrow before the string as seen in the above. What causes this?
This poses a big issue for me. For example when comparing the string. Whenever I use
if(data == "success")
the statement in that block won't run because it would be false. The code I use in the PHP file is:
echo 'success';
That value is coming from the server. You need to fix the the code there so that it generates the correct response. It's likely you have some line breaks at the beginning of the PHP file you're calling which should be removed.
That said, you can trim whitespace from the response in JS:
if (data.trim() == 'success')
I would also suggest you amend your server code so that you return something other than plain text, because, as you've seen, text can easily be affected by whitespace.
Try returning JSON instead. You can then use a boolean flag in the response and avoid the rather ugly comparison to an arbitrary string.
Use trim() function
if (data.trim() === 'success')
Side note: Make habit of using === where possible
from API side, if accessible then check your return value
Instead of returning a string you may want to return a JSON object.
That will help you because like Rory said you can use booleans and also return multiple variables to your page. Accessing a JSON object with JS is easy.
In order to do that simply create a PHP array, add the data you want in it. Then when you want to return the array use json_encode() to return a JSON representation of your array.
PHP code (AJAX target file)
$return = array(
'status' => true
);
echo json_encode($return);
JS (callback function)
if(response.status) {
console.log('success')
}

PHP - file_get_contents get JSON with regex, but can't JSON decode (got JSON_ERROR_SYNTAX)

I try to parse this page : http://fr.hearthhead.com/cards to get the hearthstoneCards JS variable.
So i do something like this :
$url = 'http://fr.hearthhead.com/cards';
$content = file_get_contents($url);
preg_match('#var hearthstoneCards = (.*)}]\;#Us', $content, $out);
$out = $out[1].'}]';
$tab_id_card = json_decode($out,true);
I try every tricks i could find (trim, stripslashes, preg for BOM and other things, put flags on json_decode and many other things), but i didn't get this working.
If i file_put_contents the $out var and compare to the real source it's the same thing (same length). If i put the string on a JS console, i get the data. But PHP don't want to parse this var :(
Some one got an idea ? :)
The problem is that you assume that code is JSON, when it's really full-fledged JavaScript. Within that code, many unquoted repetitions of the property name popularity occur, which is fine JavaScript but invalid JSON.
I tried to build a regex to fix any unquoted property names. Problem is, it's infeasible. In my case, any colons inside values broke my regex.
Short of writing a parser to fix such nonconformities or invoking a JS interpreter (which would require an external dependency such as V8Js), I think you'll be fine with fixing this specific scenario for now:
$url = 'http://fr.hearthhead.com/cards';
$content = file_get_contents($url);
preg_match('#var hearthstoneCards = (.*)}]\;#Us', $content, $out);
$out = str_replace('popularity', '"popularity"', $out);
$out = $out[1].'}]';
$tab_id_card = json_decode($out,true);
If you worry about future introduction of new unquoted properties, you can check $tab_id_card for NULL and either log the error somewhere you routinely check or even go as far as somehow firing a notification for yourself. Although I'd do it, I'd say it's not a likely scenario, due to all the other properties being correctly quoted.

How to obfuscate JavaScript on the server side?

I have a script I want to obfuscate or encrypt to hide from competition viewing the source code. I have found simple JS obfuscators but the issue with my script is I have PHP echoing variables into the JavaScript. The PHP is echoing strings and true/false.
Here is a piece of the JavaScript with PHP in it.
function redirect() {
var r = <?php echo $rvar; ?>;
if (r) {
window.location = prepare("<?php echo $redirect; ?>");
}
}
Can someone tell me what I can do to hide my JavaScript but be able to dynamically build the JS with PHP?
The only time I have ever wanted to obfuscate code is when I have been utterly ashamed of it. Retrospectively, I would probably obfuscate everything I have ever written. If protecting source is integral to your well-being, consider a shift to desktop programming.
Nevertheless, if there is one thing experience and memory has afforded me, it is that any serious newcomer to this field will stubbornly move forward with their own ideas, regardless of how bad it is, how much it grinds against commonsense and best practice, or how much a thread poo-poos all over the question. If you keep at it, hindsight will generously remind you of this period--cringes and all; the chastisements of a few strangers will pale in comparison, so I will give you one possible answer.
Use PHP's output buffering controls. You will want to start output buffering at the top of the script that will output all the JavaScript. This will capture everything into the buffer, which can then be assigned to a simple variable. This variable will contain everything that was supposed to be echoed out to the page immediately, but was instead captured and saved into the variable. This variable is just a regular string. Pass it to one of those JS obfuscators you found. This assumes it is done with PHP and is a PHP library for doing that. When it is obfuscated, echo it out. That is it. Here is an example:
<?php
// Start output buffering.
ob_start();
?>
function redirect() {
var r = <?php echo $rvar; ?>;
if (r) {
window.location = prepare("<?php echo $redirect; ?>");
}
}
<?php
// Get all the output captured in the buffer, and turn off output buffering.
// This will be a string.
$js_source = ob_get_flush();
// Obfuscate the $js_source string, by passing it to the obfuscator
// library you found.
$obfuscated_js_source = obfuscator5000($js_source);
// Send the source code to the browser by echoing it out.
echo $obfuscated_js_source;

PHP - Unable to send JSON correctly

I'm not sure why this isn't working, as a lot of the examples on the internet suggest doing it this way. Anyway, I have a SQL result that I've converted to JSON and now I'm trying to use that with Javascript.
json_encode($test, true); ?>
<script type="text/javascript">
var obj = (<?php echo $test; ?>);
alert(obj.toSource());
</script>
This does not work and Chrome gives me an error of "illegal character" and the Javascript variable somehow displays some x-debug HTML from the PHP server:
If I simple echo the JSON out to display on the webpage that works fine without any errors. What am I doing wrong?
Do it like this:
$test = json_encode($test, true);
json_encode doesn't change the variable in place.
You're doing a couple of things wrong here..
json_encode($test, true);
I think you're probably thinking of json_decode, but the second parameter to json_encode is supposed to be a bitmask of options. Passing true here is probably wrong.
#ElmoVanKielmo is also correct, the variable doesn't change because you call a function, you must reassign the variable to the return value.
You got hmtl that looks line an xdebug error/notice message. Fix that before you proceed! (You cut out the part where the message is put).
Additionally you do not encode $test correctly. json_encode returns the changed value and does not modify it by reference.

Passing JSON directly to Javascript without JSON.parse()

I noticed that many people are passing objects from PHP to Javascript as JSON like this:
var obj=JSON.parse('<?php echo json_encode($obj) ?>');
or
var obj=jQuery.parseJSON('<?php echo json_encode($obj) ?>');
Why don't people pass JSON directly like this?
var obj=<?php echo json_encode($obj) ?>;
This works fine with the few objects that I tried. Are there cases when this won't work?
passing objects from PHP to Javascript as JSON like this:
var obj=JSON.parse('<?php echo json_encode($obj) ?>');
Ouch! You're right, this is overcomplicated. Also, it actually has serious problems with apostrophes and backslashes in the JSON string, which are not escaped and destroy the string literal.
Why don't people pass JSON directly?
People who do it properly do it this way indeed.
Are there cases when this won't work?
Yes. There are unicode characters that are valid in pure JSON, but a syntax error in JavaScript - see http://timelessrepo.com/json-isnt-a-javascript-subset for details. However, json_encode would output these as escape sequences anyway.
Generally, you'd use JSON parsers to secure situations where the code returned may be erroneous (instead of crashing your script, it will simply throw an exception and keep going). This is generally a good idea when the JSON is sent from a source you don't have control over. It seems unnecessary when you're in control of both ends (PHP server and JS client).
That said, a "safer" method just for server side would be:
<?php $json_encoded = json_encode ($obj); ?>
var obj=<?php echo ($json_encoded ? $json_encoded : 'null'); ?>;
This makes sure only a valid object is passed into JavaScript.
More info: https://api.jquery.com/jQuery.parseJSON/

Categories

Resources