From 338e06e8818413e3e93e9cf65c4bd366f11f7e78 Mon Sep 17 00:00:00 2001 From: Nicolas Valcarcel Date: Sat, 6 Jul 2019 12:17:48 -0500 Subject: [PATCH 1/3] Escape the quotes on a non very safe way --- README.md | 26 +++++++++++++++++++++++++- marketplace/listings.py | 4 +++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 296f362..38cd91e 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,30 @@ You seems to have an SQLi in /listings/create for param description =========================== 1 failed in 0.32 seconds =========================== ``` +### Fix +Given that we have seen that the way this injection works is by breaking out of the `'`'s, we can use PostgreSQL escaping `E'\''`. For that we change our SQL query and replace every occurrence of `'` with `\'`: +```python + sql = "INSERT INTO listings (title, description) VALUES (E'%s', E'%s')" % ( + title.replace("'", "\\'"), description.replace("'", "\\'") + ) +``` + +With that our test now pass: +```text +(venv) > $ pytest --tb=short +================================================================================================== test session starts =================================================================================================== +platform linux -- Python 3.5.3, pytest-5.0.0, py-1.8.0, pluggy-0.12.0 +rootdir: {...} +collected 1 item +tests/test_listings.py . [100%] +================================================================================================ 1 passed in 0.95 seconds ================================================================================================ +``` + +But this is not sufficient, if we modify our payload to be `injection\', (select version()))-- -` our query will end up being: +```sql +INSERT INTO listings (title, description) VALUES (E'injection\\', (select version()))-- -', E'\'') +``` +and attacker will still be able to exploit our app. ## Description Welcome to the Secure coding with python course. In this repository you will find a series of branches for each step of the development of a sample marketplace application. In such a development, we will be making security mistakes and introducing vulnerabilities, we will add tests for them and finally fixing them. @@ -74,7 +98,7 @@ The branches will have the following naming scheme for easier navigation: {Chapt For this course we will be using Python3, Flask and PostgreSQL. -**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.1-sql-injection/fix)** +**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.2-sql-injection/test2)** ## Index ### 1. Vulnerable Components diff --git a/marketplace/listings.py b/marketplace/listings.py index 3f9dbcb..65ce3ac 100644 --- a/marketplace/listings.py +++ b/marketplace/listings.py @@ -24,7 +24,9 @@ def register(): db = get_db() cur = db.cursor() - sql = "INSERT INTO listings (title, description) VALUES ('%s', '%s')" % (title, description) + sql = "INSERT INTO listings (title, description) VALUES (E'%s', E'%s')" % ( + title.replace("'", "\\'"), description.replace("'", "\\'") + ) print(sql, file=sys.stdout) cur.execute(sql) db.commit() From efbdd91992f918cfbb7ac22fbfcc16c0a7b673e6 Mon Sep 17 00:00:00 2001 From: Nicolas Valcarcel Date: Sat, 3 Aug 2019 15:30:42 -0500 Subject: [PATCH 2/3] remove last step text --- README.md | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/README.md b/README.md index cd02774..add25bb 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,6 @@ # Secure Coding with Python. ## Chapter 2: SQL Injection -### Testing -Testing for SQL injections is a tedious job, it's mostly done by hand or using special scanners, like web scanners or SAST/DAST tools. For this chapter we will be writing a very simple fuzzer function and create unit tests that use them in order to test for injections. - -The fuzzer helper looks like this: -```python -import pytest - -from psycopg2.errors import SyntaxError - -def sqli_fuzzer(client, url, params): - fail = False - injections = ["'"] - for injection in injections: - for param in params: - data = {k: 'foo' for k in params} - data[param] = injection - try: - client.post(url, data=data) - except SyntaxError: - print('You seems to have an SQLi in %s for param %s' % (url, param)) - fail = True - - if fail: - pytest.fail('Seems you are vulnerable to SQLi attacks') -``` - -After running `pytest --tb=short` we get: -```text -============================= test session starts ============================== -platform linux -- Python 3.5.3, pytest-5.0.1, py-1.8.0, pluggy-0.12.0 -rootdir: {...} -collected 1 item - -tests/test_listings.py F [100%] - -=================================== FAILURES =================================== -_________________________________ test_create __________________________________ -tests/test_listings.py:6: in test_create - sqli_fuzzer(client, '/listings/create', ['title', 'description']) -tests/helpers/sqlifuzzer.py:19: in sqli_fuzzer - pytest.fail('Seems you are vulnerable to SQLi attacks') -E Failed: Seems you are vulnerable to SQLi attacks ------------------------------ Captured stdout call ----------------------------- -INSERT INTO listings (title, description) VALUES (''', 'foo') -You seems to have an SQLi in /listings/create for param title -INSERT INTO listings (title, description) VALUES ('foo', ''') -You seems to have an SQLi in /listings/create for param description -=========================== 1 failed in 0.32 seconds =========================== - -``` ### Fix Given that we have seen that the way this injection works is by breaking out of the `'`'s, we can use PostgreSQL escaping `E'\''`. For that we change our SQL query and replace every occurrence of `'` with `\'`: ```python From 92ad6fd2f124e1ba42cdec5246bd229775808ed0 Mon Sep 17 00:00:00 2001 From: Nicolas Valcarcel Date: Sat, 3 Aug 2019 15:31:42 -0500 Subject: [PATCH 3/3] change next section link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index add25bb..e2e44c9 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ The branches will have the following naming scheme for easier navigation: {Chapt For this course we will be using Python3, Flask and PostgreSQL. -**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.2-sql-injection/test2)** +**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.2-sql-injection/test)** ## Index ### 1. Vulnerable Components