4
\$\begingroup\$

I'm creating multiple Django apps with vote possibilities, so I made an appvote to handle all this votes. In my templates I'm including an ajax-function namedvote. To know on which model I'm liking I addapp_name andmodel_name to thevote function (I made some templatetags to get these values). In my views.py I usemodel = apps.get_model(app_name, model_name) to get the model class. But now I'm worried a hacker could do something with theapp_name andmodel_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 Falsedef _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 manipulatedapp_name andmodel_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?)

Sᴀᴍ Onᴇᴌᴀ's user avatar
Sᴀᴍ Onᴇᴌᴀ
29.6k16 gold badges46 silver badges203 bronze badges
askedJan 22, 2019 at 20:25
Myzel394's user avatar
\$\endgroup\$
1
  • 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\$CommentedJan 22, 2019 at 21:21

1 Answer1

1
\$\begingroup\$

Question

But now I'm worried a hacker could do something with theapp_name andmodel_name values.

Can he crash my server when he manipulate these values? (maybe "ajax-injection" or something like this?)

I'm not sure what the best approach to this would be. Perhaps it would be wise to define a list of the values that are acceptable for a user to pass there, though maybe that wouldn't be sufficient.

Other review points

function vote(bool){

The namebool is not very descriptive. Given that it is used as the value for thevoted parameter a name likevoted would be more appropriate. And if your code complies with standards you could simply write voted

in the list of parameters as a shorthand forvoted: voted


The success handler looks like this:

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);        }

There is quite a bit of redundancy in both cases. AlsoparseInt() calls should pass a radix1.

if (!data.error){    const thumbClass = '.fa-thumbs-' + bool ? 'up' : 'down';    $(".half " + thumbClass).removeClass("far").addClass("fas");    const toAdd = bool ? 1 : -1;    $(".half #count").text(parseInt($(".half #count").text(), 10) + toAdd);

In thevote function in ajax/views.py there is this line:

votedFor = True if request.GET.get("voted") == "true" else False

This could be simplified to just:

votedFor = request.GET.get("voted") == "true"

1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#Octal_interpretations_with_no_radix

answeredApr 9, 2020 at 18:58
Sᴀᴍ Onᴇᴌᴀ's user avatar
\$\endgroup\$
1
  • 1
    \$\begingroup\$Wow thank you for your answer for my old question, that isn`t very common! I already found a better way. I register all models in a global dict by saving the model class with a random ID. In the frontend then I use the ID and send it, in the backend I then can easily get the model by the ID.\$\endgroup\$CommentedApr 9, 2020 at 20:21

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.