2
\$\begingroup\$

I'm creating multiple Django apps with vote possibilities, so I made an app vote to handle all this votes. In my templates I'm including an ajax-function named vote. To know on which model I'm liking I add app_name and model_name to the vote function (I made some templatetags to get these values). In my views.py I use model = apps.get_model(app_name, model_name) to get the model class. But now I'm worried a hacker could do something with the app_name and model_name values.

vote/ajax.html (only function):

function vote(bool){
    $.ajax({
        type: "post",
        timeout: 8000,
        url: '{% url 'ajax:vote' %}',
        dataType: 'json',
        data: {
            'csrfmiddlewaretoken': getCookie('csrftoken'),
            'model_name': "{{ model|get_model_name }}",
            'app_name': "{{ model|get_app_name }}",
            'voted': bool,
            'id': "{{ model.id }}",
        },
        success: function(data) {
            if (!data.error){
                if (bool){
                    $(".half .fa-thumbs-up").removeClass("far").addClass("fas");
                    $(".half #count").text(parseInt($(".half #count").text()) + 1);
                } else {
                    $(".half .fa-thumbs-down").removeClass("far").addClass("fas");
                    $(".half #count").text(parseInt($(".half #count").text()) - 1);
                }
            }
        }
    });
}

ajax/views.py:

def vote(request):
    try:
        app_name = request.POST.get("app_name")
        model_name = request.POST.get("model_name")
        id = request.POST.get("id")
        votedFor = True if request.POST.get("voted") == "true" else False
    except ValueError:
        return JsonResponse({"error": True})

    model = apps.get_model(app_name, model_name)

    if model is None or id is None:
        return JsonResponse({"error": True})

    try:
        usable_model = model.objects.get(id=id)
    except model.DoesNotExist:
        return JsonResponse({"error": True})

    try:
        usable_model.vote._meta.get_field("votes")
    except FieldDoesNotExist:
        return JsonResponse({"error": True})

    usable_model.vote.vote(request, votedFor)
    return JsonResponse({"error": False})

vote/functions:

def vote(self, request, votedFor):
    if request.user.is_authenticated:
        if not UserVoted.objects.filter(User=request.user, Vote=self).exists():
            UserVoted.objects.create(User=request.user, Vote=self, votedFor=votedFor)
            self._like_or_dislike(votedFor)
            return True
        return False
    ip = get_client_ip(request)
    if ip:
        if not UserVoted.objects.filter(ip=ip, Vote=self).exists():
            UserVoted.objects.create(ip=ip, Vote=self, votedFor=votedFor)
            self._like_or_dislike(votedFor)
            return True
        return False
    return False

def _like_or_dislike(self, votedFor):
    if votedFor is not None:
        Vote.objects.filter(id=self.id).update(votes=F('votes') + 1) if votedFor else Vote.objects.filter(id=self.id).update(votes=F('votes') - 1)
        return True
    return False

I already manipulated app_name and model_name and the server didn't crash but I don't know what a hacker can do. Can he crash my server when he manipulate these values? (maybe "ajax-injection" or something like this?)

\$\endgroup\$
  • 5
    \$\begingroup\$ Your indentation is off. This being Python, indentation is very important. Remove your code, paste it in file-by-file and with every bit you paste in, select it, hit Ctrl + K. The question editor should do the rest. \$\endgroup\$ – Mast Jan 22 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.