Add flaw 3: SQL injection
This commit is contained in:
parent
f8fd726953
commit
141be7b2b3
2 changed files with 20 additions and 7 deletions
13
README.md
13
README.md
|
@ -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:
|
||||||
|
|
|
@ -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})
|
||||||
|
|
||||||
|
|
Reference in a new issue