Как предотвратить атаки XSS в Django REST API CharFields? - PullRequest
2 голосов
/ 03 февраля 2020

В настоящее время я работаю над приложением, использующим Django 2.2 с djangorestframework 3.9.2. Я знаю, что Django сам по себе обеспечивает хорошую защиту от SQL инъекций или в контексте отображения контента в django шаблонах (XSS), но я заметил, что, хотя я использую Django REST API, все CharFields в моих моделях не очищаются автоматически.

Примечание. Этот вопрос не относится к django шаблонам.

Например, для модели прямых сообщений (message/models.py):

class Message(models.Model):
    sender = models.ForeignKey(...)
    receiver = models.ForeignKey(...)
    message = models.CharField(max_length=1200)
    timestamp = models.DateTimeField(...)
    is_read = models.BooleanField(default=False)

Фактически не предоставляет потенциальному злоумышленнику возможность напечатать сообщение, содержащее <script>alert("Attack");</script>. Он будет сохранен в базе данных и будет обслуживаться REST API как действительный HTML, что позволяет выполнять атаку межсайтовых сценариев.

Это ожидаемое поведение? Как это можно предотвратить?

Ответы [ 2 ]

4 голосов
/ 03 февраля 2020

Django (или DRF) не позволяет избежать попадания html / текстового содержимого в базу данных. Текст экранируется только при его отображении с использованием системы шаблонов (если только он не помечен как безопасный в какой-то момент).

Причина этого в том, что Django на самом деле не знает, для чего вы будете использовать этот текст , Для некоторых случаев использования может быть вполне приемлемо хранить HTML, включая теги сценариев.

Если вы ищете способ дезинфицировать входные данные, прежде чем они попадут в базу данных, я могу порекомендовать библиотеку Mozilla * bleach: https://github.com/mozilla/bleach

Я не использовал django-bleach (https://django-bleach.readthedocs.io/), но кажется удобным способом интегрировать bleach в Django .

2 голосов
/ 03 февраля 2020

Вы можете использовать escape() метод в валидации сериализатора:

from django.utils.html import escape

class MySerializer:
    def validate_myfield(self, value):
        return escape(value)
...