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?)