如何使用Django + jQuery修复XSS?

时间:2016-04-14 07:37:41

标签: jquery python ajax django xss

enter image description here

我写了以下代码,这些代码用于Ajax的消息功能。 当我填写

<script>alert("Django+Ajax");</script> 

在表单中提交,警报出现在我的浏览器上。 我想逃避输出,但我不知道该怎么做。 你能给我一些建议吗?

message.html

<html>
<head>
    <style type="text/css">
        div#message_form {
            display: none;
            margin: 25px;
            padding: 25px;
            background: #eee;
            width: 200px;
            height: 180px;
        }
    </style>
</head>
<body>

    <input type="button" id="message" value="message">  <br />
    <div id="message_form">
        <form id="post_message" method="POST" action="">
            {% csrf_token %}
            title: {{ form.title }}  <br />
            body: {{ form.body }}  <br />
            <input type="submit" value="send">
            <input type="reset" value="reset">
        </form>
    </div> 

    <div id="get_title"></div>
    <div id="get_body"></div>


    {% load staticfiles %}
    <script type="text/javascript" src="{% static "myapp/js/jQuery.js" %}"></script>
    <script type="text/javascript" src="{% static "myapp/js/django_ajax.js" %}"></script>
    <script type="text/javascript">

    $(function() {

        $('#message').on('click', function() {
            $('#message_form').slideToggle();   
        });

        $('#message_form').submit(function(e) {
            e.preventDefault();
            var url = location.href;
            var arr = url.split('/');
            $.ajax({
                type: 'POST',
                url: '/myapp/deal_message/',
                dataType: 'json',
                data: {
                    'title': $('#title').val(),
                    'body': $('#body').val(),
                    'target_id': arr[arr.length-2],
                },
                success: function(data, dataType) {
                    $('#get_title').append(data.title);  <!-- ### HERE ### -->
                    $('#get_body').append(data.body);  <!-- ### HERE ### -->
                    $('#post_message')[0].reset();
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {
                    alert('Error: ' + errorThrown);
                },
            });
            return false;
        });

    });

    </script>
</body>
</html>

forms.py

class Message(forms.ModelForm):

    class Meta:
        model = Message

        fields = ('title', 'body',)
        widgets = {
            'title': forms.TextInput(attrs={'id': 'title', 'placeholder': 'message title'}),
            'body': forms.Textarea(attrs={'rows': 4, 'cols': 18, 'id': 'body', 'placeholder': 'message body'}),
        }
        labels = {field:field for field in fields}
        help_texts = {}
        error_messages = {}

views.py

#@login_required(login_url='/')
def message(request, owner_id):
    errors = ""

    from myapp.forms import Message
    view = { 
        'errors': errors,
        'form': Message,
    }
    template = 'myapp/message/message.html'
    return render(request, template, view)


def deal_message(request):
    u""" """

    #import pdb; pdb.set_trace()

    errors = ""
    sender_id = [request.user.user_id if isinstance(request.user.user_id, int) else 0].pop()
    try:
        target_id = int(request.POST['target_id'])
    except ValueError as ve:
        errors = ve


    def chat_exist(sender_id, target_id):
        # 1 on 1
        from myapp.models import Chat
        from myapp.models import Chat_Member

        try:
            sender_chats = Chat_Member.objects.filter(user_id=sender_id).filter(chat__type=0)
            target_chats = Chat_Member.objects.filter(user_id=target_id).filter(chat__type=0)

            cid = set([o.chat_id for o in sender_chats]) & set([o.chat_id for o in target_chats])
            if len(cid) == 0:
                new_chat = Chat()
                new_chat.type = 0
                new_chat.save()

                #new_chat.member = Chat_Member()
                c1 = Chat_Member(chat_id=new_chat.chat_id, user_id=sender_id)
                c2 = Chat_Member(chat_id=new_chat.chat_id, user_id=target_id)
                c1.save()
                c2.save()
                return new_chat.chat_id
            else:
                if len(cid) != 1:
                    raise
                else:
                    return cid.pop()
        except:
            return 0


    chat_id = int(chat_exist(sender_id, target_id))

    res = {}

    from myapp.forms import Message
    formset = Message
    if request.method == 'POST':    
        form = formset(request.POST)
        if form.is_valid():
            try:
                res['title'] = form.cleaned_data['title']
                res['body'] = form.cleaned_data['body']
                res = json.dumps(res)

                from myapp.models import Chat
                from myapp.models import Message

                new_message = Message()
                new_message.user_id = sender_id
                new_message.chat_id = chat_id
                new_message.title = form.cleaned_data['title']
                new_message.body = form.cleaned_data['body']
                new_message.save()

                new_chat = Chat(chat_id=chat_id)
                new_chat.last_message = form.cleaned_data['body'][:30]
                new_chat.save()
            except:
                errors = "DB Error"
        else:
            errors = ""

    return HttpResponse(res, content_type="application/json; charset=UTF-8")

jQuery2.2.0Django1.9.1Python3.5.1

2 个答案:

答案 0 :(得分:4)

您需要转义您在JSON对象中输出的HTML。通常Django会在常规响应中为您做到这一点,但是当您将其封装在JSON中时,它并不是那么直截了当。

在编码JSON之前使用escape函数,如in this question所述,如下所示:

from django.utils.html import escape

# ...

res['title'] = escape(form.cleaned_data['title'])
res['body'] = escape(form.cleaned_data['body'])
res = json.dumps(res)

答案 1 :(得分:2)

有一种非常基本的方法来解决与表单相关的任何类型的XSS,无论何时提交它只是验证特殊字符,如&lt; &GT; ()+等或尝试逃避XSS字符。更多详情here