PHP Securely view untrusted email content in browser - php

What would be the recommended way to securely view emails in a browser (in PHP)?
Emails are highly insecure content and desktop email software obviously implements only a very limited subset of HTML and no javascript at all to prevent attacks. But if I'd take an email HTML source and display it in a browser, javascript code and other stuff would be executed.
I thought a solution would be to send a header like this along with the email source:
header("Content-Security-Policy: sandbox");
But this would prevent me from fetching inline images from the server as I still would need a PHP session id to be transmitted to understand that the user is allowed to fetch this content.
As there are many web email clients out there I wonder if there is a best practice model.
(FYI: I try to implement my own web email tool fitting to specific needs of a larger software suite)

You can address the issue of images by not requiring authentication and then making the URLs hard to guess (ex: <img src="/resources/SomeReallyLongHardToGuessRandomString">).
More broadly though, securely displaying user generated HTML is hard. Like really hard. This is a case where you should use a library. Keep in mind that you might have a user with a browser that is too old for the Content-Security-Policy header. This browser would happily run any scripts on the page. HTML Purifier is my personal choice, but there are others. Also, keep in mind that this is a dependency you will want to update often as people are constantly discovering new bugs.
As an additional line of defense, many sites use a seperate domain for user generated content. For example Google uses googleusercontent.com. That way if something does slip by, they haven't compromised the whole application. Note that this would still be bad, as an attacker might be able to read user content they shouldn't be able to (emails in this case).

I finally decided to modify the HTML source of the email (in my php script) to serve the inline images as base64 encoded data inside the HTML source. Therefore no additional loading of images is needed:
<img src="data:image/gif;base64,R0lGODlhDgE3APf/ALJUMt3W0aMyFPTixGRHOXNXSvnu3b1sSu7SpPLduurTxapEIvbly/bq4+bAffTo31Q1J/369dGafaAtDO3o5ePd2c6Tdfz6+a9...">
This will solve the current problem of displaying emails, because then I can stay my
header("Content-Security-Policy: sandbox");
because it is one major way to prevent attacks to be successful. Additionally, for enhanced security, I plan to look again into roundcubemail and see if I find out how they handle this problem and also use HTMLpurifier to further strip the email source from possible threats.

Related

Security for user-generated content in Phonegap app using access origin

My app displays some user-generated content and I also need to allow HTML tags. What I was wondering: When setting the config.xml file to only allow my own server - is there sill a way a user/hacker could somehow steal data? On a normal webpage you could insert a script to send some data to another server. But in my case, it is impossible to get this user's data to a 3rd party server. Or am I missing something? (And yes, I will still use a php script to remove some html entities. So this is just a question about if it is possible and not about if it is a good idea to trust other users)
Any attacker in the world can send any data imaginable, valid or invalid, to your app, regardless of what controls you believe are in place, and there is nothing you can do to prevent them from sending anything.
As soon as you believe you've found a way to stop them, they can simply reverse engineer your client (step 1: download the .apk, step 2: JD-GUI, step 3: ???? step 4: pwnage) to allow them whatever capabilities they desire.
If you need to allow some HTML, but don't want to be vulnerable to XSS attacks, the traditional solution is to use HTML Purifier on output when serving data to the end user.
If HTML Purifier is too slow, check out Stauros. Stauros is narrowly focused on XSS prevention, while HTML Purifier has a broader goal of outputting standards-compliant HTML.

Is XSS possible via an #import, and if so how? Are there ways to protect against it?

We allow the use of #import via a custom CSS editor in our CMS, but I want to know if we've opened ourselves up to potential security risks by doing that, can it be used to XSS?
If so, how would that work, and further, how do we go about protecting ourselves against such an attack?
FYI, we don't actually leave the #import statements in the custom CSS when it's served, they are stripped out via preg_replace_callback() and replaced with their actual target content via file_get_contents(). This is so the CSS can still be cached and not block page loading, but potentially gives us an opportunity to filter the URL's that are used, or even the content that's returned.
EDIT:
After the quick education from #duskwuff it's obvious there are lots of potential problems with offering the service, but it looks like a similar question and answer (here: https://stackoverflow.com/a/5209050/1058733) shows that it can be done pretty safely using HTMLPurifier + CSSTidy to sanitize CSS input which would fit perfectly in our script after file_get_contents() and before caching, and additionally during the save object process for good measure.
Yes. CSS is, in general, not safe - there are a number of ways that it can be used to inject Javascript code, including but not limited to:
Dynamic properties (expression() - in Internet Explorer 7 and earlier)
DHTML behaviors (behavior - in Internet Explorer)
XBL bindings (in Gecko-based browsers)
Depending on the nature of your site, unrestricted CSS may also be used to steal passwords from your users by reformatting page content to appear like a password prompt, or to deny access to the site by reformatting or hiding vital components of the page (e.g, hiding a "log in" link).
Do not allow users to enter CSS that will be used on your site unless you're prepared to fully parse it and validate it against a whitelist of approved properties and selectors.

Serving JSON and HTML securely to JavaScript

I am thinking of secure ways to serve HTML and JSON to JavaScript. Currently I am just outputting the JSON like:
ajax.php?type=article&id=15
{
"name": "something",
"content": "some content"
}
but I do realize this is a security risk -- because the articles are created by users. So, someone could insert script tags (just an example) for the content and link to his article directly in the AJAX API. Thus, I am now wondering what's the best way to prevent such issues. One way would be to encode all non alphanumerical characters from the input, and then decode in JavaScript (and encode again when put in somewhere).
Another option could be to send some headers that force the browser to never render the response of the AJAX API requests (Content-Type and X-Content-Type-Options).
If you set the Content-Type to application/json then NO Browser will execute JavaScript on that page. This is apart of RFC-4627, and Google uses this to protect them selves. Other Application/ Content types follow similar rules.
You still have to worry about DOM Based XSS, however this would be a problem with your JavaScript, not really the content of the json. Another more exotic security concern with Json is information leakage like this vulnerability in gmail.
Make sure to always test your code. There is the Sitewatch free xss scanner, or the open source Skipfish and finally you could test this manually with a simple <script>alert(/xss/)</script>.
Instead of worrying about how you could encode the malicious code when you return it, you should probably take care that it does not even get into your database. A quick google search about preventing cross-site scripting and input validation might help you here. Cheers
If the user has to be logged in to view the web page then secure the ajax.php with the same authorization mechanism. Then a client that's not logged in cannot access ajax.php directly to retrieve the data.
I don't think your question is about validating user input, as others pointed out. You don't want to provide your JSON api to other people... right?
If this is the case then there isn't much you can do... in fact, even if you were serving HTML instead of JSON, people would still be doing HTML scraping to get what they wanted from your site (this is how Search Engine spiders work).
A good way to prevent scraping is to allow only a specific amount of downloads from an IP address. This way if someone is requesting http://yoursite.com/somejson.json more than 100 times a day, you probably know it's a scraper, and not someone visiting your page for 100 times in 1 day.
Insertion of script tags (or SQL) is only a problem if you fail to ensure it isn't at the point that it could be a problem.
A <script> tag in the middle of a comment that somebody submits will not hurt your server and it won't hurt your database. What it would hurt, if you fail to take appropriate measures, would be a page that includes the comment when you subsequently serve it up and it reaches a client browser. In order to prevent that from happening, your code that prepares the page must make sure that user-supplied content is always scrubbed before it is exposed to an unaware interpreter. In this case, that unaware interpreter is a client web browser. In fact, your client web browser really involves two unaware interpreters: the HTML parser & layout engine and the Javascript interpreter.
Another important example of an unaware interpreter is your database server. Note that a <script> tag is (almost certainly) harmless to your database, because "" doesn't mean anything in SQL. It's other sorts of input that cause problems for SQL, like quotes in strings (which are harmless to your HTML pages!).
Stackoverflow would be pretty lame if I couldn't put <script> tags in my answers, as I'm doing now. Same goes for examples of SQL Injection attacks. Recently somebody linked a page from some prominent US bank, where a big <textarea> was footnoted by a warning not to include the characters "<" or ">" in whatever you typed. Predictably, the bank was ridiculed over hundreds of Reddit comments, and rightly so.
Exactly how you "scrub" user-supplied content depends on the unaware interpreter to which you're delivering it. If it's going to be dropped in the middle of HTML markup, then you have to make sure that the "<", ">", and "&" characters are all encoded as HTML entitites. (You might want to do quote characters too, if the content might end up in an HTML element attribute value.) If the content is to be dropped into Javascript, however, you may not need to worry about HTML escaping, but you do need to worry about quotes, and possibly Unicode characters outside the 7-bit range.
For outputting safe html from php, I recommend http://htmlpurifier.org/

Using HTML Purifier to stop links to own site

I have used HTML purifier to weed out any suspect stuff coming in from my public facing WYSIWYG editor. The incoming HTML is also displayed in the public portion of the website.
I have allowed links, and I also automatically linkify URLs in plain text (using the purifier).
Is there a way to allow external links, but ban links to the same domain? E.g my domain is www.example.com
http://www.google.com will be linked.
http://www.example.com/logout/ will not be linked.
I am looking at minimizing any interference from malicious users. Should I just make my logout link a form action with a POST key/value pair to stop this from happening?
Thanks
Your login/out form should ALWAYS be POST-only.
Don't worry about a verification value, but this is a pretty important security issue - any transactions which change the state of the webserver should be POST requests. You should NEVER allow http://example.com/object?action=delete, or any variant thereof. PHP encourages bad practice in this matter, but you should ALWAYS use one or the other, and NEVER allow both.
If your users can write forms into your WYSIWYG editor, you've got far bigger problems than this.
To answer your original question, to disable internal links, use URI.HostBlacklist and be sure to set URI.MakeAbsolute:
http://htmlpurifier.org/live/configdoc/plain.html#URI.HostBlacklist

How to disable or encrypt "View Source" for my site

Is there any way to disable or encrypt "View Source" for my site so that I can secure my code?
Fero,
Your question doesn't make much sense. The "View Source" is showing the HTML source—if you encrypt that, the user (and the browser) won't be able to read your content anymore.
If you want to protect your PHP source, then there are tools like Zend Guard. It would encrypt your source code and make it hard to reverse engineer.
If you want to protect your JavaScript, you can minify it with, for example, YUI Compressor. It won't prevent the user from using your code since, like the user, the browser needs to be able to read the code somehow, but at least it would make the task more difficult.
If you are more worried about user privacy, you should use SSL to make sure the sensitive information is encrypted when on the wire.
Finally, it is technically possible to encrypt the content of a page and use JavaScript to decrypt it, but since this relies on JavaScript, an experienced user could defeat this in a couple of minutes. Plus all these problems would appear:
Search engines won't be able to index your pages...
Users with JavaScript disabled would see the encrypted page
It could perform really poorly depending the amount of content you have
So I don't advise you to use this solution.
You can't really disable that because eventually the browser will still need to read and parse the source in order to output.
If there is something SO important in your source code, I recommend you hide it on server side.
Even if you encrypt or obfuscate your HTML source, eventually we still can eval and view it. Using Firebug for instance, we can see source code no matter what.
If you are selling PHP software, you can consider Software as a Service (SaaS).
So you want to encrypt your HTML source. You can encrypt it using some javascript tool, but beware that if the user is smart enough, he will always be able to decrypt it doing the same thing that the browser should do: run the javascript and see the generated HTML.
EDIT: See this HTML scrambler as an example on how to encrypt it:
http://www.voormedia.com/en/tools/html-obfuscate-scrambler.php
EDIT2: And .. see this one for how to decrypt it :)
http://www.gooby.ca/decrypt/
Short answer is not, html is an open text format what ever you do if the page renders people will be able to see your source code. You can use javascript to disable the right click which will work on some browsers but any one wanting to use your code will know how to avoid this. You can also have javascrpit emit the html after storing this encoded, this will have bad impacts on development, accessibility, and speed of load. After all that any one with firebug installed will still be able to see you html code.
There is also very really a lot of value in your html, your real ip is in your server code which stays safe and sound on your server.
This is fundamentally impossible. As (almost) everybody has said, the web browser of your user needs to be able to read your html and Javascript, and browsers exist to serve their users -- not you.
What this means is that no matter what you do there is eventually going to be something on a user's machine that looks like:
<html>
<body>
<div id="my secret page layout trick"> ...
</div>
</body>
</html>
because otherwise there is nothing to show the user. If that exists on the client-side, then you have lost control of it. Even if you managed to convince every browser-maker on the planet to not make that available through a "view source" option -- which is, you know, unlikely -- the text will still exist on that user's machine, and somebody will figure out how to get to it. And that will never happen, browsers will always exist to serve their users before all others. (Hopefully)
The same thing is true for all of your Javascript. Let me say it again: nothing that you send to a user is secure or secret from that user. The encryption via Javascript hack is stupid and cannot work in any meaningful sense.
(Well, actually, Flash and Silverlight ship binaries, but I don't think that they're encrypted. So they are at the least irritating to get data out of.)
As others have said, the only way to keep something secret from your users is to not give it to them: put the logic in your server and make sure that it is never sent. For example, all of the code that you write in PHP (or Python/Ruby/Perl/Java/C...) should never be seen by your users. This is e.g. why Google still has a business. What they give you is fundamentally uninteresting compared to what they never send to you. And, because they realize this, they try to make most things that they send you as open as useful as possible. Because it's the infrastructure -- the Terrabyte-huge maps database and pathfinding software, as opposed to the snazzy map that you can click and drag -- that you are trading your privacy for.
Another example: I'm not sure if you remember how many tricks people employed in the early days of the web to try and keep people from saving images to disk. When was the last time you ran across one of those? Know why? Because once data is on your user's machine, she controls it. Not you.
So, in short: if you want to keep something secret from your user, don't give it to her.
You cant. The browser needs the source to render the page. If the user user wishes the user may have the browser show the source. Firefox can also show you the DOM of the page. You can obfuscate the source but not encrypt or lock the user out.
Also why would you want this, it seem like a lame ass thing to do :P
I don't think there is a way to do this. Because if you encrypt how the browser will understand the HTML?
No. The browsers offer no ability for the HTML/javascript to disable that feature (thankfully). Plus even if you could the HTML is still transmitted in plain text ready for a HTTP sniffer to read.
Best you could do would be to somehow obscure the HTML/javascript to make it hard to read. But then debuggers like Firebug and IE 8's debugger will reconstruct it from the DOM making it easy to read,
You can, in fact, disable the right click function. It is useless to do so, however, as most browsers now have built in inspector tools which show the source anyway. Not to mention that other workarounds (such as saving the page, then opening the source, or simply using hotkeys) exist for viewing the html source. Tutorials for disabling the right click function abound across the web, so a quick google search will point you in the right direction if you fell an overwhelming urge to waste your time.
There is no full proof way.
But You can fool many people using simple Hack using below methods:
"window.history.pushState()" and
adding oncontextmenu="return false" in body tag as attribute
Detail here - http://freelancer.usercv.com/blog/28/hide-website-source-code-in-view-source-using-stupid-one-line-chinese-hack-code
You can also use “javascript obfuscation” to further complicate things, but it won’t hide it completely.
“Inspect Element” can reveal everything beyond view-source.
Yes, you can have your whole website being rendered dynamically via javascript which would be encrypted/packed/obfuscated like there is no tomorrow.

Categories