Web apps today are quite sophisticated on the client-side, with HTML, Javascript and CSS content. Security concerns have maginified especially because of multi-domain content on a page, such as is seen in Mashup applications. Areas to be considered carefully are:
Web Storage:
- Storing sensitive data
Rather use sessionStorage.setItem() instead of localStorage which persists the stored data indefinitely, unless explicitly removed. Instead, the code should look like :
Cross Domain Communication:
- Web Messaging
When using Web messaging, be sure to validate the origin of a message and the message itself. e.g.
window.addEventListener("message", receiveMessage, false);
...
function receiveMessage(event) {
if (event.origin !=== "http://www.example.com:")
return;
if (!validateEmail(event.data))
return;
div.getElementById('user_email_address').textContent = event.data;
...
}
- CORS - Cross domain requests
(Preflight request is the initial request issued prior to sending a CORS request to determine the origins, HTTP methods, and custom headers that can be used to access a given resource on a server.)
Secure Cross-Domain Communications - Properly Sandboxed IFrames:
- Other Communication mechanisms - if possible don't use them
- Do not use window.name for Messaging
- Avoid Fragment Identifier Messaging (FIM)
- Avoid setting the document.domain property
- In case of communication over web sockets always be sure to check the WebSocket origin header to confirm that the packet-originator domain is not an unknown one.
Javascript Best Practices:
When using Javascript the main concern is to prevent malicious code from being included and executed in the context of legitimate web pages
Understanding the dataflow of your JS code is key, in order to apply input validation and output encoding. Data flow analysis is then important. It helps determine paths data takes from JS source to sink functions. Some common JS sources and sinks for data analysis.
- Sources:
document referer - set by server that initiated HTTP-302 redirection
window.name - can be used to carry out cross-domain communications between an iframe and its parent document
location - property of an element that describes url at which element is hosted
event.data - Message payload sent via html 5 web messaging postMessage() function
localStorage.getItem - Retrieves data from the localStorage object
sessionStorage.getItem - Retrieves data from the sessionStorage object
document.cookie - Retrieves data from the client's cookies
- Sinks:
document.write() - writes content to the document object
innerHTML() - reads or sets a DOM element's markup
location.* - The location object contains info about the current URL
location.assign() - Loads a new page into the browser
eval(string) - evaluate or execute its argument. Ofetn used to execute dynamically built/concatenated expressions
setTimeout(code, millisec, lang) - Calls a function or evaluates an expression after a specified number of millisec
setInterval(code, millisec, lang) - Same as above but at specified timme intervals, repeatedly
object.execScript(code, language) - Executes the specified script in the provided language.
Input Validation :
- Verify data origin
if data has multiple components, like headers and payload, tokenize it and check syntax, finally semantics for appropriateness to the context it will be used in
- Strategies for Input validation
Black-listing ( exclude specified bad characters)
White-listing ( include only known-good chars)
rostering or mapping (only allow good complete strings or values)
indirect selection (only allow good indirect key values )
Output Encoding ( complement to input validation)
Replace any chars that could be interpreted as special or as control chars in the context of their use, with their corresponding encoded representation. The encoding scheme depends on the context of their use. When implementing output encoding :
- Identify output context - Conetxts may be HTML, dynamically assembled and evaluated JS, and CSS. Even within these there are sub-contexts where different encodings may apply. e.g. for HTML code :
Element names
Attribute names
Attribute values
HTML data (text node)
Event Handlers
e.g. <a href="http://abc.com" onclick="function() {alert('hi');}">Contact Us!</a>
In the above string 'a' is an Element name, "href' an attribute name etc. Note how the value of the onclick HTML attribute is a Javascript sub-context within the enclosing HTML context.
- Use Proper Encoding -
Use public encoding libraries e.g. OWASP ESAPI, JQuery, Dojo Toolkit, Microsoft's WPL. Dont write your own.
e.g. of transformation by encoding:-
HTML entity encoding
"&<> gets converted to "&<>
HTML attribute encoding also similar to above
URI encoding
param1=a¶m2=b#something to param1%3Da%26param2%3Db%23something
Javascript parameter encoding
hello)\";( to hello\x29\x22\x3B\x28
Additionally, there are several other best practices to follow:
- Validate Poster attribute in <Video> elements - beware of scripts in the values
- Beware of oninput attribute - this event handler is new in HTML5 and applies to all elements. It may be used to inject malicious javascript when an element receives input.
- Avoid using eval() function - If you have to, ensure that input that is passed is properly validated.
e.g.
Insecure use :
function Test() { this.bar ="hi"; this.bar1="h1";}
var foo = new Test();
function access_property(prop) { var value = eval('foo.'+prop); alert(value); }
access_property(document.getElementById('prop').value);
Secure Use:
function Test() { this.bar ="hi"; this.bar1="h1";}
var foo = new Test();
function access_property(prop) { var value = foo[prop]; alert(value); }
access_property(document.getElementById('prop').value);
- Serve JS code securely
Serve external JS libraries from an internal server
Serve JS via HTTPS (SSL/TLS) ro avoid Man-in-the-Middle attackes which will change the JS script to cause harm to clients.
- Set Cookies as HttpOnly so that malicious JS code can't access cookie info via document.cookie property, and can't hijack any session info stored in the cookie.
JSON Best practices:
- Input Validation of Json data
JSON data may be manipulated by Web Proxies (Fiddler) before reaching server.Similarly Man-in-Middle attacks could change JSON data before reaching client.
- Do not include verbose error messages
Avoid JSON data containing detailed error messages when error occurs on the server.
e.g. { 'id': 39, 'error': 'db_query', 'message': 'Invalid parameters for SQL statement "SELECT id, username, password FROM users WHERE username=\'admin\' AND password=null;"'}
- Validate JSONP callback Method parameter
<script type="text/javascript" src="http://www.otherdomain.com/orderservice.svc/GetOrders?jsonp=processResults"></script>
More about using JSONP
JSONP message format is basically a normal JSON format with padding. I will explain what padding is all about in JSONP. As I said in the previous section in the Same Origin Policy <Script> tag is exempted. So a cross domain call can be done as shown as below.<script type="text/javascript" src="http://www.otherdomain.com/orderservice.svc/GetOrders"></script>
This cross-domain call will be successful and the result will be returned in a JSON format as shown below.[{"OrderId":1000, "OrderItem":"Cricket Bat", "Quantity": 10, "TotalPrice":20000}{"OrderId":1001, "OrderItem":"Football", "Quantity": 100, "TotalPrice":50000}]But this is of no use since we have received the data and are not processing it. Now let's check what JSONP does. Modify the script URL with an additional query string value as shown below:<script type="text/javascript" src="http://www.otherdomain.com/orderservice.svc/GetOrders?jsonp=processResults"></script>The above JSONP call to the cross-domain service will return the JSON with padding the given query string value as a script callback method.parseResults([{"OrderId":1000, "OrderItem":"Cricket Bat", "Quantity": 10, "TotalPrice":20000}{"OrderId":1001, "OrderItem":"Football", "Quantity": 100, "TotalPrice":50000}])You can implement JSONP callback JavaScript function as shown below.function parseResults(results) {alert('Cross domain JS call achieved. Have your implementation going in here!');}
processResults will be called with the JSON data returned by the response from a call to a cross-domain URL. The callback method is echoed back in the JSONP response along with the requested data.This should be properly validated before use anywhere in calling page.
- Avoid using eval on JSON data
eval() is often used to convert JSON into Javascript objects. But this should be avoided. Instead use JSON.parse( {...} ), since this will do the same thing without the potential to execute maliciously injected code.
Common Assessment approaches:
- Static code Analysis Security Code Reviews
- manual and automated. Examples of Automated tools are AppScan Source, HP Fortify Source Code Analyzer, Coverity Statis Analysis.
- Dynamic Analysis -
Dynamic Application Security Testing (DAST) tests and evaluates a program at runtime, in the production (deployed) environment.
- treats program as blackbox
- limited insight into architecture or source code
- similar to activity that hackers would perform
- findings have lower false positives
- e.g. of this type of testing is "Penetration testing".
- lower level of return since it is done at a late stage of the product lifecycle - i.e. on deployment





































