1
0
Fork 0

Add flaw 3: SQL injection

This commit is contained in:
Vili Sinervä 2024-11-25 19:08:50 +02:00
parent f8fd726953
commit 141be7b2b3
No known key found for this signature in database
GPG key ID: DF8FEAF54EFAC996
2 changed files with 20 additions and 7 deletions

View file

@ -7,8 +7,6 @@ The point is to demonstrate common cyber security problems and their fixes.
## Description of vulnerabilities ## Description of vulnerabilities
> **_NOTE:_** More detailed description of problems coming soon.
I am using the 2021 OWASP Top Ten list. I am using the 2021 OWASP Top Ten list.
LINK: https://github.com/VSinerva/csb-project-1 LINK: https://github.com/VSinerva/csb-project-1
@ -46,7 +44,16 @@ If users already exist with weakly hashed passwords, a more complicated migratio
FLAW 3: FLAW 3:
> ADD EXACT SOURCE LINK > ADD EXACT SOURCE LINK
SQL Injection (Unsanitized SQL query for search) (Injection) The application has a classic SQL injection vunlerability in its search function.
This is cause by taking the user input (search text) and placing it directly in the SQL query with a Python f-string.
As an example, the "Search text" shown below will give any user a full listing of all usernames and their hashed passwords.
`' AND 0=1 UNION SELECT date_joined, username || ":" || password as user, id FROM auth_user; --`
Especially with flaws 2 and 4 present, this will quickly lead to a lot of compromised accounts.
The fix to this issue is to properly escape/sanitize the user input e.g. by escaping control characters.
This is difficult to do perfectly, so best practice is to use a well-known library or something similar for this.
Luckily, Django has existing functionality for doing what we wanted to do, which will fix this issue.
The commented out code implements this fixed version.
FLAW 4: FLAW 4:

View file

@ -5,7 +5,6 @@ from django.contrib.auth.validators import UnicodeUsernameValidator
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.password_validation import validate_password from django.contrib.auth.password_validation import validate_password
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_exempt
from django.db import connection from django.db import connection
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -52,9 +51,16 @@ def search(request):
user = request.user user = request.user
keyword = request.GET.get('keyword') keyword = request.GET.get('keyword')
notes = Note.objects.filter(owner=user, body__icontains=keyword) # FLAW 3:
notes_list = [ { 'time' : note.time, 'body' : note.body, 'id' : note.id } for note in notes ] # Using the commented out version of the code uses Django's built in methods
notes_list.sort(key=lambda note: note['time']) # This makes sure the inputs are properly sanitized
# notes = Note.objects.filter(owner=user, body__icontains=keyword)
# notes_list = [ { 'time' : note.time, 'body' : note.body, 'id' : note.id } for note in notes ]
# notes_list.sort(key=lambda note: note['time'])
query = f"SELECT time, body, id FROM notes_note WHERE body LIKE '%{keyword}%' ORDER BY time;"
with connection.cursor() as cursor:
notes = cursor.execute(query).fetchall()
notes_list = [ { 'time' : note[0], 'body' : note[1], 'id' : note[2] } for note in notes ]
return render(request, 'search.html', { 'notes' : notes_list, 'keyword' : keyword}) return render(request, 'search.html', { 'notes' : notes_list, 'keyword' : keyword})