Imitating cookies behavior in chrome packed app - javascript

I am using REST service, that is not in my control to modify.
The service have verification/login and many "data-retrive" endpoints.
I have been requested to create "Chrome packed app" that will use this REST service.
The limitations I have are:
Can't use sandboxed pages.
Can't use webview.
The problem:
Xhr requests ignore "Set-cookie" headers.
it's impossible to set cookies manually (Like there is no cookie api).
Ideas & research
I googled my way into XHR implementation using "chrome.socket", With no https support, since "chrome.socket" dose not support TLS.
Forge is a "Chrome-js" library that adds TLS support to the "chrome.socket"
Questions
Is there any way to Modify requests and response headers?
Is there any way to combine the XHR implementation using "chrome.socket" with Forge? (I don't really know the protocol or the original XHR implementation)
is it even reasonable to implement fake cookie API to manage the data from the headers?

You should look into using a Cross-Origin Resource Sharing (CORS) request. There is a good introduction here.
In particular, you will need to use withCredentials:
Standard CORS requests do not send or set any cookies by default. In
order to include cookies as part of the request, you need to set the
XMLHttpRequest’s .withCredentials property to true: [...]
Note that you will need the server's cooperation to do this:
In order for this to work, the server must also enable credentials by
setting the Access-Control-Allow-Credentials response header to
“true”.
Since you are always on Chrome, you could use the Fetch API instead of XMLHttpRequest2. In that case you would add the credentials option:
Should you want to make a fetch request with credentials such as
cookies, you should set the credentials of the request to “include”.
Both of these mechanisms will (1) support HTTPS and (2) manage cookies opaquely, i.e. they will not permit you to inspect the cookie data.

Related

How does CORS plugin / --disable-web-security work on browser?

I'm sure I'm not the only one who have used/uses CORS plugins for browsers or --disable-web-security flag while making API calls to external (or even internal) API endpoints. I used this plugin to make Google Maps related API calls. But within the same application, ParseSDK API calls needed no CORS or --disable-web-security flag.
My question is : Why are these endpoints acting differently and how does CORS plugin solve the problem (even though we don't have control over those APIs)?
Thanks in advance.
Well, what that plugin does is highly irresponsible; It actually disables the same origin policy, which enforces that a website on a specific origin can only make requests to that origin.
The same origin policy actually just prevents a website from reading the response of a GET/POST request, the request itself is made, because it's considered safe.
Over time this good security feature became a burden and people used workarounds like JSONP.
So we got a new, standardized way to access foreign origins:
CORS (Cross-Origin Resource Sharing) is a mechanism that allows a web server to specify that another origin is allowed to access its content. This is done with Access-Control-Allow-Origin: example.com which allows example.com to access the response even if the response is from a different origin.
The Access-Control-Allow-Credentials: true would also allow the credentials, which includes cookies and HTTP Basic authentication to be sent within the request.
You can also specify a wildcard for Access-Control-Allow-Origin: *, which allows all websites to access this response. However when you do this you have to specify Access-Control-Allow-Credentials: false, so no credentials are exposed.
This is the only correct way to implement a public accessible AJAX API in the internet.
However this plugin just simply disables the same origin policy completely which is extremely dangerous.
The link you posted (did you read the description?) specifies exactly what the extension does - it adds the Access-Control-Allow-Origin: * header to all responses. This is a CORS header that normally the server sends to notify the browser that you are allowed to make requests from arbitrary origins.
Parse SDK probably supports CORS on their server end.
Just for your information, when most people say CORS they are not referring to a browser extension. They're referring to the web standard called CORS. Documentation below.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Enable CORS for Azure Storage via Client-side Javascript

I am working on a Javascript library to create entities in Azure Storage Table. Luckily, Azure supports Cross-Origin Resource Sharing (CORS). CORS is disabled by default. Using Set Table Service Properties API it is possible enable it for specific domains and methods for a limited time.
Enabling CORS requires you to make a non-simple request: PUT request against https://<account-name>.table.core.windows.net/?restype=service&comp=properties with headers Authorization, x-ms-date, x-ms-version. When the library makes that HTTP request, browser sends a preflight request to the URL first. Preflight request always fails, because CORS is not enabled for that URL. The actual request fails, since preflight request is failed.
In that case, it seems not possible to enable CORS for Azure Storage services via client side javascript methods. Is that so? Is there anybody who worked on these APIs and managed to get it working?
NOTE: Having a proxy method is always an option (among others). We can create an API on the server side to enable CORS or even create entities without any client side execution (which doesn't require CORS at all). Client wouldn't need to make any cross domain request. However, I am not looking for that. I am more interested in solving the issue using client side capabilities only.

How can I override the Origin header in Chrome when connecting to a WebSocket?

I am trying to connect to an external web socket server, which is not run by myself. I would like to connect to it from a localhost javascript file, therefore the origin header has null value.
I understand that this is a measure against cross-site forgery. However, since I am on localhost, I should be able to fake this, by getting Chrome to send a custom Origin header.
Is it possible? (if I need an extension, that is fine)
If not, what is my best option to achieve the above? Thank you.
Web pages cannot change the Origin header, but extensions can modify the request headers via the chrome.webRequest API. But ws:// and wss:// are not supported by this API, so this doesn't help unless the server also supports other means of communication via http(s) (e.g. long-polling).
There is still a solution though: Simply load a (known) web page at the desired origin in an iframe (e.g. https://example.com/favicon.ico or https://example.com/robots.txt) and use a content script to open the WebSocket from there.
The Origin header is one of the headers that are set automatically by the user agent (as part of the browser implementation), and cannot be altered programatically or through extensions. This makes sense because web service providers cannot allow random connections from localhosts.
You can connect to an external WebSocket only if you do it from a host explicitly accepted by the web service provider. Many headers cannot be trusted (because they can be overridden), but this is not the case with Origin as it offers security not only for users, but also for service providers against unwanted connections.
As far as I know this will not be possible, it would break the security guards against CSRF in Chrome.
If you were able to do that the whole concept of XHR would fall apart.
Here is an Extension you can use to manipulate header on the fly, but so far I have not been able to get it to manipulate socket headers.
Look here if you want to read more about this.
But this doesn't stop you from implementing your own client (in place of chrome) where you can literally send whatever headers you want, not sure if this helps you, sorry.
It depends how you want to use your chrome browser. Since you mention localhost I assume you develop and will use this for some kind of scraping. I suggest that you explore Chrome DevTools Protocol which will render (almost) any kind of protection useless because you use a real browser. CORS, Origin, Cookie or any arbitrary header value will be under your control, and you can send a custom header for xhr/websocket request(s). If you want to manipulate in a more advanced way you can use Network.continueInterceptedRequest. You might only want to start chrome using parameters like "--disable-web-security, --disable-xss-auditor, --disable-client-side-phishing-detection, --allow-insecure-localhost" more about such options at peter.sh. However, the last option require a plugin in order to spoof origin header so I recommend the first option.

CORS in embedded javascript

I'm intending to add security for our Javascript code which gets embedded on other sites - eg: like analytics code.
The user copies 4-5 lines of the code and puts it on his site. The code actually downloads the real script as the next step.
I have been recommended to use CORS instead of the current JSONP calls as I can restrict the domains.
As I understand, the CORS would work only if the html page which will add my scripts needs to add access domains and if I add the access domains for the the js file, it wouldn't work.
Is the CORS for the final js or the html page intending to use my script?
Edit:
Since it's confusing to the users, I have made it more simple.
HTML in domain A adds my script from Domain B like Google analytics. Can I add access-domains: while rendering my JS or should the HTML add the access-domains in the response?
There is a good explanation from wiki for this question:
CORS can be used as a modern alternative to the JSONP pattern. While JSONP supports only the GET request method, CORS also supports other types of HTTP requests. Using CORS enables a web programmer to use regular XMLHttpRequest, which supports better error handling than JSONP. On the other hand, JSONP works on legacy browsers which predate CORS support. CORS is supported by most modern web browsers. Also, while JSONP can cause cross-site scripting (XSS) issues where the external site is compromised, CORS allows websites to manually parse responses to ensure security.
As I understand, the CORS would work only if the html page which will add my scripts needs to add access domains
You can access all domains via:
Access-Control-Allow-Origin: *
Also now CORS has good support.
P.S. IE8-9 has own imlementation by XDomainRequest.
CORS works by having your server output the Access-Control-Allow-Origin header containing the allowed domains. The sites that make ajax requests to your server don't need to do anything special to enable CORS, there is no configuration required. The sites just simply make normal XHR requests and the browser will internally handle the CORS.
You control the CORS access from the header on your server. In CORS, you can also control the HTTP verbs that are allowed, for example POST or GET (Access-Control-Allow-Methods) or the permitted request headers (Access-Control-Allow-Headers).
Note that IE8 doesn't support the CORS XHR, Microsoft decided to create their own CORS implementation with XDomainRequest. So if any of the sites that call your server want to support IE8, they will need to use XDomainRequest instead of XMLHttpRequest. There is no support for CORS in IE7 or eariler - not even XDomainRequest.

JavaScript access from parent domain to subdomain?

I've read that setting document.domain = "example.com" lets me access the parent domain from a subdomain.
Will the same work the other way around?
Let's say my main site is running under http://example.com. All API functions that I want to access via AJAX (GET & POST) are hosted on http://api.example.com.
Will I be able to access api.example.com from example.com?
EDIT: Looking at document.domain again, I don't think that this will solve the problem. The result from calls to api.example.com are not necessary HTML, but output from a PHP script running on the API server. It can be JSON, plain text, etc. so there's no way to set document.domain for that (since it's not an iframe).
You need to set document.domain on BOTH pages
Alternatively set CORS headers on your server:
http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
A Quick Overview of CORS
Firefox 3.5 and Safari 4 implement the
CORS specification, using
XMLHttpRequest as an “API container”
that sends and receives the
appropriate headers on behalf of the
web developer, thus allowing
cross-site requests. IE8 implements
part of the CORS specification, using
XDomainRequest as a similar “API
container” for CORS, enabling simple
cross-site GET and POST requests.
Notably, these browsers send the
ORIGIN header, which provides the
scheme (http:// or https://) and the
domain of the page that is making the
cross-site request. Server developers
have to ensure that they send the
right headers back, notably the
Access-Control-Allow-Origin header for
the ORIGIN in question (or ” * ” for
all domains, if the resource is
public) .
The CORS standard works by adding new
HTTP headers that allow servers to
serve resources to permitted origin
domains. Browsers support these
headers and enforce the restrictions
they establish. Additionally, for HTTP
request methods that can cause
side-effects on user data (in
particular, for HTTP methods other
than GET, or for POST usage with
certain MIME types), the specification
mandates that browsers “preflight” the
request, soliciting supported methods
from the server with an HTTP OPTIONS
request header, and then, upon
“approval” from the server, sending
the actual request with the actual
HTTP request method. Servers can also
notify clients whether “credentials”
(including Cookies and HTTP
Authentication data) should be sent
with requests.

Categories