TypoScript Security

02.07.2011

TypoScript is a powerful „language“ built into the TYPO3 CMS which is used to control and configure the output of your website. With that power at the tip of your fingers, you can do amazing things. But like in every other part of our lives: with power comes responsibility.

TypoScript is a powerful „language“ built into the TYPO3 CMS which is used to control and configure the output of your website. With that power at the tip of your fingers, you can do amazing things. But like in every other part of our lives: with power comes responsibility.

My impression is that it is not widely known, that you can introduce major security problems in your TYPO3 installation if you do not properly take care of user input which is accessible through TypoScript.

In this post I will explain what user input is and how you have to deal with it within TypoScript.

User Input

So what kind of user input is accessible through TypoScript? Let’s look at the getText data type which you can access through „stdWrap.data“. You can do something like this:

lib.user = TEXT

lib.user.data = GP : stuff

„GP“ is short for GET/POST. You can access URL parameter values with it.

E.g.: http://your.site/?stuff=user-input „user-input“ will be the value for „lib.user“

In this example user input is something every website visitor can enter and/or modify.

This is also possible:

lib.user = TEXT

lib.user.data = page : title

In this example „lib.user“ holds the value of the title of the current page. In this case the user input is provided by your website editors.

Another example for user input by website editors is this:

lib.menu = HMENU

lib.menu.1 = TMENU

lib.menu.1.NO = 1

I guess something like this is found in pretty much every TYPO3 installation, because it creates a menu out of the pages in the pagetree :)

Why is User Input dangerous? Bad Examples:

User Input is dangerous, because you (as a website integrator) have no control over what exactly a user decide to provide as input.

Let’s revisit our „lib.user“ example from above and extend it a little bit, so that the URL parameter value is shown on our website:

You have introduced a Cross Site Scripting vulnerability (XSS) in your TYPO3 installation by only using TypoScript. (If you want to test this use Firefox, because at least Safari and Internet Explorer have a XSS protection which prevents the JavaScript from being executed)

Now look at this example:

lib.breadcrumb = CONTENT

lib.breadcrumb {

table = tt_news render

Obj = TEXT render

Obj.field = title

select {

pidInList = 5

andWhere {

data = GP:tx_ttnews|tt_news

wrap = uid=|

}

}

}

This TypoScript snippet is used to show the title of the currently shown tt_news article in the breadcrumb. DON’T DO THAT LIKE THIS!

It introduces a SQL Injection vulnerability, which is one of the most severe security issues you can have on your website. Website visitors can now forge SQL and provide it as a URL parameter to get everything out of your TYPO3 installation.

How to avoid such mistakes?

Let’s fix the XSS vulnerabilities first by adding the following line:

lib.user.htmlSpecialChars = 1

This line is crucial here. It escapes encodes the user input for HTML output. If you do not want your editors to enter arbitrary HTML and JavaScript code on your TYPO3 installations (which is recommended) fix your TypoScript code for menus:

lib.menu.1.NO.stdWrap.htmlSpecialChars = 1

And of course do not allow SQL Injections by transforming the user input to an integer, before passing it to the SQL query by TypoScript:

lib.breadcrumb.select.andWhere.intval = 1

Jigal van Hemert wrote an excellent article on how to escape user input for TypoScript SQL queries, if the values are not supposed to be integer but strings.

Conclusion

It might tricky sometimes, especially when it comes to more complex TypoScript. But if you respect the following two rules, you should be on the safe side.

Every time you use the stdWrap property „data“, „dataWrap“ , „insertData“ etc. think about where the data comes from and where it goes.

Escape the data properly depending on where the data goes (htmlSpecialChars for HTML output, intval or marker usage for SQL)