Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sanitize user defined CSS in PHP

I want to allow users to use their own stylesheets for thei profiles on my forum, but I'm afraid of possible security vulnerabilities. Does anyone have any tips for sanitizing CSS?

Basic process: User enters CSS into form -> Save to DB -> Output as inline CSS

like image 532
Gio Borje Avatar asked Jul 13 '10 21:07

Gio Borje


2 Answers

HTMLPurifier with CSSTidy does what you're looking for.

HTMLPurifier is primarily designed for sanitizing HTML, but also has an option to extract style blocks with CSSTidy.

There's an example in the HTMLPurifier docs (but alas, I've used up my two links per post.)

Here's another:

require_once './htmlpurifier/library/HTMLPurifier.auto.php';
require_once './csstidy/class.csstidy.php';

// define some css
$input_css = "
    body {
        margin: 0px;
        padding: 0px;
        /* JS injection */
        background-image: url(javascript:alert('Injected'));
    }
    a {
        color: #ccc;
        text-decoration: none;
        /* dangerous proprietary IE attribute */
        behavior:url(hilite.htc);
        /* dangerous proprietary FF attribute */
        -moz-binding: url('http://virus.com/htmlBindings.xml');
    }
    .banner {
        /* absolute position can be used for phishing */
        position: absolute;
        top: 0px;
        left: 0px;
    }
";

// Create a new configuration object
$config = HTMLPurifier_Config::createDefault();
$config->set('Filter.ExtractStyleBlocks', TRUE);

// Create a new purifier instance
$purifier = new HTMLPurifier($config);

// Turn off strict warnings (CSSTidy throws some warnings on PHP 5.2+)
$level = error_reporting(E_ALL & ~E_STRICT);

// Wrap our CSS in style tags and pass to purifier. 
// we're not actually interested in the html response though
$html = $purifier->purify('<style>'.$input_css.'</style>');

// Revert error reporting
error_reporting($level);

// The "style" blocks are stored seperately
$output_css = $purifier->context->get('StyleBlocks');

// Get the first style block
echo $output_css[0];

And the output is:

body {
    margin:0;
    padding:0;
}

a {
    color:#ccc;
    text-decoration:none;
}

.banner {
}
like image 110
dleavitt Avatar answered Oct 07 '22 18:10

dleavitt


Define the classes yourself, and make a GUI to apply color and other properties to each class, use the same approach twitter does for that.

alt text http://grab.by/grabs/3217158e9c48538eb127fb1678dab6ae.png

Of course, this would only work if your layout is fixed and defined by the admin, not the user.

like image 30
Germán Rodríguez Avatar answered Oct 07 '22 19:10

Germán Rodríguez