Question

What are the measures needed to prevent or to stop JavaScript injections from happening in a PHP Web application so that sensitive information is not given out (best-practices in PHP, HTML/XHTML and JavaScript)?

Was it helpful?

Solution

A good first step is applying the methods listed in the question Gert G linked. This covers in detail the variety of functions that can be used in different situations to cleanse input, including mysql_real_escape_string, htmlentities(), htmlspecialchars(), strip_tags() and addslashes()

A better way, whenever possible, is to avoid inserting user input directly into your database. Employ whitelist input validation: in any situation where you only have a limited range of options, choose from hard-coded values for for insertion, rather than taking the input from any client-side facing form. Basically, this means having only certain values that you accept, instead of trying to eliminate/counter evil/mal-formed/malicious input.

For example: If you have a form with a drop down for items, do not take use the input from this dropdown for insertion. Remember that a malicious client can edit the information sent with the form's submission, even if you think they only have limited options. Instead, have the drop down refer to an index in an array in your server-side code. Then use that array to choose what to insert. This way, even if an attacker tries to send you malicious code, it never actually hits your database.

Obviously, this doesn't work for free-form applications like forums or blogs. For those, you have to fall back on the "first step" techniques. Still, there are a wide range of options that can be improved via whitelist input validation.

You can also use parameterized queries (aka prepared statements with bind variables) for your sql interactions wherever possible. This will tell your database server that all input is simply a value, so it mitigates a lot of the potential problems from injection attacks. In many situations, this can even cover free-form applications.

OTHER TIPS

Treat any value you output to html with htmlspecialchars() by default.

Only excuse for not using htmlspecialchars() is when you need to output to html string that itself contains html. In that case you must be sure that this string is from completely safe source. If you don't have such confidence then you must pass it through whitelist html filter that allows only for carefully limited set of tags, attributes, and attribute values. You should be especially careful about attribute values. You should never allow everything to pass as attribute value especially for attributes like src, hef, style.

You should know all places in your webapp where you output anything to html without using htmspeciachars(), be sure that you really need those places and be aware that despite all your confidence those places are potential vulnerabilities.

If you are thinking that this is too much caution: "Why do I need to htmlspecialchar() this variable that of I know it contains just integer and loose all the precious CPU cycles?"

Remember this: You don't know, you only think you know, CPU cycles are cheapest thing in the world and nearly all of them will be wasted by waiting for database or filesystem or even memory access.

Also never use blacklist html filters. Youtube made that mistake and someone suddenly found out that only first <script> is removed and if you enter second one in the comment you can inject any Javascript into visitors browser.

Similarly to avoid SQL Injections treat with mysql_real_escape_string() all values that you glue to SQL query, or better yet use PDO Prepared statements.

If your not passing anything that needs to be formated as html then use:

strip_tags() <- Eliminates any suspicious html

and then run the following to clean before saving to the db

mysql_real_escape_string() 

If your ajax is saving user entered html via a textbox or wysiwyg then look into using HTMLPurifier to strip out javascript but allow html tags.

I do not agree fully with the other answers provided so I will post my recommendations.

Recommended reading XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

Html Injection: Whenever displaying any user submitted content, it should be appropriately cleaned up with htmlspecialchars or htmlentities when specifying ENT_QUOTES if used inside of single quotes. I would recommend never encapsulating in single quotes and always encapsulating your attributes in double quotes (do not omit them). This applies to things such as:

<input value="<?php echo htmlspecialchars($var); ?>" />
<textarea><?php echo htmlspecialchars($var); ?></textarea>
<p><?php echo htmlspecialchars($var); ?></p>
<img width="<?php echo htmlspecialchars($var); ?>" />

Javascript Injection: It is best practice (but not always practical) to never echo user content into events and javascript. However, if you do there are some things that can be done to reduce the risk. Only pass integer id's. If you require something such as a type specifier, then use a whitelist and/or conditional check ahead of time before outputting. Possibly force user content to alphanumeric only when appropriate; preg_replace("/[^A-Za-z0-9]/", '', $string); but be very careful what you allow here. Only include content when it is encapsulated in quotes and note that htmlspecialchars/htmlentities does not protect you here. It will be interpreted at runtime even if it has been translated into html entities. This applies to things such as:

<a href="www.stackoverlow.com/?id=<?php echo (int)$id; ?>">Click</a>
href, src, style, onClick, etc.

Do not echo any user content into other areas such as the body of script tags etc unless it has been forced to an int or some other very very limited character set (if you know what you are doing).

SQL Injection: Use Prepared statements, bind user content to them, and never directly insert user content into the query. I would recommend creating a class for prepared statements with helper functions for your different basic statement types (and while on the subject, functionalize all of your database statements). If you choose not to use prepared statements then use mysql_real_escape_string() or similar (not addslashes()). Validate content when possible before storing into the database such as forcing/checking for integer data type, conditional checks on types, etc. Use proper database column types and lengths. Remember the main goal here is to prevent sql injection but you can optionally do html/javascript injection protection here as well.

Other Resources I have done some research online in hopes to find a simple solution already publicly available. I found OWASP ESAPI but it appears quite dated. The links to the php version are broken in several places. I believe I found it here; ESAPI PHP but again it is quite dated and not as simple as I was hoping for. You may find it useful however.

All in all, don't ever just assume you're protected such as using htmlentities in an onClick attribute. You must use the right tool in the right location and avoid doing things in the wrong location.

This question already have some answers accepted and rated by users.

Instead I am also posting an answer, hope this will work fine.

This is tested by me.

$value = preg_replace("/[\'\")(;|`,<>]/", "", $value); 

preg_replace() function works perfectly here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top