How can I include server variables in JS with CSP? - content-security-policy

In my app I have some server variables:
{{# serverVars }}
<script>
window.serverVars = {{{ . }}};
</script>
{{/ serverVars }}
This is used to set, eg, window.serverVars.countryCode to the countryCode as determined by the server using geoIP.
Now in CSP this is considered unsafe-inline which is generally bad. So what's the best approach:
Using a nonce is difficult: the nonce is unique per request and most CSP libraries (eg, Helmet) considered CSP policies static
Using a hash is difficult: the value of serverVars is unique per request and most CSP libraries (eg, Helmet) considered CSP policies static
unsafe-inline for script-src is considered insecure
What's the best way to add dynamic server variables into client side JavaScript with CSP?

I’ve seen some people use scripts with types that the browser won’t execute, then fetch and parse those from the trusted JavaScript. For example, in the HTML:
<script id="config" type="application/x-configuration">
{"environment": "production", ...}
</script>
And then in your JavaScript file:
var config = JSON.parse(document.getElementById('config').textContent);
You could also put it as a data attribute if you’d prefer, e.g.:
<!DOCTYPE html>
<html lang="en" data-config="{"environment": "production", ...}">
...
And again fetching it in your JavaScript:
var config = JSON.parse(document.documentElement.dataset.config);

In addition to #icktoofay's excellent answer, I want to point out that some CSP libraries, eg Yahoo's Express CSP have a useScriptNonce that will dynamically generate nonce's for scripts.

Related

Content security policy header - both upgrade insecure requests and report the events

What I'm trying to achieve: Both upgrade all HTTP requests within the page to HTTPS and report/log the events.
The server supports both HTTP and HTTPS.
Test HTML page. Note the hardcoded HTTP protocol in <img>
<html>
<head>
</head>
<body>
<img src="http://example.com/testimage.png" />
</body>
</html>
According to the W3C documentation, I set up my .htaccess like this:
Header set Content-Security-Policy "upgrade-insecure-requests; default-src https:"
Header set Content-Security-Policy-Report-Only "default-src https:; report-uri https://report-uri.io/report/..."
When I call https://example.com/testpage.html, it loads the image over HTTPS but doesn't report the event.
What am I missing?
I'm not sure if upgrade-insecure-requests or block-all-mixed-content will generated events because they prevent the bad events from happening in the first place.
I could be wrong about the reasoning, but I do know block-all-mixed-content does not generate violations.
For block-all-mixed-content, it explicitely will not send a report. From https://www.w3.org/TR/mixed-content/#strict-opt-in:
This directive has no effect when monitored. This directive’s only
effect is to set a policy flag on the protected resource; it will
therefore never be violated, and has no reporting requirements.

JMeter Office360 online : JavaScript required to sign in error while authorization

When I try to login on sharepoint360 online site using JMeter, it gives JavaScript required to sign in error in response. I got below code in response.
<html>
<head>
<noscript>JavaScript required to sign in</noscript>
<title>Continue</title>
<script type="text/javascript">
function OnBack() {}
function DoSubmit() {
var subt = false;
if (!subt) {
subt = true;
document.fmHF.submit();
}
}
</script>
</head>
<body onload="javascript:DoSubmit();">
<form name="fmHF" id="fmHF" action="https://ApplicationURL.sharepoint.com/_forms/default.aspx?apr=1&wa=wsignin1.0" method="post" target="_self">
<input type="hidden" name="t" id="t" value="EgBZAgMAAAAEgAAAAwABJaEZDRmSdbQKqL6rJyYKAN1Z0valM74LOhnXMHkbILiqeyEyWkHmbZ3hVG8XvpXOVLvlnylOzhJx8KQgSsuO0d6P2quRRU168QMumuqH/qvLVkpZ5mPiBDDyI8l1z+E4++pxZ3H37uIevfjckj40rTlGYJ85aT0/nxcqDxlL6pxKStDm9GKNI81ypsDKv7dMEqg9lRDjJO5qmNEDiCP8jPB3WWke5pVqcn6c1MbnbHzKU2uHzekZqjxAflfvWu5LS9R+N6jciFZvicn8P0EV0LZHqmjXgUsoVMdn9gGemJYnQCoIbkk7Oo9DPaqXRsxApY5sqCwotEJvZ45AaBNAQkgBYABIAQAAAxBYNSeVFbxuVhW8blZOoQcACgAgAAAhAGtrQHNmd3Byb2R1Y3RkZXYub25taWNyb3NvZnQuY29tAGMAAC1rayVzZndwcm9kdWN0ZGV2Lm9ubWljcm9zb2Z0LmNvbUBwYXNzcG9ydC5jb20AAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAB0t1bGRlZXAABUt1bWFyAAAAACAAAAAAAAAAAAD//////////wAAFbxuVpUsb1YAAAAAAAAAAAAAAAANADEyMy42My42NS42NgAAAAAAAAAAAAAAAAAAAQAAAQAAAQAAAQAAAADU1N9WAQAAAQAAAAAAAAAAAAAAAAAANwBodHRwczovL3BvcnRhbC5taWNyb3NvZnRvbmxpbmUuY29tL0NoYW5nZVBhc3N3b3JkLmFzcHgA/////wAAAAAAAA==">
</form>
</body>
Thanks in advance.
Sunil
As per Apache JMeter Homepage
JMeter does not perform all the actions supported by browsers. In particular, JMeter does not execute the Javascript found in HTML pages. Nor does it render the HTML pages as a browser does
You need to extract the "value" attribute of that "t" hidden input and pass it along with other request parameters. I would recommend using CSS/JQuery Extractor or XPath Extractor for this.
Relevant configurations:
CSS/JQuery Extractor
Reference Name: anything meaningful, i.e. t
CSS/JQuery Expression: input[id=t]
Attribute: value
XPath Extractor
Use Tidy - check. If response is XHTML compliant it is not required however.
Reference Name: again, any JMeter Variable name, i.e. t
XPath Expression: //input[#id='t']/#value
Refer the extracted value as ${t} where required
Handle any other dynamic parameters similarly and you should be good to go. JMeter doesn't execute JavaScript but it can capture and execute JavaScript-driven HTTP requests. Given you perform load testing you shouldn't worry about what is happened in browser as JavaScript is being executed on client side only. See ASP.NET Login Testing with JMeter article for more detailed explanation and instructions.
Looking at how sharepoint authentication works, I believe you need to implement authentication using HTTP Request, instead of using login page, as explained here. Basically you will need 2 HTTP requests: first to extract the SAML token, and second to receive authentication cookies, which you can then use in the following HTTP requests, as you normally do.

How to run content script code on an HTML file locally hosted by Google Chrome Extension? [duplicate]

I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}

Using LESS in a Chrome Extension

I'm attempting to use LESS in a tab created via a Chrome extension (chrome.tabs.create), but I'm getting a cross domain error ("NETWORK_ERR: XMLHttpRequest Exception 101"), referring to the LESS JavaScript file. I'm not clear on how to set up the permissions. Adding the LESS JavaScript file to "web_accessible_resources" doesn't seem to help. All other files, such as css and js files load fine. It seems I only receive this error from within the less source. Any ideas?
To explain my setup a bit more, the LESS JavaScript file and .less file are loaded in an HTML file something like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet/less" href="static/css/main.less">
<script src="/static/js/jquery-1.8.2.min.js"></script>
</head>
<body>
Whatever...
</body>
</html>
This html file is loaded in background.js like this:
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.create({url: 'mypage.html'})
});
The manifest file has permissions for "tabs" and "all urls", and loads background.js.
I'm not sure where you include the client side less.js compiler. See also: http://lesscss.org/#client-side-usage. Less.js is a client-side javascript. It seems the less.js loads from an other URL (domain) than your main.less file. This can be fixed by enabeling CORS, see: http://enable-cors.org/. On the domain where home.less has been installed, the server should send an Access-Control-Allow-Origin: * header.
less.js loads the less files with a XMLHttpRequests which supports CORS for most modern browsers see http://caniuse.com/#search=cors. More details can be found at http://www.html5rocks.com/en/tutorials/cors/
For development use less.js from local folder.
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
for release use any less compiler like lessc.

Does content_scripts matches "chrome-extension://*/*" work?

I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}

Resources