13.1. Locking down your system
Interchange has lots of built-in protections to make developing your catalogs pretty care-free. But it will definitely pass you the ammo to shoot yourself in the foot, as will any templating system that has power. So you have to be careful, as you do in any scripting environment.
Most of the protections have to do with:
- Tags like [cgi foo], [data ...] and such are not reparsed for tags.
- The [value foo] tag never allows a left square bracket to be output.
- Safe is used for Perl, which means that arbitrary perl code which reads/writes or uses IO is not possible.
- The Interchange files don't need to be readable or writable by any other user ID, so CGI/PHP programs run by the web server can't get at them.
- Dangerous operations are allowed only via global UserTag, and not by catalog UserTag.
But there are ways that user-entered data could end up getting parsed for tags. The most common breach is to take possibly tainted user data entered into a form and put it in a database without filtering it first. There are several ways to do that:
- For user-entered form fields like name, address, etc you should always use the [value ...] tag to display them.
- You can filter lists of variables automatically with
Filter name textarea_put Filter address textarea_put Filter comments textarea_put Filter email textarea_put
- You can prevent problems in some cases by using the data tag (i.e. [data table=foo col=bar key="[item-param something]"]) which is not reparsed for tags as [item-data ....] is. This is not foolproof unless you control the key in some fashion -- in most cases, you will use [data session username] or something you control.
- You should never put user-entered data directly in a Scratch variable, which can be called with mv_click and mv_check.
- Process all user-entered data before putting it in a database that could be displayed in a page later. Or process it before it is displayed.
- When putting data inside a container tag, the output of which is reparsed for more tags by default, consider setting reparse=0.
There are other ways to nail down your system and make it more difficult to have a security problem.
- Use the WRITE_CONTROL database settings.
Database products WRITE_CONTROL 1
It is the default for MV DBM databases (i.e. you have to have a [flag type=write table=foo] to write) but not for SQL.
- Set "NoAbsolute Yes" in interchange.cfg, it prevents [file /some/dir] or [include /some/rogue/file] from being used. NOTE: This is the default starting in IC 4.7.x.
- Split the admin server onto a different IC iteration from your production catalog, and disable the UI for the production catalog. That allows you to set the pages/ directory to be read-only for the production server, and to put WRITE_CONTROL in the production catalog_after.cfg or etc/<catalog id>.after file.
You could also use a different username to access the SQL data, and make the production server username have read-only access.
You can use a different UID for the admin server iteration, and make all directories except products/, upload/, tmp/, session/, and logs/ read-only for the production server UID.
- Make as much stuff read-only as you can. Develop a script which sets things read-write while you are admin-ing, and read-only otherwise.
- Always make ICDIR/*.cfg, ICDIR/bin/*, and ICDIR/lib/* read-only for the IC user.
- Don't let the interchange daemon user ID have read or write permission on things it doesn't need.
- Never use AllowGlobal in production if you have user-entered data going into a database. (AllowGlobal is not the default, so many people won't know what it is -- see Interchange Configuration.)
The UI does the proper write flagging, so this should have no effect on it.
AUTHORS NOTE: I should have made WRITE_CONTROL the default for SQL in MV4, my bad. As long as MV3 compatibility was as poor as it turned out to be, I should have gone for it.
All in all, Interchange has been proven to be securable over time. But we all have to do our part and think about what we are doing with user-entered data.