I have this app that uses EWS to access mail, using the standard /EWS/Exchange.asmx SOAP endpoint.
One my user's mail servers is protected by Microsoft Forefront, and the initial HTTP request to
https://server_name/EWS/Exchange.asmx
is redirected (HTTP 302) to:
https://server_name/
CookieAuth.dll?GetLogon?curl=Z2FEWSZ2FExchange.asmx&reason=0&formdir=3
which is an regular HTML page, the point of which, I guess, is to make the user authenticate "manually".
I've not heard about Forefront until today, not sure how to handle it.
Is this normal behavior for Forefront (i.e. it always redirects the initial HTTP request), or is it triggered by something in my app? For example, user-agent?
If it's normal, how am I supposed to get past this page and access /EWS/Exchange.asmx?
If it's triggered by something my app is doing, how can I find out what it is?
My code runs on Android and forms its own XML requests without using any SOAP library. At the transport level, I use Apache HTTP client components. The code works fine with Office 365/Exchange Online, and, according to user reports, "self-hosted" corporate Exchange servers with NTLM.
However, in this case, I'm not even getting an HTTP 401: the HTTP 302 is returned by the very first HTTP roundtrip.
Trying to preemptively authenticate the initial request using Basic authentication didn't make any difference.
The user who reported this issue also mentioned that another EWS based app works, so there must be a solution to it.
Related
I sniffed the network traffic coming out of an app that displays real time data. I am trying to get access to the api to display the same real time data on a website that I am working on currently. I was able to view the get request and the response using fiddler and I then sent a get request directly using the url. However, my get request was blocked by CORs policy. I'm a beginner and would like to know how to access the API.
If the server that's hosting the API doesn't supply COR headers that explicitly allow this, you're not going to be able to make these requests via your browser. I'd recommend making the requests on your server instead of in the browser, because that's not bound by CORs settings.
So my current state is I have a REST API web server (ASP.Net Web API), a website in plain Html which communicates with the server via ajax / angular post and get, also I have a mobile application which communicates via ajax / angular post and get.
I use Basic Auth header to secure the request, the web server will decrypt the content of the auth header and do the verification after.
What kind of attacks would the system be vulnerable to? Also what kind of security should I implement.
I read about the CSRF attacks and I think my system have no protection against it, but I have no idea how to implement it on REST API.
Also what about the cookie stealing attacks. Because my system uses persist cookies to store the auth token, how to deal with this kind of attack?
To prevent CSRF attacks, both your backend (ASP.NET Web API) and frontend (Angular) must be configured to prevent such an attack.
Taken from https://angular.io/guide/security#xsrf:
To prevent XSRF, the application must ensure that a user request originates from the real application, not from a different site. The server and client must cooperate to thwart this attack.
In a common anti-XSRF technique, the application server [backend] sends a randomly generated authentication token in a cookie. The client code reads the cookie and adds a custom request header with the token in all subsequent requests. The server compares the received cookie value to the request header value and rejects the request if the values are missing or don't match.
This technique is effective because all browsers implement the same origin policy. Only code from the website on which cookies are set can read the cookies from that site and set custom headers on requests to that site. That means only your application can read this cookie token and set the custom header. The malicious code on evil.com can't.
With that in mind, here's another quote from Angular HttpClient Docs which explains how you can implement it.
Taken from https://angular.io/guide/http#security-xsrf-protection:
When performing HTTP requests, an interceptor reads a token from a cookie, by default XSRF-TOKEN, and sets it as an HTTP header, X-XSRF-TOKEN. Since only code that runs on your domain could read the cookie, the backend can be certain that the HTTP request came from your client application and not an attacker.
By default, an interceptor sends this header on all mutating requests (POST, etc.) to relative URLs but not on GET/HEAD requests or on requests with an absolute URL.
your server needs to set a token in a JavaScript readable session cookie called XSRF-TOKEN on either the page load or the first GET request. On subsequent requests the server can verify that the cookie matches the X-XSRF-TOKEN HTTP header, and therefore be sure that only code running on your domain could have sent the request. The token must be unique for each user and must be verifiable by the server; this prevents the client from making up its own tokens. Set the token to a digest of your site's authentication cookie with a salt for added security.
Key points to take note would be:
When the angular app is loaded, it should make an API call first to your backend to retrieve an authentication token that is saved as a cookie that with the name "XSRF-TOKEN". Probably somewhere on root component (app.component.ts) ngOnInit() sounds like a good place.
By default, the authentication token will be automatically injected in the http header on all mutating requests such as POST. (Take note of this though, it is undocumented: Angular 6 does not add X-XSRF-TOKEN header to http request). Unless you return a custom-named cookie, then you have to use Angular's HttpClientXsrfModule.
With that in mind, your ASP.NET Web API should also be validating the XSRF-TOKEN as it receives requests.
With regards to your second question, cookie hijacking is done via XSS.
XSS vulnerabilities generally occur when an application takes user input and outputs it to a page without validating, encoding or escaping it.
Angular by default sanitizes inputs for tags. However, this is provided you do things "the angular way". If you use third-party libs, such as jQuery, to manipulate the DOM instead of using Angular's renderer2 module, you might lose this protections.
Taken from: https://angular.io/guide/security#xss:
In the same way, if you interact with other libraries that manipulate the DOM, you likely won't have the same automatic sanitization as with Angular interpolations. Avoid directly interacting with the DOM and instead use Angular templates where possible.
For cases where this is unavoidable, use the built-in Angular sanitization functions. Sanitize untrusted values with the DomSanitizer.sanitize method and the appropriate SecurityContext.
To increase security, you should also sanitize any mutating requests (such as PUT or POST) in your backend.
It is difficult to provide you with code examples because your question seem to be a more theory-based question.
I hope you will take a read on those links that I have hyperlinked above. They are definitely more detailed and well-explained. I hope it will at least point you in the right direction of what to get started on.
I'm playing with the idea of having a completely decoupled HTML5 frontend, but still user authentication for a web app. Is this possible or will I run into some heavy browser security issues?
The idea is to have all static content delivered through a CDN on like example.com, and having it fetch dynamic data (and user authentication) through a separate subdomain, like api.example.com.
This would speed up the loading time of the site, and I could keep the frontend stuff in a completely separate repo so that the developers don't have to worry about setting up the backend to develop and test new features.
Is this already possible in some JS framework perhaps, backbone.js, angular.js, ember.js, knockout.js ?
It definitely is, but I think it is more about approach rather than technology. I have implemented what you describe for a project (it's online but don't want to do a shameless plug here, if interested to check it out I can post the link). My stack is java in the backend exposing a REST api for both autentication and business logic. The client is a backbone.js application. I explicitely decided NOT to use sessions at all. It is completely stateless. This of course means that the user must be re-authenticated at every request.
When the user logs in through a slightly modified OAuth endpoint, it gets a token that must be passed at every request. Cookie works in this case as they are handled automatically by the browser. If not passed as cookie, the backend expect it as a parameter. The frontend communicates using the REST endpoints. It's a single-page application, full client side, this means that the backend serves a page that is basically empty, that include few JS files that are the application itself. No other pageload occurs. Logout is done by simply deleting the cookie or not sending the authToken, the server cannot and doesn't have to "forget" about the user. Token are nice as they can be invalidated, both expilcitely or by changing the password. I've chosen this approach as it made it easy to develop desktop app and browser plugin for my webapp without touching a single line of backend code.
Either I'm dense, or the docs assume I already know what they're telling me, but I need some clarification on doing authentication for a box.com app. I really don't understand whate's going on. As I read it:
the app running on the user's machine sends a request to Box, including all the little secrets (Which aren't all that secret any more if the user knows how to read the code).
The user is directed to the Box login page, which then sends the user to my server (with no page specified) attaching an authentication code.
The app somehow magically gets that code back from my server and sends a request to Box for the access token.
Box sends the access token to my server?
The app again magically gets the access token from my server and sends its APT requests.
Obviously I got lost somewhere.
And, why do I have to have a server involved in the process? The article on making a JavaScript app refers to a direct request for a token. Is there documentation on that somewhere?
You register your application on Box
After registration you receive clientId and clientSecret once on Box website
You hardcode your credentials somewhere in your application
First time your application needs to access Box API it should redirect user to https://www.box.com/api/oauth2/authorize, specifying your clientId, clientSecret and redirectURI as parameters. About redirectURI see below.
The box.com website opens. User enters his own credentials in the web form on box.com
User allows your application to access his files via API on the box.com website
Box redirects user back to you application using redirectURI specified before. One of the parameters to this request is "code". This is a very short-lived (30 seconds) access code that is only aligable for obtaining real access token.
During next 30 seconds your application should make another call to Box API to next URL: https://www.box.com/api/oauth2/token, specifying the previously obtained code. If everything was correct, your application receives an access_token, a refresh_token and "expires" values.
Now your application can make requests to Box API, specifying access_token every time
access_token expires in number of seconds, specified in "expires" field. It should be about 3600 seconds or 1 hour. Each time your application sees that access_token has expired, it should make another request to Box with the refresh_token and obtain a fresh access_token for another 1 hour.
refresh_token itself expires in 14 days
Note: if you develop a desktop application, then you should open browser for user on the step 4, redirectURI should be something like http://127.0.0.1:8080/Callback and you should run a small webserver just to catch the redirect with the code as in step 7.
Box requires that you specify a redirect_uri in your application's profile, and it must be an HTTPS URL.
As a result, it is not possible to use box with what google's oauth2 documentation calls "Client Side" or "Installed" applications, only "Web Server Applications" are allowed. Web Server applications do not have the secret leaking problem, because only the server knows the secret. You can pass the access token from your server to javascript on the client after
the oauth transaction is complete, if you want the client to make api requests directly.
In your question you are not totally clear in what you are actually trying to produce.
I however suspect that you are trying to write a client application what needs to authenticate to box using the OAUTH2 solution they have delivered in API V2.
If this is for an IPhone for example BOX has a great example of how to handle it.
In a WinForm application you would need to capture the resulting code sent back by box in the browser1.isnavigating event.
Windows console application you register a custom URI registration to collect the code.
Neither of these need to be registered in the API developers Application on box as you would pass the redirect required in the request to box.
If this does not point you in the right direction and your writing a .NET app then post again and I will try to clarify a little more.
Box requires some form user interaction which is short sighted in my opinion but try a web service that simulates a user interaction which then you can save/pass the token to your application to sync up with the Box "Cloud".
If your API and Website making ajax calls to that API are on the same server (even domain), how would you secure that API?
I only want requests from the same server to be allowed! No remote requests from any other domain, I already have SSL installed does this mean I am safe?
I think you have some confusion that I want to help you clear up.
By the very fact that you are talking about "making Ajax calls" you are talking about your application making remote requests to your server. Even if your website is served from the same domain you are making a remote request.
I only want requests from the same server to be allowed!
Therein lies the problem. You are not talking about making a request from server-to-server. You are talking about making a request from client-to-server (Ajax), so you cannot use IP restrictions (unless you know the IP address of every client that will access your site).
Restricting Ajax requests does not need to be any different than restricting other requests. How do you keep unauthorized users from accessing "normal" web pages? Typically you would have the user authenticate, create a user session on the server, pass a session cookie back tot he client that is then submitted on every request, right? All that stuff works for Ajax requests too.
If your API is exposed on the internet there is nothing you can do to stop others from trying to make requests against it (again, unless you know all of the IPs of allowed clients). So you have to have server-side control in place to authorize remote calls from your allowed clients.
Oh, and having TLS in place is a step in the right direction. I am always amazed by the number of developers that think they can do without TLS. But TLS alone is not enough.
Look at request_referer in your HTTP headers. That tell you where the request came from.
It depends what you want to secure it from.
Third parties getting their visitors to request data from your API using the credentials those visitors have on your site
Browsers will protect you automatically unless you take steps to disable that protection.
Third parties getting their visitors to request changes to your site using your API and the visitors' credentials
Nothing Ajax specific about this. Implement the usual defences against CSRF.
Third parties requesting data using their own client
Again, nothing Ajax specific about this. You can't prevent the requests being made. You need authentication/authorisation (e.g. password protection).
I already have SSL installed does this mean I am safe
No. That protects data from being intercepted enroute. It doesn't prevent other people requesting the data, or accessing it from the end points.
you can check ip address, if You want accept request only from same server, place .htaccess in api directory or in virtualhost configuration directive, to allow only 127.0.0.1 or localhost. Configuration is based on what webserver You have.