This isn't a language specific question, but I am using PHP5.
I am working on a project that has some amount of PII. Legally we are required to secure this data from hacking attempts, and because of that I have been researching best practices for defending common attack types. Obviously all database calls are using parameterized queries, and all data provided by the user is sanitized to prevent injection. I have also implemented sessions and methods to prevent session hijacking.
When it comes to defending against XSS attacks on forms, best practice seems to be to include a hidden input with a form token, then after the post to check the tokens match. There are further ways to make this more secure.
I have imagined one type of attack and haven't found a solution for it. What if a malicious site loads a hidden iframe pointed at my site (eg, view-member.php?id=1234) and because the victim user is logged into my site, their session continues in that iframe. What is stopping this malicious site from iterating through the IDs and ripping the data to get ahold of PII? Should I be creating a unique token for each page view, and checking that token when the page loads?
I am not 100% sure, but assuming my site is using HTTPS, the browser should warn the user and/or prevent the connection. Is that correct? Is that enough security?
In fact, everytime you present a form or any kind of interaction, you should include a randomized, verifiable piece of information that changes every time. This is not for preventing XSS but CSRF: https://en.wikipedia.org/wiki/Cross-site_request_forgery
The main problem is: An attacker can just send automated requests to your input-handling script without going through the "pain" of filling in your form manually (or even visit your page).
However, you won't prevent XSS attacks with this technique, as XSS attacks are mainly user input containing executable code (javascript) that is not filtered by the input validation. So to prevent XSS as well, you should always make sure not to deliver unfiltered user-generated content anywhere.
HTTPS won't help you in either case unless you use client-side certificates that allow access to your website only from trusted clients. HTTPS mainly acts as a transmission scrambler and identity verifier but does not prevent a bot from sending valid (but malicious) data to your form.
Hosting a website in an iFrame does not grant the attacker the permission to read cookies or information from the target page (that would be awful) as long as you follow the same-origin policy: https://en.wikipedia.org/wiki/Same-origin_policy
With this, only domains you whitelist will get access to information hosted on your page.
Related
All the examples of CSRF exploits tend to be against pages which process the incoming request.
If the page doesn't have a form processing aspect do I need to worry about CSRF ?
The situation I'm looking # :
the page in question contains sensitive data
as such users need to establish a session to view the page
... my understanding is that a malicious page will be able to redirect a client to this page by embedding a link to it, however since there's no action on the target to perform there's no harm that can result, right ?
There's no way for said malicious site can view the sensitive page, correct ?
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility, and so I'd like to avoid them if possible.
There's no way for said malicious site can view the sensitive page, correct ?
Correct in terms of CSRF.
The blog you linked is talking about Cross-Origin Script Inclusion, which is a different animal. To be vulnerable to XOSI your sensitive page would have to be interpretable as JavaScript, and you'd have to be either serving it without a proper HTML MIME type, or the browser would have to be an old one that didn't enforce type checking on scripts.
You might also potentially worry about clickjacking, where another site includes yours in a frame and overlays misleading UI elements. There are some sneaky ways that has been used to extract sensitive data (see the next generation clickjacking paper and this amusing info leak in Firefox) so you may wish to disallow framing with the X-Frame-Options header.
Why I ask: I want the url to the page with sensitive data to have a 'simple' URL which allows people to email the link to other people (who will in turn need a session to view the page). The token-based solution I've seen for most CSRF solutions remove this possibility
You definitely shouldn't be putting a CSRF token in a GET URL. Apart from the ugliness, and breakage of navigation, URLs are easy to leak from the browser or other infrastructure, potentially compromising the confidentiality of the token.
Normal practice is not to put CSRF protection on side-effect-free actions.
In general, CSRF is independent from whether the request causes any side effects or not. The CWE describes CSRF (CWE-352) as follows:
The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
So CSRF is a general request intention authenticity problem.
However, although CSRF is not really feasible without any effects other than data retrieval as the same-origin policy restricts the attacker from accessing the response, the attacker could exploit another vulnerability to profit from retrieval-only requests as well and gain access to sensitive data.
I have been looking into the OWASP recommendation to prevent CSRF attacks (https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet).
Now, what I do not understand is how this would prevent an attack that is a combination of an XSS and a CSRF attack. Let's say we have the following attack scenario:
Attacker is able to perform a stored XSS attack, so that the script that the attacker inserts on the website is executed everytime a user visits the page.
This script will completely redesign the DOM, for example instead of the original form where a user needs to give some irrelevant information, the attacker's script redesigns it so that this form will be redesigned to a form where a user with admin privileges is added. Note that the user will not see this, as the labels of the fields will remain the same. Only the POST will be different.
The attacker knows that this website uses anti-CSRF tokens. Looking at the OWASP recommendation: '(..)application should include a hidden input parameter with a common name such as "CSRFToken"', the attacker knows that most websites will have a hidden field with this id somewhere on the page.
the attacker makes sure the value of this field is also submitted in the fake POST. Even though the attacker doesn't know the value of this hidden field, it can specify in the POST that this value should be sent with the request. This is possible, as the user's DOM has been modified, the request will come from the user's browser, the user's cookies will also be sent with the request.
The user submits the form, and the fake user is created.
It seems to me this cannot be prevented by just using a CSRF token. Or is an implicit assumption of the synchronizer pattern that XSS attacks have been neutralized?
Or is an implicit assumption of the synchronizer pattern that XSS attacks have been neutralized?
Yes. If your website is attacked in this way then it is an XSS attack rather than CSRF. CSRF simply means the request is made "cross site", whereas in your example the request is on the same site - it is just the scripting that is "cross site".
My web application displays some sensitive information to a logged in user. The user visits another site without explicitly logging out of my site first. How do I ensure that the other site can not access the sensitive information without accept from me or the user?
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag and read the side effects. I could continue on building a blacklist, but I do not want to enumerate what is unsafe. I want to know what is safe, but I can not find any documentation of this.
UPDATE: In my example JavaScript from the victim site was executed on the attacker's site, not the other way around, which would have been Cross Site Scripting.
Another example is images, where any other site can read the width and height, but I don't think they can read the content, but they can display it.
A third example is that everything without an X-Frame-Options header can be loaded into an iframe, and from there it is possible to steal the data by tricking the user into doing drag-and-drop or copy-and-paste.
The key point of Cross Site Attack is to ensure that your input from user which is going to be displayed, is legal, not containing some scripts. You may stop it at the beginning.
If for example my sensitive data is in JavaScript format, the other site can include it in a script tag
Yep! So don't put it in JavaScript/JSONP format.
The usual fix for passing back JSON or JS code is to put something unexecutable at the front to cause a syntax error or a hang (for(;;); is popular). So including the resource as a <script> doesn't get the attacker anywhere. When you access it from your own site you can fetch it with an XMLHttpRequest and chop off the prefix before evaluating it.
(A workaround that doesn't work is checking window.location in the returned script: when you're being included in an attacker's page they have control of the JavaScript environment and could sabotage the built-in objects to do unexpected things.)
Since I did not get the answer I was looking for here, I asked in another forum an got the answer. It is here:
https://groups.google.com/forum/?fromgroups=#!topic/mozilla.dev.security/9U6HTOh-p4g
I also found this page which answers my question:
http://code.google.com/p/browsersec/wiki/Part2#Life_outside_same-origin_rules
First of all like superpdm states, design your app from the ground up to ensure that either the sensitive information is not stored on the client side in the first place or that it is unintelligible to a malicious users.
Additionally, for items of data you don't have much control over, you can take advantage of inbuilt HTTP controls like HttpOnly that tries to ensure that client-side scripts will not have access to cookies like your session token and so forth. Setting httpOnly on your cookies will go a long way to ensure malicious vbscripts, javascripts etc will not read or modify your client-side tokens.
I think some confusion is still in our web-security knowledge world. You are afraid of Cross Site Request Forgery, and yet describing and looking for solution to Cross Site Scripting.
Cross Site Scripting is a vulnerability that allows malicious person to inject some unwanted content into your site. It may be some text, but it also may be some JS code or VB or Java Applet (I mentioned applets because they can be used to circumvent protection provided by the httpOnly flag). And thus if your aware user clicks on the malicious link he may get his data stolen. It depends on amount of sensitive data presented to the user. Clicking on a link is not only attack vector for XSS attack, If you present to users unfiltered contents provided by other users, someone may also inject some evil code and do some damage. He does not need to steal someone's cookie to get what he wants. And it has notnig to do with visiting other site while still being logged to your app. I recommend:XSS
Cross Site Request Forgery is a vulnerability that allows someone to construct specially crafted form and present it to Logged in user, user after submitting this form may execute operation in your app that he didin't intended. Operation may be transfer, password change, or user add. And this is the threat you are worried about, if user holds session with your app and visits site with such form which gets auto-submited with JS such request gets authenticated, and operation executed. And httpOnly will not protect from it because attacker does not need to access sessionId stored in cookies. I recommend: CSRF
I have a question about XSS
Can forms be used as a vector for XSS even if the data is not stored in the database and used at a later point?
i.e. in php the code would be this:
<form input="text" value="<?= #$_POST['my_field'] ?>" name='my_field'>
Showing an alert box (demonstrate that JS can be run) on your own browser is trivial with the code above. But is this exploitable across browsers as well?
The only scenario I see is where you trick someone into visiting a certain page, i.e. a combination of CSRF and XSS.
"Stored in a database and used at a later point": the scenario I understand about CSS is where you're able to post data to a site that runs JavaScript and is shown on a page in a browser that has greater/different privileges than your own.
But, to be clear, this is not wat I'm talking about above.
Yes, it's still an attack vector.
What you need to consider is:
Can an authenticated user be tricked into viewing this page with maliciously-crafted data?
The answer is this case is yes (assuming you have authenticated users). Because it's possible to direct someone to your site and pass in malicious variables to that field.
Yeah, it's still an attack vector, although impact is more situational.
Here's a contrived scenario that expands on previous answers if the form requires authentication to reach (and is easier if the site doesn't care if forms are submitted via POST or GET):
1) Attacker uses CSRF to login the victim using the attacker's credentials (e.g. <iframe src=http://../login?id=...&pass=..."></iframe>). This way the attacker brings the form to the victim and it doesn't matter if the victim doesn't have an account.
2) Attacker uses another CSRF to execute XSS against the form, which asks the victim for some credentials, etc. (This is where some convincing social engineering needs to occurr or the attacker has some useful JavaScript to use within the browser's Same Origin for the site.)
Another contrived scenario in which the vulnerable form performs some important action, like transfer money between accounts:
0) Vulnerable form uses hidden form fields with random values to prevent CSRF. The attacker doesn't know what the values are and can't set up a proper attack.
1) Attacker creates a CSRF payload that includes JavaScript to read a form's random csrf tokens (i.e. pull them from the browser's DOM).
2) Victim logs into site.
3) Attacker lures victim to CSRF payload, CSRF bootstraps the form request with the correct csrf tokens because it's executing in the victim's browser, within the victim site's Same Origin, and using the victim's auth session. The attacker doesn't need to know the csrf tokens, just be able to manipulate the form fields that store them.
4) Attacker benefits from having the victim submit the form -- no pop-ups or social engineering necessary aside from luring the victim to the CSRF payload, but the form needs to do something "useful" for the attacker.
i think what you are mean is, since User 2 cannot be showing previous data added by User 1, so can the XSS happen? So if User 1 hack the URL so that some $_GET params got displayed on the webpage as well (and then even, change it to a tinyurl), and spread this URL saying that it is really worthwhile to see this page, etc, then it might be possible.
So it is still better to escape all params when displaying the page.
That is absolutely a valid form of XSS. XSS comes in two forms - stored and reflected. Reflected is much more common, but stored has the potential to be more damaging. Reflected XSS is usually used as part of a social engineering attack. An attacker creates a URL like the following:
http://host.com/page.php?my_field=malicious_code
They will often shorten the URL with tinyutl or bit.ly, and get it out with the usual social engineering methods (email, message board, twitter, hijacked facebook accounts, etc.)
Is it acceptable to submit from an http form through https? It seems like it should be secure, but it allows for a man in the middle attack (here is a good discussion). There are sites like mint.com that allow you to sign-in from an http page but does an https post. In my site, the request is to have an http landing page but be able to login securely. Is it not worth the possible security risk and should I just make all users go to a secure page to login (or make the landing page secure)?
Posting a form from an http page to an https page does encrypt the data in the form when it is transmitted in the most simple terms. If there is a man-in-the-middle attack, the browser will warn you.
However, if the original http form was subjected to man-in-the-middle and the https post-back address was modified by the attacker, then you will get no warning. The data will still actually be encrypted, but the man-in-the-middle attacker would be able to decrypt (since he sent you the key in the first place) and read the data.
Also, if the form is sending things back through other means (scripted connections) there may be a possibility of unencrypted data being sent over the wire before the form is posted (although any good website would never do this with any kind of sensitive data).
Is there any reason not to use HTTPS for the entire transaction? If you can't find a very good one, use it!
It's arguably simpler than switching protocols.
The MITM risk is real.
Following your link, the user "Helios" makes an excellent point that using 100% HTTPS is far less confusing to the user.
This kind of thing is popping up all over the net, especially in sites for which login is optional. However, it's inherently unsafe, for quite subtle reasons, and gives the user a false sense of security. I think there was an article about this recently on codinghorror.com.
The danger is that while you sent your page with a post target of "https://xxx", the page in which that reference occurs is not secure, so it can be modified in transit by an attacker to point to any URL the attacker wishes. So if I visit your site, I must view the source to verify my credentials are being posted to a secure address, and that verification has relevance only for that particular submit. If I return tomorrow, I must view source again, since that particular delivery of the page may have been attacked and the post target subverted - if I don't verify every single time, by the time I know the post target was subverted, it's too late - I've already sent my credentials to the attacker's URL.
You should only provide a link to the login page; and the login page and everything thereafter should be HTTPS for as long as you are logged in. And, really, there is no reason not to; the burden of SSL is on the initial negotiation; the subsequent connections will use SSL session caching and the symmetric crypto used for the link data is actually extremely low overhead.
IE Blog explains: Critical Mistake #1: Non-HTTPS Login pages (even if submitting to a HTTPS page)
How does the user know that the form is being submitted via HTTPS? Most browsers have no such UI cue.
How could the user know that it was going to the right HTTPS page? If the login form was delivered via HTTP, there's no guarantee it hasn't been changed between the server and the client.
Jay and Kiwi are right about the MITM attack. However, its important to note that the attacker doesn't have to break the form and give some error message; the attacker can instead insert JavaScript to send the form data twice, once to him and once to you.
But, honestly, you have to ask, what's the chance of an attacker intercepting your login page and modifying it in flight? How's it compare to the risk of (a) doing a MITM attack strait on the SSL session, and hoping the user presses "OK" to continue; (b) doing the MITM on your initial redirect to SSL (e.g., from http://example.com to https://example.com) and redirecting to https://doma1n.com instead, which is under the attacker's control; (c) You having a XSS, XSRF, or SQL injection flaw somewhere on your site.
Yes, I'd suggest running the login form under SSL, there isn't any reason not to. But I wouldn't worry much if it weren't, there are probably much lower hanging fruit.
Update
The above answer is from 2008. Since then, a lot of additional threats have become apparent. E.g., access sites from random untrusted networks such as WiFi hotspots (where anyone nearby may be able to pull off that attack). Now I'd say yes, you definitely should encrypt your login page, and further your entire site. Further, there are now solutions to the initial redirect problem (HTTP Strict Transport Security). The Open Web Application Security Project makes several best practices guides available.
This post is the key one. Yes, if the user's data is sent to you, it will have arrived somewhere securely. But there is no reason to believe that somewhere will be your site. The attacker isn't just going to get to listen to the data moving in each direction at this point. He'll be the other end of the user's session. The your site is just going to think the user never bothered to submit the form.
For me (as an end-user), the value of an HTTPS session is not only that the data is encrypted, but that I have verification that the page I'm typing my super-secrets into has come from the place I want it to.
Having the form in a non-HTTPS session defeats that assurance.
(I know - this is just another way of saying that the form is subject to an MITM attack).
No, it's not secure to go from HTTP to HTTPS. The originating and resulting points of the request must be HTTPS for the secure channel to be established and utilized.
Everyone suggesting that you provide only a link to the login page seems to be forgetting that the link could easily be changed using a MITM attack.
One of the biggest things missed out in all of the above is that there is a general trend to place a login on a home page (Huge trend in User Experience Trends).
The big problem here is that Google does not like to search secure pages with good reason, so all those Devs who are wondering why not make it all secure, well if you want your page invisible to Google, secure it all. Else, the second best option to post from http to https is the lesser of two evils at this point?
I think the main consideration of this question has to do with the URL that users know and the protocol scheme (http:)that browsers substitute by default.
In that case, the normal behavior of a site that wants to ensure an encrypted channel is to have the http://home-page redirect to https://home-page. There is still a spoofing / MitM opportunity, but if it is by DNS poisoning, the risk is no higher than if one starts out with the https: URL. If a different domain name comes back, you need to worry then.
This is probably safe enough. After all, if you are subject to a targetted MitM, you might as well start worrying about keyboard loggers, your local HOSTS file, and all sorts of other ways of finding out about your secure transactions involving your system already being owned.