Last Updated: 2014-03-27 21:15:14 UTC
by Alex Stanford (Version: 1)
ISC user Craig Cox wrote in alerting us of a fairly sophisticated phishing campaign that is currently in progress. The website appleidconfirm.net has a seemingly realistic Apple login page that is being sent out by email.
Upon submitting what it considers valid credentials, you're redirected to the /?2 page of the site which contains another form which appears to be Apple's site:
At this stage the site is collecting personal details about the account holder which may aid them in making changes to the account or stealing the victim's identity. After submitting precious personal information, it's now time to give them your credit card information:
Only after supplying a valid Visa, Mastercard, American Express or Discover card number are you forwarded to the /?3 "Success" page.
Finally, after a just a couple of seconds on this page (before you have a chance to click one of the links which are actually a screenshot image of the real Apple site without any functional links) you are redirected to the real apple.com. At this point the attacker would have obtained all the necessary information to exploit the victim, and the victim would have absolutely no idea how this happened. Clever!
We're able to observe or infer several things through a quick analysis.
First of all, we can observe that the site is running on PHP:
In the phishing emails, they have a parameter like /e=656d61696c4076696374696d2e656d61696c appended to the URL. Thanks to insight from ISC readers, it's now clear that this is the victim's email as a tracking identifier. (Hex to ASCII)
We can also see that the site is hosted by Lycos with a domain registered just a day ago via Tucows.
Looking at the front-end of the site, we can see that the phishers didn't actually replicate the full HTML/CSS page but rather overlayed screenshots of the real apple.com with forms. This is how they manage to so accurately mimic the appearence of the target site without affording much effort into the front-end development. The background screenshot of apple.com used on their main page can be seen at http://www.appleidconfirm.net/img/main.png
Lastly, we can see that the site is not using HTTPS. This is a key differentiator from the true apple.com login page which does utilize HTTPS. Yet another reason to pay close attention to the URL bar in your browser.
Obviously it's not very difficult to craft a successful phishing campaign, but from a technological standpoint it's difficult to thwart them. So, what can we do? We should invest in awareness through education. That means reconsidering the amount of time and budgeting you set aside to train the less technical staff about phishing and social engineering. Informally, it may be time to sit down with that friend or family member who keeps sending you ads for weight loss because they have fallen victim to the latest phish. Knowledge is power.
Finally, when you see a phish in progress take the time to write a few abuse emails to the relevant providers. (and forward the phish to us!)
Last Updated: 2014-03-27 16:14:10 UTC
by Alex Stanford (Version: 1)
In writing web applications PHP developers often find themselves repeatedly calling the
htmlentities function, or the
htmlspecialchars function. These will encode the special characters of a string to their HTML entities, ensuring that output can safely avoid being executed by browser parsing engines.
The problem with this is a human one. Humans do make mistakes, and even those well aware of the consequences and solutions will eventually suffer from an oversight that results in an XSS vulnerability. How can we limit the possibility of creating vulnerabilities in such a situation?
We’ve seen a very fair share of approaches to mitigating XSS in PHP but one in particular seems to fly under the radar. PHP has a couple of configuration directives in php.ini which will automagically filter input by various sanitization and/or validation flags of your choosing. So, can we make it work like
In your (recent) default php.ini file you will find the following:
[filter] ; http://php.net/filter.default ;filter.default = unsafe_raw ; http://php.net/filter.default-flags ;filter.default_flags =
Modify these as follows:
[filter] ; http://php.net/filter.default filter.default = full_special_chars ; http://php.net/filter.default-flags filter.default_flags = 0
This will encode all $_GET, $_POST, $_COOKIE, $_REQUEST and $_SERVER values. (The original data can be accessed through the filter_input() function.)
Example In Action
As a quick proof of concept I built a simple login form that does no sanitization or encoding. The first (Username) field is pre-filled with the data you submitted if an error occurs, such as not providing any password. To exploit the first form field, I entered
"><script>alert("XSS");</script> with no password at all.
Without the php.ini configuration changes:
Now, with the php.ini configuration changes:
The input data is safely output into the form field as content instead of code, thereby mitigating the XSS vulnerability.
Do I still need to perform output encoding in my application?
Yes. This approach will handle a large portion of the repetitive cases, but some necessity for output encoding will remain. A simple example would be the importance of using the
urlencodefunction upon outputting a URL which contains user input.
Does this work for distributable web apps that run in shared hosting environments?
This approach may not always be feasible in shared environments due to the potentially limited access to php.ini directives. If you’re building distributable web apps which support running in shared environments, it is not safe to rely on this approach. However, if you’re working in an environment with a custom PHP back-end running on a dedicated server(s) this approach may be your best bet.
Won’t this result in double encoding?
Yes, quite possibly. That said, double encoding is far lower risk and more easily identifiable than XSS vulnerabilities.
How can I check that the directives are properly set before outputting anything from my application?
The following code will check that the php.ini settings are in place as expected and discontinue execution with a relevant error otherwise. It should be placed at the beginning of your application before any other code is executed.
if(ini_get('filter.default')!=='full_special_chars'||ini_get('filter.default_flags')!=='0') die('Missing and/or incorrect filter.default and/or filter.default_flags directives in php.ini');
Not a Replacement for Defense in Depth
While this approach can simplify output encoding and limit the risk of developer oversight, it should not be considered an end-all solution. You may have input data sources in your application other than PHP's superglobals. You should still consider the results of a SQL query or cURL request, for example, as potentially malicious. Finally, you should continue performing penetration testing and code reviews to catch that inevitable XSS vulnerability before they do.