How to obfuscate JavaScript on the server side? - javascript

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;

Related

Is it safe to do this? PHP's json_encode and 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.

Most efficient way to pass PHP variables to external JavaScript (or jQuery) file

I've read several posts about the question and found this to be the simplest solution, here is my code:
js inside PHP code
<script>
<!--//
var jsBaseurl = <?php echo json_encode(BASE_URL."/"); ?>;
var jsTitle = <?php echo json_encode($h1_title); ?>;
var jsSubtl = <?php echo json_encode($h2_title);?>;
//-->
</script>
<script src="external.js"></script>
and the external.js
var siteURL=jsBaseurl;
alert(siteURL+jsTitle+jsSubtl)
it works fine, my question is regarding to the following comments by Pang and biplav:
WARNING: This can kill your website. Example:
<?php $myVarValue = '<!--<script>'; ?>
See this question for details. Solution: Use
JSON_HEX_TAG to escape < and > (requires PHP 5.3.0). - Pang
Another downside of this is that impacts the inital page load time. -
biplav
I would like to know a simple solution for Pang's comment and how this all impacts the performance (page load time). Thanks a lot!
About question 1: use JSON_HEX_TAG in json_encode()
Example 1
Consider this simple piece of code.
<script>
<?php $myVarValue = 'hello world'; ?>
var myvar = <?php echo json_encode($myVarValue); ?>;
alert(myvar);
</script>
Output:
<script>
var myvar = "hello world";
alert(myvar);
</script>
It alerts hello world. Good.
Example 2
Let's try having </script> as the string.
<script>
<?php $myVarValue = '</script>'; ?>
var myvar = <?php echo json_encode($myVarValue); ?>;
alert(myvar);
</script>
Output:
<script>
var myvar = "<\/script>";
alert(myvar);
</script>
It alerts </script>. Good.
As you can see, the slash (/) is correctly escaped as \/,
Example 3
Now, consider this very special string: <!--<script>
<script>
<?php $myVarValue = '<!--<script>'; ?>
var myvar = <?php echo json_encode($myVarValue); ?>;
alert(myvar);
</script>
Output:
<script>
var myvar = "<!--<script>";
alert(myvar);
</script>
Surprisingly, it does not alert anything, and there's nothing in the error console. What?!
If you check JSON's spec, none of the characters in <!--<script> need to be escaped, so what went wrong?
Image adapted from json.org
For a complete and well explained answer, read this amazing Q & A. In short, it turns out that having
<!--<script> in a <script> block confuses the HTML parser. PHP actually did its job correctly in json_encode();
you just can't have a <!--<script> there, even though it is a perfectly valid JavaScript string!
I did a few simple tests myself. The browsers actually ignore everything after <!--<script>, so if it happens in the middle of a page,
the entire second half of the page is gone! I'm not sure if someone can actually inject something malicious there to, say, execute arbitrary
code, but that's bad enough.
Also,
If you have not just a string in $myVarValue, but a complex object like array("key" => array("one", "and<!--<script>two", 3)), which includes <!--<script>, it's still bad.
If you have a plain HTML file (i.e. no PHP) and you have <!--<script> anywhere (even in a JavaScript comment) in your <script> block, it's also bad.
If you are using other, non-PHP, server-side programming languages, and produced <!--<script>, it's bad too.
If your PHP is outputting JavaScript directly (Content-type: application/javascript), it's actually ok [1].
The solution? Use JSON_HEX_TAG to escape < and > (requires PHP 5.3.0).
<script>
<?php $myVarValue = '<!--<script>'; ?>
var myvar = <?php echo json_encode($myVarValue, JSON_HEX_TAG); ?>;
// ^^^^^^^^^^^^^^
alert(myvar);
</script>
Output:
<script>
var myvar = "\u003C!--\u003Cscript\u003E";
alert(myvar);
</script>
It alerts <!--<script>. Hurray!
It works because there's no more <!--<script> in the output, so no more HTML parsing problems.
Note: you don't need JSON_HEX_TAG if you're not printing into a <script> block.
[1] Here, "ok" merely means it is free from the <!--<script> issue. Dynamically generating external JavaScript files is not recommended as it has tons of disadvantages, such as those stated here, here, here.
About question 2: initial page load time
Actually, it's rather obvious. If the time needed to obtain the value of $myVarValue is long
(e.g. you're fetching lots of data from DB), PHP will have to wait, so is the browser, and the user.
That means longer initial page load time. If you load the data later with Ajax instead, they won't have
to wait to see the initial result, but then, the Ajax call would be an extra HTTP request, so it
means more workload to the server, and more load to the network.
Of course, each method has its pros and cons, so you have to decide. I suggest reading this excellent Q & A.
Pretty sure that won't break it. The whole point of json_encode is that it's safe to dump.
</script> might break it, but PHP escapes / as \/ by default so you shouldn't have to worry about it.

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/

How to improve readability? (pass php vars to javascript in external file)

I have got the following code:
<HTML>
<?php
if(isset($_GET['adjust'])){
$adjust = true;
}
//More variabele declaring
?>
<HEAD>
<script type="text/javascript">
var adjust = "<?php Print($adjust); ?>";
//More variable 'transports'
</script>
</HEAD>
<!-- rest of the file -->
I would like to clean this up a little, because I have a serious amount of variables. This troubles the readability and overview of the file.
I thought of putting it all into an external JavaScript file, but it didn't seem to work.
<HTML>
<?php
if(isset($_GET['adjust'])){
$adjust = true;
}
//More variabele declaring
?>
<HEAD>
<script type="text/javascript" src="externalJS.js"></script>
</HEAD>
<!-- rest of the file -->
With externalJS.js:
var adjust = "<?php Print($adjust); ?>";
//More variable 'transports'
According to this question, also asked here on stackoverflow, this ain't possible.
Is there a way to do it with the knowledge of the past few years, since above question was answered?
Are there other alternatives to improve the readability?
P.S.: I think it is worth mentioning I gain my php-variables from the url, txt-files and cookies.
When I have had cases where I have had to place a number of variables into javascript, I have used the approach of loading all those items into an object (or array) and outputting that data into an object/array literal in javascript.
For example:
<?php
$js_object = new stdClass();
$js_object->foo = 'some value';
$js_object->bar = 'some other value';
?>
<script type="text/javacript">;
var php_values = <?php echo json_encode($js_object); ?>;
console.log(php_values.foo);
console.log(php_values.bar);
</script>
This does a few things.
Your JS output section does not need to change at all if the variables being passed need to change. Anything you want to access in JS just needs to be loaded in $js_object before the object is output to the browser via json_encode()
It puts all your PHP-provided values in a neat object/array in javascript where they can be accessed.
You can easily pass complex data structures in this manner (nested arrays, objects containing arrays, arrays of objects, etc.)
If needed you could extend the object in javascript to provide methods, etc. to act on the data.
I would also comment that you might want to think a bit about whether you wanted to pass cookie data in this manner. Cookie data is available to javascript anyway so you may want to work with that data directly if you need to change values or such.
Mike Brant's approach is good here (storing everything in a json object), but to accomplish specifically what you are asking here in a more segmented way you can simply make your included javascript library a PHP file that outputs Javascript headers. Your markup would look like this:
<HTML>
<?php
if(isset($_GET['adjust'])){
$adjust = true;
}
//More variabele declaring
?>
<HEAD>
<script type="text/javascript" src="externalJS.js.php?<?=http_build_query($_GET);?>"></script>
</HEAD>
<!-- rest of the file -->
And then your externalJS.js.php file would look like:
<?php
header("content-type: text/javascript");
?>
var adjust = "<?php Print($adjust); ?>";
//More variable 'transports' and any other PHP/Javascript code
The header here tells the browser to treat the result as javascript despite the .php extension.
Also, if you really wanted to you could also just tell you webserver to parse js files as PHP, so that it would look for <?php ... ?> segments and execute them, so you don't even need to have a non-js extension on the file:
AddType application/x-httpd-php .js
But be careful when you do this, as it means that all javascript files (or any files in the specified directory, if you're using htaccess) will be parsed, which could open up security holes if you're not careful.
A couple of side notes:
Have a look at the discussion around text/javascript vs application/javascript
Don't capitalize all the tag names. Yes, HTML5 says it's OK, but the W3C recommends lowercase as a convention (both for standardization and for any possible conversion to xhtml).
When just printing or echoing, first of all use lower-case (print vs Print), don't wrap the printed variable in parentheses (print and echo are language constructs, so they don't need the parentheses and there are situations where using them can cause problems), and lastly, if all you're doing in a PHP tag is printing or echoing, try using PHP echo shorthand (most webservers understand them by default): <?=$var_name;?> is the same as <?php print($var_name);?>
Create an array in PHP containing the variable name (as you want it in javascript) as the key for each element, and the value as you want it in javascript as the value of each element. Then, follow this:
$myVars = array();
$myVars['adjust'] = isset($_POST['adjust']) ? true : false;
$myVars['other'] = isset($_POST['other']) ? true : false;
$myVars['another'] = isset($_POST['another']) ? true : false;
<script type="text/javascript">
<?php
foreach( $myVars as $k => $v ):
echo 'var ' . $k . '="' . $v . '";';
?>
</script>
Cheers

Javascript: How to not directly post a variable

I am in need of help again, this time with a little Javascript snippet. There's also a little bit of PHP involved. The PHP is as follows (to generate random numbers)
$no1 = rand(0,9);
$no2 = rand(0,9);
$no3 = $no1+$no2;
I'm using this as a captcha method, for a very simple contact form. I'm not a fan of the bulky methods that I find all over google searches.
To validate this code, I use the following Javascript
if(document.forms["feedback"].check.value !== "<?php echo $no3; ?>"){
window.alert("Incorrect security code");
return false;
}
Then inside my form, I just use this:
<?php echo $no1; ?> + <?php echo $no2; ?> = <input name="check" type="text" id="check" size="3">
It all works as it's supposed to, but if there was a way for me to not to just directly echo $no3 in my javascript here:
if(document.forms["feedback"].check.value !== "<?php echo $no3; ?>")
Then that would eliminate any way of viewing the source to find the answer. I'm very much aware that it's a simple math problem, and if anyone knows how to view source, they most definitely can add, but a colleague of mine pretty much insisted on this.
So, does anyone know a way to help me out? I pretty much wrote most of this by hand, including the javascript, so please be nice when telling me that my code is horrible and out dated..
Thanks!
Put the $no1 and $no2 variables inside of span tags (or anything else you can directly target with Javascript) and then get the values from those spans with JS and use that to calculate the sum in JS rather than echoing it into the source with PHP, e.g. give the spans IDs like #captcha-1 and #captcha-2 use getElementByID to retrieve the values, then do the validation entirely in Javascript.
It will still be easy for anyone with a brain to figure out how to bypass but at least the answer will not be present anywhere in the source code other than as a JS variable.
If you want to hide the validation process entirely, you will need to use JS and AJAX to send the sum input by the user to a serverside PHP function which checks to see if it is equal to $no1 + $no2 and then submit the form as part of the response success function.
All that being said, this is still a very weak spam deterrent method.

Categories

Resources