🔖 Day19 - Markdown DIY prevent XSS attack (Part 2)

2018 - 01 - 25
🔖 Day19 - Markdown DIY prevent XSS attack (Part 2)
In XSS markdown DIY (Part 1) we built tools for user to decorate comment content, and wrote a Form Method updateContent which accepted the submitted content and decrypted those markdowns into proper HTML tags before saving to database. However, what if we want to let users edit their comments? By calling the instance from database, the comment content is shown in HTML tags instead of our markdowns. To prevent showing plain HTML to users, we need to encrypt the comment again upon loading the views. In this demo, we have pre-built model Comment, and form CommentForm.
1. [Views function for editing the comment] views.py:
from .models import Comment
from .form import CommentForm

def edit_comment(request, key):
    comment = Comment.objects.get(pk=key)
    if request.user != 'comment.author':
        return index()
    
    if request.method == 'POST':
        temp = CommentForm(request.POST, instance=comment)
        if temp.is_valid():
            edited_content = temp.updateContent()
            form = temp.save(comment=False)
            form.content = edited_content
            form.save()
            return index(request)
        else:
            content = encryptContent(comment)
            form = CommentForm(initial={'content':content}, instance=comment)
    else:
        content = encryptContent(comment)
        form = CommentForm(initial={'content':content}, instance=comment)
    return render(request, 'comment.html', {'form':form})        
This snippet is similar to edit a post as shown here , (both passed an instance to the form such that the form is pre-filled), excepts an extra function encryptContent() is called before showing the form. Since we wish to present markdowns instead of plain HTML tags to user while editing their comments, encryption is needed.
2. [Encrypt content with markdowns] The encryptContent() lives in the same views.py:
def encryptContent(request, target):
    plain_content = target.content
    tags = {'<b>': '[bold]', '</b>': '[/bold]',
            '<a href="': '[link]', '">': '[linkTitle]',
            '</a>': '[/link]',
            '&lt;': '<', '&gt;': '>'}
    lines = plain_content.split('\n')
    new_lines = []
    for l in lines:
        for t in tags:
            l = re.sub(t, tags[t], l)
        new_lines.append(l)
    encrypted_content = '\n'.join(new_lines)
    return encrypted_content
    
The target is passed to this function from edit_comment() by calling encrypt_content(comment) in previous snippet. The principle is more or less the same as that we turn the markdowns into HTML tags in Part 1.

Comments

There is no comment yet

New Comment

Please Login to comment