diff --git a/README.md b/README.md index 5d6a350..e62391c 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,55 @@ # Secure Coding with Python. ## Chapter 2: SQL Injection -### 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("'", "\\'") - ) +### Testing part 2 +We could keep adding more cases to our fuzzer, or use external tools, like [sqlmap](http://sqlmap.org/), which are +going to be limited by the test cases we can pass to them, we could also use a Static Application Security Testing, +like [bandit](https://github.com/PyCQA/bandit/). + +First we install bandit: +```bash +> pip install bandit ``` - -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 ================================================================================================ +or +```bash +> pip install -r requirements.txt ``` -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'\'') +Then we can go and check our code with it: +```text + > $ bandit marketplace/**/*.py +Test results: +>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. + Severity: Medium Confidence: Low + Location: marketplace/listings.py:27 + More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html +26 +27 sql = "INSERT INTO listings (title, description) VALUES (E'%s', E'%s')" % ( +28 title.replace("'", "\\'"), description.replace("'", "\\'") +29 ) + +-------------------------------------------------- + +Code scanned: + Total lines of code: 28 + Total lines skipped (#nosec): 0 + +Run metrics: + Total issues (by severity): + Undefined: 0.0 + Low: 0.0 + Medium: 1.0 + High: 0.0 + Total issues (by confidence): + Undefined: 0.0 + Low: 1.0 + Medium: 0.0 + High: 0.0 +Files skipped (0): ``` +As we can see, the tool doesn't like our sanitization strategies and flags our code as a possible source of SQL injection. -and attacker will still be able to exploit our app. - -**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.2-sql-injection/test)** +**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/2.2-sql-injection/fix)** ## Index ### 1. Vulnerable Components diff --git a/requirements.txt b/requirements.txt index 88fd963..21a3104 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Flask==1.0.3 safety==1.8.5 psycopg2==2.8.3 -pytest==5.1.0 \ No newline at end of file +pytest==5.1.0 +bandit==1.6.2 diff --git a/tests/helpers/sqlifuzzer.py b/tests/helpers/sqlifuzzer.py index 7d8629a..60759af 100644 --- a/tests/helpers/sqlifuzzer.py +++ b/tests/helpers/sqlifuzzer.py @@ -4,7 +4,7 @@ def sqli_fuzzer(client, url, params): fail = False - injections = ["'"] + injections = ["'", "\\'"] for injection in injections: for param in params: data = {k: 'foo' for k in params}