Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Flask==1.0.3
safety==1.8.5
psycopg2==2.8.3
pytest==5.1.0
pytest==5.1.0
bandit==1.6.2
2 changes: 1 addition & 1 deletion tests/helpers/sqlifuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down