Security implications of having credentials show up in HTML - javascript

I'm currently developing a java backend and a frontend using php, html and javascript for a private project (but which I'd eventually like to open source), which means that access is limited to my LAN anyway and security does not play a vital role at the moment but might in the future.
As I'm most comfortable with coding in java most of the data processing and storage (MySQL) is handled in java and provided over http to the frontend (javascript; fetch()).
Additionally this java backend handles the authentication process which means I have to pass the login credentials with a fetch call in javascript to the backend.
As I'm not really into advanced web programming, I figured a basic POST -> REDIRECT -> GET setup for the login should suffice and I used similar login procedures (but handling the authentication in PHP) before. Therefore:
The client fills out a HTML-Form and submits it
The browser does a POST request to /login passing the credentials and the target page
PHP then returns the HTML containing a javascript portion that holds the credentials in plain text login("<?php echo $_POST['username'] ?>", "<?php echo $_POST['password'] ?>", "<?php echo $_POST['target'] ?>");
Javascript then fetches the java-backend with those credentials to create a session
Javascript issues window.location.replace(target); and the client is redirected to the target page (where authentication is handled via the session cookie)
I'm currently overthinking, if this is a good idea from an efficiency and security perspective. My current idea is to use the form to directly fetch the data to the backend with javascript instead of using a POST request to an additional page (skipping step 2 and 3 above):
This would mean that first of all PHP would never see the credentials (which would be one less point of failure) and that the credentials probably would not show up in the HTML. Additionally, this would cut loading times as the POST is not needed anymore.
My questions are therefore:
Is it bad security practice to have credentials show up in the HTML (as it is with having them in the URL, to prevent the user from accidentally sending their credentials to someone while copying the URL)? What are the risks associated with this? Could these credentials be read by any JS-libraries used or browser extensions? If so, those could probably also read the credentials which I type into the form anyway?
Is my alternative setup better from a security perspective (and efficiency perspective)?
Are there any other suggestions for improving security in this context?
Thank you for helping me.

Short summary of this post and the discussion below:
By first POSTing the credentials to PHP and then serving them back to the client in the returned HTML, latency (due to an additional page load) is increased, PHP is added as another point of failure and the system is theoretically opened up to more security problems (i.e. through javascript or browser extensions scanning the code or by hacking the PHP server).
Therefore two solutions are plausible:
Skip PHP entirely and let the login be handled by javascript and the java backend only (detailed description of this procedure below in points 1 - 5; this is only possible as the PHP server doesn't need authentication information in this specific use case)
POST the credentials to PHP and let PHP communicate with the java backend responsible for authentication, instead of reserving them to the client
Original post:
I don't quite understand why you think the PHP backend can't be trusted but in your scheme the PHP already gets your credentials, thanks to that original POST. If you want to avoid using PHP why not have your form call a JavaCcript function instead of POSTing to the PHP backend in the first place:
User enters credentials
User clicks "login"
JavaScript intercepts the login attempt, calls login()
JavaScript fetches user,pass from document body (getElementById(...))
JavaScript contacts the Java backend which handles login
No PHP needed. But I might wonder why that's necessary - if you can't trust your own backend, what exactly are your security practices? If your PHP can't be trusted why would your Java be any better?
In your scheme you're already passing the credentials to the PHP backend in the POST request. If your concern is PHP not knowing the credentials you've already failed.
As for efficiency, your scheme has extra page loads, which will use bandwidth, maximize latency (as opposed to the goal of minimizing latency) and make you look incompetent to users who notice the extra redirect. JavaScript sounds like the better solution is you want to write your database code in Java.
As far as the credentials appearing in the HTML there's really no difference since the only person who could access them would be the user (who already typed them in). If they input incorrect credentials they'll only see incorrect credentials. That said, it violates best practice and probably isn't a good idea.
Is it bad security practice to have credentials show up in the HTML (as it is with having them in the URL, to prevent the user from accidentally sending their credentials to someone while copying the URL)? What are the risks associated with this? Could these credentials be read by any JS-libraries used or browser extensions? If so, those could probably also read the credentials which I type into the form anyway?
The answer is Yes, it's entirely bad practice and opens you up to extra risk. They're probably not too concerning but you got it exactly right - there are more places where malicious code could read the credentials, and any JS library or installed extension can read them.
Is my alternative setup better from a security perspective (and efficiency perspective)?
No and no. From the security perspective it adds another point of failure; instead of needing to hack the Java backend they could choose to hack the PHP backend instead. This wouldn't necessarily be the end of the world but is an extra point of failure.
Are there any other suggestions for improving security in this context?
I explained my advice above. Either suck it up and use PHP, or use JavaScript to bypass PHP entirely.
One more thing, when handling logins make sure the Java passes a secret value (unique to each session) and the server verifies that value on every page load. When I was working as an ethical hacker an app I tested passed an auth token (OAuth2) but the server didn't actually verify it was correct, just that the client said it was valid. Make sure the server checks anything the client does.
Also, emphasis on unique to each session since a secret value that stays the same for each session is definitely gonna be the worst-kept secret you've ever wished hadn't got out.

Related

How to make sure a request is sent from original software?

I'm currently making an open source browser extension that will send requests to my site. This can easily be done with Ajax, a request will be sent to the page action.php.
My site will use PHP, well now the question is, how can I make sure action.php receives the request from the original extension? I mean griefers could easily send false information to the server, or a fork could be used and send incorrect data. I thought of generating a token of some sort, but anyone could recreate it I guess.
How can I prevent this situation?
I have some experience with this myself. I've been building an extension with a login and eventually came to the inevitability that security in an extension is inherently difficult.
The issue is that an extension is just a bundle of JS and HTML that anyone can inspect the values of. This means that anyone determined enough to dig through your code can potentially find out how to bypass anything you have built in.
The solution I eventually came to is that, the extension itself cannot hold any long-lasting secrets. A session with a timeout is the only safe thing to store. The actual login for my extension is done via a website over HTTPS.
If you are trying to do this without any such login, your only recourse is to make it as difficult as possible to determine what needs to be sent by using an algorithm that can generate server verifiable tokens, and then only publishing minified code to the webstore.
EDIT: Reread the question and noticed that you said you are doing this open source. Without some sort of authentication on the webserver via HTTPS, there is little you can do to stop those determined to bypass your protections because they will be on display in your public repository.
For sensitive endpoints like this, it would make sense do to the data processing server-side. The client would only have to query the server to process the data.

Authentication - key in each ajax

Im writing new app and this time i want to completely separate HTML/JS layer from the PHP layer. Thats because I'll do phonegap version in the future.
I have question about authentication. This time I can't use session variables so i must figure out new way of authentication. Im going to try it this way:
User fills login form and send it via ajax to php file.
Php file checks whether login and password are ok or not, and then create a key-token for that user. Save it on his side (ex. in mysql) and return it to the client side as javascript.
Browser is receiving key-token and save it in session_storage.
Each ajax request is attached by this token and then verified by php.
Is there a hole in that plan?. Maybe there is much easier/better solution. Its inspired by how php session works but with key-token instead of session id. Please help me.
I can't use session variables
What you describe sounds exactly like a session, but you're going to implement itself yourself rather than using the known, tested properties and flexibility of the standard PHP session handler. Hence even if you avoid the inherent design pitfalls, you run the risk of injecting defects in your implementation.
I would strongly urge you to use the standard PHP mechanism (although you might want to consider a more complex save handler, even if it's just enabling the multi-layer function).
Given that what you describe is no different from the PHP handler, then, yes it will work if implemented correctly - is it secure? Not from the information you've provided.
Session storage does offer the possibility of carrying out more secure operations without resorting to SSL (although HTTPS is a must have if security is important) since you can pre-share encryption keys (but the initial key negotiation is highly vulnerable).
OTOH what you describe is vulnerable to sniffing, injection and CSRF.

Public facing Authentication mechanisms for REST

I am designing a new service that would enable 'customers' to register and pay a per-use type fee for particular searches they perform. This service would be exposed using a RESTFul and SOAP interface. Typically the web service would integrate with the customer's website and then be exposed to the 'public' where anyone would be able to use the customer's website and take advantage of my web service features (which the customer would pay for but have full control of moderating the requests so they don't get charged too much).
I want to design the service that optimises the integration to make it as simple as possible. The web service API will change so creating an internal proxy to expose the web service to the public in some cases is too much of a detractor for customers. So the issue as I see it is creating a web service that balances authentication, security and integration.
Ideal
Not use OAuth
Avoid forcing the customer to create an internal proxy which re-exposes the same web service API I have already.
Be secure (token username/pass whatever and ssl)
Embed a javascript library in customer website - This would be a client Javascript library to make integration steps even easier.
The Javascript library would need to be secure enough so that the public wouldn't be able to simply grab credentials and re-purpose it themselves
Not be too hacky, if possible, so the web service doesn't have to be re-built if Firefox 87 comes out (to be released in as many minutes) and decides to fubar it.
It seems that some kinda of 3-way authentication process is needed for this to work, i.e. authenticates a particular client (in the public), the web service (the customer) and the web service.
Has anyone implemented something kind of similar and how did they tackle a situation like this?
I also understand there is a balance between what can be done, and what would violate cross-domain security, so perhaps the entire web service might be exposed by another GET only interface which would return JSONP data.
/** Addendum **/
I have since discovered a web service that does what I'm looking after. However, I am not confident I understand the implementation details entirely. So perhaps someone could also elaborate on my thinking.
The web service I discovered seems to host the Javascript on the service side. The customer would then integrate their website with the service side by including the Javascript in a script tag, but supplies a key to do so i.e.
Somehow if I add the script to my website it doesn't work. So somewhere along the line the token must be registered to a particular customer domain, and the 'client-lib.js' is actually a servlet or something similar which can somehow detect that the user from the 'public' coming in has actually originated from the 'customer' domain.
Is my thinking right? Is there some kind of http header that can be used this way? Is that safe?
Cheers
First of all - let me provide you a link to another SO question which I answered yesterday - as it gives a pretty extensive answer to a similar question-set.
I am assuming that you are going to charge the owner of the site from which the search is made, and not care so much who the individual user is who makes the search. If that's incorrect, please clarify and I will update my answer accordingly.
Clearly, in any such case, the first and foremost thing you need to do is to make sure you know which client this is on each request. And - as you said, you also want to make sure you're protecting yourself from cross-site attacks and people stealing your user's keys.
What you might consider would be the following:
Create a private key on your side - which only your service knows.
Whenever a new consumer site creates an account with you, create a new shared key which only you and they will know. I suggest creating this key by using your private key as a password, and encrypting some kind of identifier which will let you identify this particular user.
As part of your registration process, make the consumer site tell you what URI they will be using your scripts on.
Now - the way that you both do your tracking and authentication becomes fairly simple.
You mentioned providing a JS library which won't need to update every time FF updates. I suggest building that library using jQuery, or another, similarly supported cross-browser JS foundational library - and letting that wrap your AJAX.
When the client site requests your script, however, have them provide you something like:
http://www.yourdomain.com/scripts/library.js?key={shared key}
On your side, when you receive this request, check the following:
When you decrypt their shared key using your private key, you should not get gibberish. If you do - it's because their key has been altered in some way - and is not valid. This should result in a 401: Unauthorized error.
Once you decrypt the key and know which client site this is (because that's what the key contains) - check to make sure that the request is coming from the same URI that client registered with. This now protects you from someone stealing their key and injecting it into a different website.
As long as the above matches, let them download the file.
Now - when you serve the JS file, you can do so in a way that injects the key into that file - and therefore it has access to their shared key. On each of your AJAX requests, include that key so that you can identify which client this request is coming from again. In a RESTful environment, there shouldn't really be sessions - so you need this level of authentication on each post. I suggest including it as a cookie.
On your server-side - simply repeat the checks of their key on each subsequent request - and voila - you've built yourself some fairly tight security without a lot of overhead.
That said - if you expect a lot of traffic - you may want to come back to this and explore more deep security processes in the future, as rolling your own security matrix can leave unexpected holes. However - it is a good start and will get you off the ground.
Feel free to ask any questions if you need, and I will try to update my answer accordingly.
The best way to go about it is something like this (taking that you want to use javascript hosted on your server and make the include part as simple as it can be):
*user registers on your website and he receives a token for his domain
*the user can include a js file pointing to your server
the js file will be something like:
<script type="text/javascript" src="http://your.server.com/js.php?token=###&widget=xxx"></script>
or
<script type="text/javascript" src="http://your.server.com/js.js?token=###&widget=xxx"></script>
if you will use a .htaccess to redirect
*in the php file check if the token matches the requests domain, if yes echo out the js lib, if not throw a error or something
*in the js you will need to build some ajax calls to your service and stuff to manipulate the HTML (create a widget holder,show some data, etc.)
*also all the calls should have the token, and again you can use the same logic to check if token==server address
EDIT:
The REFERER is sent by the client's browser as part of the HTTP protocol, and is therefore unreliable indeed.
If you want to verify if a request is coming from your site, well you can't, but you can verify the user has been to your site and/or is authenticated. Cookies are sent in AJAX requests so you can rely on that. But this means you need to use something like oAuth
If you want to use this method, you should still check the referrer as well to prevent CSRF en.wikipedia.org/wiki/Cross-site_request_forgery
Ideally you should use a unique token per session per user (per request if you're paranoid) to prevent CSRF attacks. Checking the referrer is just security by obfuscation and not quite a real solution.

Web services API Keys and Ajax - Securing the Key

This is probably a generic security question, but I thought I'd ask in the realm of what I'm developing.
The scenario is: A web service (WCF Web Api) that uses an API Key to validate and tell me who the user is, and a mix of jQuery and application on the front ends.
On the one hand, the traffic can be https so it cannot be inspected, but if I use the same key per user (say a guid), and I am using it in both then there's the chance it could be taken and someone could impersonate the user.
If I implement something akin to OAuth, then a user and a per-app key is generated, and that could work - but still for the jQuery side I would need the app API key in the javascript.
This would only be a problem if someone was on the actual computer and did a view-source.
What should I do?
md5 or encrypt the key somehow?
Put the key in a session variable, then when using ajax retrieve it?
Get over it, it's not that big a deal/problem.
I'm sure it's probably a common problem - so any pointers would be welcome.
To make this clearer - this is my API I have written that I am querying against, not a google, etc. So I can do per session tokens, etc, I'm just trying to work out the best way to secure the client side tokens/keys that I would use.
I'm being a bit overly cautious here, but just using this to learn.
(I suggest tagging this post "security".)
First, you should be clear about what you're protecting against. Can you trust the client at all? A crafty user could stick a Greasemonkey script on your page and call exactly the code that your UI calls to send requests. Hiding everything in a Javascript closure only means you need a debugger; it doesn't make an attack impossible. Firebug can trace HTTPS requests. Also consider a compromised client: is there a keylogger installed? Is the entire system secretly running virtualized so that an attacker can inspect any part of memory at any time at their leisure? Security when you're as exposed as a webapp is is really tricky.
Nonetheless, here are a few things for you to consider:
Consider not actually using keys but rather HMAC hashes of, e.g., a token you give immediately upon authentication.
DOM storage can be a bit harder to poke at than cookies.
Have a look at Google's implementation of OAuth 2 for an example security model. Basically you use tokens that are only valid for a limited time (and perhaps for a single IP address). That way even if the token is intercepted or cloned, it's only valid for a short length of time. Of course you need to be careful about what you do when the token runs out; could an attacker just do the same thing your code does and get a new valid token?
Don't neglect server-side security: even if your client should have checked before submitting the request, check again on the server if the user actually has permission to do what they're asking. In fact, this advice may obviate most of the above.
It depends on how the API key is used. API keys like that provided by Google are tied to the URL of the site originating the request; if you try and use the key on a site with an alternate URL then the service throws and error thus removing the need to protect the key on the client side.
Some basic API's however are tied to a client and can be used across multiple domains, so in this instance I have previously gone with the practice of wrapping this API in server side code and placing some restrictions on how the client can communicate with the local service and protecting the service.
My overall recommendation however would be to apply restrictions on the Web API around how keys can be used and thus removes the complications and necessity of trying to protect them on the client.
How about using jQuery to call server side code that handles communication with the API. If you are using MVC you can call a controller action that can contain the code and API key to hit your service and return a partial view (or even JSON) to your UX. If you are using web forms you could create an aspx page that will do the API communication in the code behind and then write content to the response stream for your UX to consume. Then your UX code can just contain some $.post() or $.load() calls to your server side code and both your API key and endpoint would be protected.
Generally in cases like this though you proxy requests through the server using 'AJAX' which verifies the browser making requests is authorized to do so. If you want to call the service directly from JavaScript, then you need some kind of token system like JSON Web Tokens (JWT) and you'll have to work out cross-domain issues if the service is located somewhere other than the current domain.
see http://blogs.msdn.com/b/rjacobs/archive/2010/06/14/how-to-do-api-key-verification-for-rest-services-in-net-4.aspx for more information
(How to do API Key Verification for REST Services in .NET 4)

Ajax Security

We have a heavy Ajax dependent application. What are the good ways of making it sure that the request to server side scripts are not coming through standalone programs and are through an actual user sitting on a browser
There aren't any really.
Any request sent through a browser can be faked up by standalone programs.
At the end of the day does it really matter? If you're worried then make sure requests are authenticated and authorised and your authentication process is good (remember Ajax sends browser cookies - so your "normal" authentication will work just fine). Just remember that, of course, standalone programs can authenticate too.
What are the good ways of making it sure that the request to server side scripts are not coming through standalone programs and are through an actual user sitting on a browser
There are no ways. A browser is indistinguishable from a standalone program; a browser can be automated.
You can't trust any input from the client side. If you are relying on client-side co-operation for any security purpose, you're doomed.
There isn't a way to automatically block "non browser user" requests hitting your server side scripts, but there are ways to identify which scripts have been triggered by your application and which haven't.
This is usually done using something called "crumbs". The basic idea is that the page making the AJAX request should generate (server side) a unique token (which is typically a hash of unix timestamp + salt + secret). This token and timestamp should be passed as parameters to the AJAX request. The AJAX handler script will first check this token (and the validity of the unix timestamp e.g. if it falls within 5 minutes of the token timestamp). If the token checks out, you can then proceed to fulfill this request. Usually, this token generation + checking can be coded up as an Apache module so that it is triggered automatically and is separate from the application logic.
Fraudulent scripts won't be able to generate valid tokens (unless they figure out your algorithm) and so you can safely ignore them.
Keep in mind that storing a token in the session is also another way, but that won't buy any more security than your site's authentication system.
I'm not sure what you are worried about. From where I sit I can see three things your question can be related to:
First, you may want to prevent unauthorized users from making a valid request. This is resolve by using the browser's cookie to store a session ID. The session ID needs to tied to the user, be regenerated every time the user goes through the login process and must have an inactivity timeout. Anybody request coming in without a valid session ID you simply reject.
Second, you may want to prevent a third party from doing a replay attacks against your site (i.e. sniffing an inocent user's traffic and then sending the same calls over). The easy solution is to go over https for this. The SSL layer will prevent somebody from replaying any part of the traffic. This comes at a cost on the server side so you want to make sure that you really cannot take that risk.
Third, you may want to prevent somebody from using your API (that's what AJAX calls are in the end) to implement his own client to your site. For this there is very little you can do. You can always look for the appropriate User-Agent but that's easy to fake and will be probably the first thing somebody trying to use your API will think of. You can always implement some statistics, for example looking at the average AJAX requests per minute on a per user basis and see if some user are way above your average. It's hard to implement and it's only usefull if you are trying to prevent automated clients reacting faster than human can.
Is Safari a webbrowser for you?
If it is, the same engine you got in many applications, just to say those using QT QWebKit libraries. So I would say, no way to recognize it.
User can forge any request one wants - faking the headers like UserAgent any they like...
One question: why would you want to do what you ask for? What's the diffrence for you if they request from browser or from anythning else?
Can't think of one reason you'd call "security" here.
If you still want to do this, for whatever reason, think about making your own application, with a browser embedded. It could somehow authenticate to the application in every request - then you'd only send a valid responses to your application's browser.
User would still be able to reverse engineer the application though.
Interesting question.
What about browsers embedded in applications? Would you mind those?
You can probably think of a way of "proving" that a request comes from a browser, but it will ultimately be heuristic. The line between browser and application is blurry (e.g. embedded browser) and you'd always run the risk of rejecting users from unexpected browsers (or unexpected versions thereof).
As been mentioned before there is no way of accomplishing this... But there is a thing to note, useful for preventing against CSRF attacks that target the specific AJAX functionality; like setting a custom header with help of the AJAX object, and verifying that header on the server side.
And if in the value of that header, you set a random (one time use) token you can prevent automated attacks.

Categories

Resources