From 52aa568c4810636152595f781e8ba4a35edb7e15 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 15 Feb 2021 20:17:23 +0100 Subject: [PATCH 001/121] adding http basic auth --- simplehttpserver.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 2e7ad19..86cd06f 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -12,6 +12,9 @@ import ( type options struct { ListenAddress string Folder string + Username string + Password string + Realm string Verbose bool } @@ -21,6 +24,9 @@ func main() { flag.StringVar(&opts.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") flag.StringVar(&opts.Folder, "path", ".", "Folder") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") + flag.StringVar(&opts.Username, "username", "", "Basic auth username") + flag.StringVar(&opts.Password, "password", "", "Basic auth password") + flag.StringVar(&opts.Realm, "realm", "Please enter username and password", "Realm") flag.Parse() if flag.NArg() > 0 && opts.Folder == "." { @@ -28,7 +34,12 @@ func main() { } log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) - fmt.Println(http.ListenAndServe(opts.ListenAddress, loglayer(http.FileServer(http.Dir(opts.Folder))))) + layers := loglayer(http.FileServer(http.Dir(opts.Folder))) + if opts.Username != "" || opts.Password != "" { + layers = loglayer(basicauthlayer(http.FileServer(http.Dir(opts.Folder)))) + } + + fmt.Println(http.ListenAndServe(opts.ListenAddress, layers)) } func loglayer(handler http.Handler) http.Handler { @@ -47,6 +58,19 @@ func loglayer(handler http.Handler) http.Handler { }) } +func basicauthlayer(handler http.Handler) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + user, pass, ok := r.BasicAuth() + if !ok || user != opts.Username || pass != opts.Password { + w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", opts.Realm)) + w.WriteHeader(401) + w.Write([]byte("Unauthorized.\n")) + return + } + handler.ServeHTTP(w, r) + }) +} + type loggingResponseWriter struct { http.ResponseWriter statusCode int From 8ad8b6e6efc9dcdb2ac541741531abfdf252f329 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 15 Feb 2021 20:56:48 +0100 Subject: [PATCH 002/121] adding file upload support --- simplehttpserver.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/simplehttpserver.go b/simplehttpserver.go index 2e7ad19..1bbb135 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -4,15 +4,18 @@ import ( "bytes" "flag" "fmt" + "io/ioutil" "log" "net/http" "net/http/httputil" + "path" ) type options struct { ListenAddress string Folder string Verbose bool + Upload bool } var opts options @@ -20,7 +23,9 @@ var opts options func main() { flag.StringVar(&opts.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") flag.StringVar(&opts.Folder, "path", ".", "Folder") + flag.BoolVar(&opts.Upload, "upload", false, "Enable upload via PUT") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") + flag.Parse() if flag.NArg() > 0 && opts.Folder == "." { @@ -28,6 +33,9 @@ func main() { } log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) + if opts.Upload { + log.Println("Upload enabled") + } fmt.Println(http.ListenAndServe(opts.ListenAddress, loglayer(http.FileServer(http.Dir(opts.Folder))))) } @@ -37,6 +45,18 @@ func loglayer(handler http.Handler) http.Handler { lrw := newLoggingResponseWriter(w) handler.ServeHTTP(lrw, r) + // Handles file write if enabled + if opts.Upload && r.Method == http.MethodPut { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Println(err) + } + err = handleUpload(path.Base(r.URL.Path), data) + if err != nil { + log.Println(err) + } + } + if opts.Verbose { headers := new(bytes.Buffer) lrw.Header().Write(headers) //nolint @@ -70,3 +90,7 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) { lrw.statusCode = code lrw.ResponseWriter.WriteHeader(code) } + +func handleUpload(file string, data []byte) error { + return ioutil.WriteFile(file, data, 0655) +} From 6b4eb1c947d95a706fcb2ec58efe32ca790a65ad Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 15 Feb 2021 21:11:58 +0100 Subject: [PATCH 003/121] adding https support --- simplehttpserver.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 2e7ad19..1aa7c54 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -12,6 +12,9 @@ import ( type options struct { ListenAddress string Folder string + Certificate string + Key string + HTTPS bool Verbose bool } @@ -20,6 +23,9 @@ var opts options func main() { flag.StringVar(&opts.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") flag.StringVar(&opts.Folder, "path", ".", "Folder") + flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") + flag.StringVar(&opts.Certificate, "cert", "", "Certificate") + flag.StringVar(&opts.Key, "key", "", "Key") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") flag.Parse() @@ -28,7 +34,14 @@ func main() { } log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) - fmt.Println(http.ListenAndServe(opts.ListenAddress, loglayer(http.FileServer(http.Dir(opts.Folder))))) + if opts.HTTPS { + if opts.Certificate == "" || opts.Key == "" { + log.Fatal("Certificate or Key file not specified") + } + fmt.Println(http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, loglayer(http.FileServer(http.Dir(opts.Folder))))) + } else { + fmt.Println(http.ListenAndServe(opts.ListenAddress, loglayer(http.FileServer(http.Dir(opts.Folder))))) + } } func loglayer(handler http.Handler) http.Handler { From 8890cbf2942ecc8cdc73233e4440cc679faefe96 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 15 Feb 2021 21:12:12 +0100 Subject: [PATCH 004/121] cert generation helper --- gen_cert.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 gen_cert.sh diff --git a/gen_cert.sh b/gen_cert.sh new file mode 100644 index 0000000..0cba96a --- /dev/null +++ b/gen_cert.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +openssl genrsa -out server.key 2048 +openssl ecparam -genkey -name secp384r1 -out server.key +openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 \ No newline at end of file From 0fc0dea2669949c069f5c5678849f3a0fb686f6e Mon Sep 17 00:00:00 2001 From: sandeep <8293321+bauthard@users.noreply.github.com> Date: Tue, 16 Feb 2021 01:53:09 +0530 Subject: [PATCH 005/121] Update build.yaml --- .github/workflows/build.yaml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a157f84..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,27 +6,18 @@ on: pull_request: jobs: - lint: - name: golangci-lint + golangci-lint: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.2.0 + uses: golangci/golangci-lint-action@v2.4.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.31 args: --timeout 5m - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true build: name: Build runs-on: ubuntu-latest From ae48cc600f4eb883a6fad3de2f3bd98edaba857f Mon Sep 17 00:00:00 2001 From: sandeep <8293321+bauthard@users.noreply.github.com> Date: Tue, 16 Feb 2021 01:53:09 +0530 Subject: [PATCH 006/121] Update build.yaml --- .github/workflows/build.yaml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a157f84..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,27 +6,18 @@ on: pull_request: jobs: - lint: - name: golangci-lint + golangci-lint: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.2.0 + uses: golangci/golangci-lint-action@v2.4.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.31 args: --timeout 5m - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true build: name: Build runs-on: ubuntu-latest From 8c1cc031b82f6459765779a17bbe6a47ac3393fe Mon Sep 17 00:00:00 2001 From: sandeep <8293321+bauthard@users.noreply.github.com> Date: Tue, 16 Feb 2021 01:53:09 +0530 Subject: [PATCH 007/121] Update build.yaml --- .github/workflows/build.yaml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a157f84..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,27 +6,18 @@ on: pull_request: jobs: - lint: - name: golangci-lint + golangci-lint: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.2.0 + uses: golangci/golangci-lint-action@v2.4.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.31 args: --timeout 5m - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true build: name: Build runs-on: ubuntu-latest From b71f31edcf32618c0963f8f955cfd0901d538706 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+bauthard@users.noreply.github.com> Date: Tue, 16 Feb 2021 01:53:09 +0530 Subject: [PATCH 008/121] Update build.yaml --- .github/workflows/build.yaml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a157f84..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,27 +6,18 @@ on: pull_request: jobs: - lint: - name: golangci-lint + golangci-lint: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.2.0 + uses: golangci/golangci-lint-action@v2.4.0 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.31 args: --timeout 5m - # Optional: working directory, useful for monorepos - # working-directory: somedir - - # Optional: golangci-lint command line arguments. - # args: --issues-exit-code=0 - - # Optional: show only new issues if it's a pull request. The default value is `false`. - # only-new-issues: true build: name: Build runs-on: ubuntu-latest From ed7e2ee2d2e987c8e173ed38914908913c4c0abe Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 15 Feb 2021 21:54:25 +0100 Subject: [PATCH 009/121] linting fix --- simplehttpserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 86cd06f..b7ff509 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -63,8 +63,8 @@ func basicauthlayer(handler http.Handler) http.HandlerFunc { user, pass, ok := r.BasicAuth() if !ok || user != opts.Username || pass != opts.Password { w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", opts.Realm)) - w.WriteHeader(401) - w.Write([]byte("Unauthorized.\n")) + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Unauthorized.\n")) //nolint return } handler.ServeHTTP(w, r) From 752b822207e2648c22ade4ccf2a4ebf02d26dd7f Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 17 Feb 2021 15:47:10 +0100 Subject: [PATCH 010/121] adding dep bot --- .github/dependabot.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..4d5617f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,34 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore" + include: "scope" + + # Maintain dependencies for go modules + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore" + include: "scope" + + # Maintain dependencies for docker + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore" + include: "scope" From 526bfd99472cf9dbcda081024b2f4ad5aa7c5ea2 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 19 Feb 2021 20:59:30 +0100 Subject: [PATCH 011/121] refactoring basic auth option --- simplehttpserver.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index e181945..d0314ad 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -9,13 +9,15 @@ import ( "net/http" "net/http/httputil" "path" + "strings" ) type options struct { ListenAddress string Folder string - Username string - Password string + BasicAuth string + username string + password string Realm string Certificate string Key string @@ -34,8 +36,7 @@ func main() { flag.StringVar(&opts.Certificate, "cert", "", "Certificate") flag.StringVar(&opts.Key, "key", "", "Key") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") - flag.StringVar(&opts.Username, "username", "", "Basic auth username") - flag.StringVar(&opts.Password, "password", "", "Basic auth password") + flag.StringVar(&opts.BasicAuth, "basic-auth", "", "Basic auth (username:password)") flag.StringVar(&opts.Realm, "realm", "Please enter username and password", "Realm") flag.Parse() @@ -46,7 +47,14 @@ func main() { log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) layers := loglayer(http.FileServer(http.Dir(opts.Folder))) - if opts.Username != "" || opts.Password != "" { + if opts.BasicAuth != "" { + baTokens := strings.SplitN(opts.BasicAuth, ":", 1) + if len(baTokens) > 0 { + opts.username = baTokens[0] + } + if len(baTokens) > 1 { + opts.password = baTokens[1] + } layers = loglayer(basicauthlayer(http.FileServer(http.Dir(opts.Folder)))) } @@ -94,7 +102,7 @@ func loglayer(handler http.Handler) http.Handler { func basicauthlayer(handler http.Handler) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user, pass, ok := r.BasicAuth() - if !ok || user != opts.Username || pass != opts.Password { + if !ok || user != opts.username || pass != opts.password { w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", opts.Realm)) w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("Unauthorized.\n")) //nolint From 1593493b6a65f6ca659dcfa69fc6235fa203f07e Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 01:35:25 +0100 Subject: [PATCH 012/121] fixing split amount --- simplehttpserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index d0314ad..809e52c 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -48,7 +48,7 @@ func main() { log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) layers := loglayer(http.FileServer(http.Dir(opts.Folder))) if opts.BasicAuth != "" { - baTokens := strings.SplitN(opts.BasicAuth, ":", 1) + baTokens := strings.SplitN(opts.BasicAuth, ":", 2) if len(baTokens) > 0 { opts.username = baTokens[0] } From 5a1f3a3ca43b46f80348756b8f293ceb30eaeebb Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 01:39:21 +0100 Subject: [PATCH 013/121] replacing log with gologger --- go.mod | 2 ++ go.sum | 35 +++++++++++++++++++++++++++++++++++ simplehttpserver.go | 16 +++++++++------- 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 go.sum diff --git a/go.mod b/go.mod index 1876095..120667d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/projectdiscovery/simplehttpserver go 1.15 + +require github.com/projectdiscovery/gologger v1.1.4 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..82f8703 --- /dev/null +++ b/go.sum @@ -0,0 +1,35 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI= +github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/simplehttpserver.go b/simplehttpserver.go index e181945..98475c6 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -9,6 +9,8 @@ import ( "net/http" "net/http/httputil" "path" + + "github.com/projectdiscovery/gologger" ) type options struct { @@ -44,22 +46,22 @@ func main() { opts.Folder = flag.Args()[0] } - log.Printf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) + gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) layers := loglayer(http.FileServer(http.Dir(opts.Folder))) if opts.Username != "" || opts.Password != "" { layers = loglayer(basicauthlayer(http.FileServer(http.Dir(opts.Folder)))) } if opts.Upload { - log.Println("Upload enabled") + gologger.Print().Msgf("Upload enabled") } if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { - log.Fatal("Certificate or Key file not specified") + gologger.Fatal().Msgf("Certificate or Key file not specified") } - fmt.Println(http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) + gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) } else { - fmt.Println(http.ListenAndServe(opts.ListenAddress, layers)) + gologger.Print().Msgf("%s\n", http.ListenAndServe(opts.ListenAddress, layers)) } } @@ -84,9 +86,9 @@ func loglayer(handler http.Handler) http.Handler { if opts.Verbose { headers := new(bytes.Buffer) lrw.Header().Write(headers) //nolint - log.Printf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) + gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) } else { - log.Printf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data)) + gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data)) } }) } From 75383752133ebf463f179c45bf97223e49f7ea07 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 01:52:43 +0100 Subject: [PATCH 014/121] adding auto port increment --- simplehttpserver.go | 62 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 98475c6..1dbc260 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -2,13 +2,19 @@ package main import ( "bytes" + "errors" "flag" "fmt" "io/ioutil" "log" + "net" "net/http" "net/http/httputil" + "os" "path" + "runtime" + "strconv" + "syscall" "github.com/projectdiscovery/gologger" ) @@ -55,13 +61,29 @@ func main() { if opts.Upload { gologger.Print().Msgf("Upload enabled") } +retry_listen: + var err error if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { gologger.Fatal().Msgf("Certificate or Key file not specified") } - gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) + err = http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers) + } else { - gologger.Print().Msgf("%s\n", http.ListenAndServe(opts.ListenAddress, layers)) + err = http.ListenAndServe(opts.ListenAddress, layers) + gologger.Print().Msgf("%s\n") + } + if err != nil { + if isErrorAddressAlreadyInUse(err) { + gologger.Warning().Msgf("Can't listen on %s: %s - retrying with another port\n", opts.ListenAddress, err) + newListenAddress, err := incPort(opts.ListenAddress) + if err != nil { + gologger.Fatal().Msgf("%s\n", err) + } + opts.ListenAddress = newListenAddress + goto retry_listen + } + gologger.Warning().Msgf("%s\n", err) } } @@ -133,3 +155,39 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) { func handleUpload(file string, data []byte) error { return ioutil.WriteFile(file, data, 0655) } + +func isErrorAddressAlreadyInUse(err error) bool { + var eOsSyscall *os.SyscallError + if !errors.As(err, &eOsSyscall) { + return false + } + var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr) + if !errors.As(eOsSyscall, &errErrno) { + return false + } + if errErrno == syscall.EADDRINUSE { + return true + } + const WSAEADDRINUSE = 10048 + if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE { + return true + } + return false +} + +func incPort(address string) (string, error) { + addrOrig, portOrig, err := net.SplitHostPort(address) + if err != nil { + return address, err + } + + // increment port + portNumber, err := strconv.Atoi(portOrig) + if err != nil { + return address, err + } + portNumber++ + newPort := strconv.FormatInt(int64(portNumber), 10) + + return net.JoinHostPort(addrOrig, newPort), nil +} From 69d59ffa6ddd82886dc92c461f4b9e7686fc897a Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 01:55:37 +0100 Subject: [PATCH 015/121] fixing lint errors --- simplehttpserver.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 1dbc260..b366ce9 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -59,19 +59,17 @@ func main() { } if opts.Upload { - gologger.Print().Msgf("Upload enabled") + gologger.Print().Msg("Upload enabled") } retry_listen: var err error if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { - gologger.Fatal().Msgf("Certificate or Key file not specified") + gologger.Fatal().Msg("Certificate or Key file not specified") } err = http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers) - } else { err = http.ListenAndServe(opts.ListenAddress, layers) - gologger.Print().Msgf("%s\n") } if err != nil { if isErrorAddressAlreadyInUse(err) { From bfe28042add32b69c9a6687e351e8468b9caac3f Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 02:51:41 +0100 Subject: [PATCH 016/121] adding self certificate generation --- pkg/sslcert/options.go | 21 ++++++ pkg/sslcert/sslcert.go | 151 +++++++++++++++++++++++++++++++++++++++ pkg/sslcert/tlsconfig.go | 19 +++++ simplehttpserver.go | 19 ++++- 4 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 pkg/sslcert/options.go create mode 100644 pkg/sslcert/sslcert.go create mode 100644 pkg/sslcert/tlsconfig.go diff --git a/pkg/sslcert/options.go b/pkg/sslcert/options.go new file mode 100644 index 0000000..54cbc0d --- /dev/null +++ b/pkg/sslcert/options.go @@ -0,0 +1,21 @@ +package sslcert + +import "time" + +type Options struct { + Host string // Comma-separated hostnames and IPs to generate a certificate for") + Organization string + ValidFrom string // Creation date formatted as Jan 1 15:04:05 2011 + ValidFor time.Duration // 365*24*time.Hour Duration that certificate is valid for + IsCA bool // whether this cert should be its own Certificate Authority + RSABits int // 2048 Size of RSA key to generate. Ignored if --ecdsa-curve is set + EcdsaCurve string // ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 + Ed25519Key bool // Generate an Ed25519 key +} + +var DefaultOptions = Options{ + ValidFor: time.Duration(365 * 24 * time.Hour), + IsCA: false, + RSABits: 2048, + Organization: "Acme Co", +} diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go new file mode 100644 index 0000000..6469b78 --- /dev/null +++ b/pkg/sslcert/sslcert.go @@ -0,0 +1,151 @@ +// Package sslcert contains a reworked version of https://golang.org/src/crypto/tls/generate_cert.go +package sslcert + +import ( + "bufio" + "bytes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "math/big" + "net" + "strings" + "time" +) + +func pubKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} + +func Generate(options Options) (privateKey, publicKey []byte, err error) { + if options.Host == "" { + return nil, nil, errors.New("Empty host value") + } + + var priv interface{} + switch options.EcdsaCurve { + case "": + if options.Ed25519Key { + _, priv, err = ed25519.GenerateKey(rand.Reader) + } else { + priv, err = rsa.GenerateKey(rand.Reader, options.RSABits) + } + case "P224": + priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + case "P256": + priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + case "P384": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + case "P521": + priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + default: + err = fmt.Errorf("Unrecognized elliptic curve: %q", options.EcdsaCurve) + return + } + if err != nil { + err = fmt.Errorf("Failed to generate private key: %v", err) + return + } + + // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature + // KeyUsage bits set in the x509.Certificate template + keyUsage := x509.KeyUsageDigitalSignature + // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In + // the context of TLS this KeyUsage is particular to RSA key exchange and + // authentication. + if _, isRSA := priv.(*rsa.PrivateKey); isRSA { + keyUsage |= x509.KeyUsageKeyEncipherment + } + + var notBefore time.Time + if len(options.ValidFrom) == 0 { + notBefore = time.Now() + } else { + notBefore, err = time.Parse("Jan 2 15:04:05 2006", options.ValidFrom) + if err != nil { + err = fmt.Errorf("Failed to parse creation date: %v", err) + return + } + } + + notAfter := notBefore.Add(options.ValidFor) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + err = fmt.Errorf("Failed to generate serial number: %v", err) + return + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{options.Organization}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + hosts := strings.Split(options.Host, ",") + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, h) + } + } + + if options.IsCA { + template.IsCA = true + template.KeyUsage |= x509.KeyUsageCertSign + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey(priv), priv) + if err != nil { + err = fmt.Errorf("Failed to create certificate: %v", err) + return + } + + var pubKeyBuf bytes.Buffer + pubKeyBufb := bufio.NewWriter(&pubKeyBuf) + err = pem.Encode(pubKeyBufb, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + err = fmt.Errorf("Failed to write data to cert.pem: %v", err) + return + } + + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + err = fmt.Errorf("Unable to marshal private key: %v", err) + return + } + var privKeyBuf bytes.Buffer + privKeyBufb := bufio.NewWriter(&privKeyBuf) + err = pem.Encode(privKeyBufb, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) + if err != nil { + err = fmt.Errorf("Failed to write data to key.pem: %v", err) + return + } + + return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil +} diff --git a/pkg/sslcert/tlsconfig.go b/pkg/sslcert/tlsconfig.go new file mode 100644 index 0000000..e2bbe92 --- /dev/null +++ b/pkg/sslcert/tlsconfig.go @@ -0,0 +1,19 @@ +package sslcert + +import ( + "crypto/tls" +) + +func NewTLSConfig(options Options) (*tls.Config, error) { + pubKey, privKey, err := Generate(options) + if err != nil { + return nil, err + } + + cert, err := tls.X509KeyPair(pubKey, privKey) + if err != nil { + return nil, err + } + + return &tls.Config{Certificates: []tls.Certificate{cert}}, nil +} diff --git a/simplehttpserver.go b/simplehttpserver.go index 98475c6..803d02c 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -11,6 +11,7 @@ import ( "path" "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" ) type options struct { @@ -21,6 +22,7 @@ type options struct { Realm string Certificate string Key string + Domain string HTTPS bool Verbose bool Upload bool @@ -35,6 +37,7 @@ func main() { flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") flag.StringVar(&opts.Certificate, "cert", "", "Certificate") flag.StringVar(&opts.Key, "key", "", "Key") + flag.StringVar(&opts.Domain, "domain", "", "Domain") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") flag.StringVar(&opts.Username, "username", "", "Basic auth username") flag.StringVar(&opts.Password, "password", "", "Basic auth password") @@ -57,9 +60,21 @@ func main() { } if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { - gologger.Fatal().Msgf("Certificate or Key file not specified") + tlsOptions := sslcert.DefaultOptions + tlsOptions.Host = opts.Domain + tlsConfig, err := sslcert.NewTLSConfig(tlsOptions) + if err != nil { + gologger.Fatal().Msgf("%s\n", err) + } + httpServer := &http.Server{ + Addr: opts.ListenAddress, + TLSConfig: tlsConfig, + } + httpServer.Handler = layers + gologger.Print().Msgf("%s\n", httpServer.ListenAndServeTLS("", "")) + } else { + gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) } - gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) } else { gologger.Print().Msgf("%s\n", http.ListenAndServe(opts.ListenAddress, layers)) } From 86e2a7d6d16d98897b7c44ac943a2b1a2ebae8fb Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 17:48:56 +0100 Subject: [PATCH 017/121] improved output --- simplehttpserver.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index e560113..62cb4e6 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -14,8 +14,8 @@ import ( "path" "runtime" "strconv" - "syscall" "strings" + "syscall" "github.com/projectdiscovery/gologger" ) @@ -53,7 +53,6 @@ func main() { opts.Folder = flag.Args()[0] } - gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) layers := loglayer(http.FileServer(http.Dir(opts.Folder))) if opts.BasicAuth != "" { baTokens := strings.SplitN(opts.BasicAuth, ":", 2) @@ -65,11 +64,11 @@ func main() { } layers = loglayer(basicauthlayer(http.FileServer(http.Dir(opts.Folder)))) } - if opts.Upload { - gologger.Print().Msg("Upload enabled") + gologger.Print().Msg("Starting service with Upload enabled") } retry_listen: + gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) var err error if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { @@ -81,7 +80,7 @@ retry_listen: } if err != nil { if isErrorAddressAlreadyInUse(err) { - gologger.Warning().Msgf("Can't listen on %s: %s - retrying with another port\n", opts.ListenAddress, err) + gologger.Print().Msgf("Can't listen on %s: %s - retrying with another port\n", opts.ListenAddress, err) newListenAddress, err := incPort(opts.ListenAddress) if err != nil { gologger.Fatal().Msgf("%s\n", err) @@ -89,7 +88,7 @@ retry_listen: opts.ListenAddress = newListenAddress goto retry_listen } - gologger.Warning().Msgf("%s\n", err) + gologger.Print().Msgf("%s\n", err) } } From bd654bf7de05652c7cc25912482156fb607db277 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 17:58:09 +0100 Subject: [PATCH 018/121] adding missing buffer flush --- pkg/sslcert/sslcert.go | 2 ++ simplehttpserver.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go index 6469b78..862ee21 100644 --- a/pkg/sslcert/sslcert.go +++ b/pkg/sslcert/sslcert.go @@ -133,6 +133,7 @@ func Generate(options Options) (privateKey, publicKey []byte, err error) { err = fmt.Errorf("Failed to write data to cert.pem: %v", err) return } + pubKeyBufb.Flush() privBytes, err := x509.MarshalPKCS8PrivateKey(priv) if err != nil { @@ -146,6 +147,7 @@ func Generate(options Options) (privateKey, publicKey []byte, err error) { err = fmt.Errorf("Failed to write data to key.pem: %v", err) return } + privKeyBufb.Flush() return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil } diff --git a/simplehttpserver.go b/simplehttpserver.go index 803d02c..f8e5875 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -37,7 +37,7 @@ func main() { flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") flag.StringVar(&opts.Certificate, "cert", "", "Certificate") flag.StringVar(&opts.Key, "key", "", "Key") - flag.StringVar(&opts.Domain, "domain", "", "Domain") + flag.StringVar(&opts.Domain, "domain", "local.host", "Domain") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") flag.StringVar(&opts.Username, "username", "", "Basic auth username") flag.StringVar(&opts.Password, "password", "", "Basic auth password") From bbee79f0fca7e3577978ad06e95c1704690db3c6 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 20:11:28 +0100 Subject: [PATCH 019/121] adding initial implementation of template based tcp server --- go.mod | 5 +- go.sum | 2 + pkg/tcpserver/responseengine.go | 15 ++++ pkg/tcpserver/rule.go | 22 ++++++ pkg/tcpserver/tcpserver.go | 124 ++++++++++++++++++++++++++++++++ simplehttpserver.go | 20 ++++++ 6 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 pkg/tcpserver/responseengine.go create mode 100644 pkg/tcpserver/rule.go create mode 100644 pkg/tcpserver/tcpserver.go diff --git a/go.mod b/go.mod index 120667d..2bc0442 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.15 -require github.com/projectdiscovery/gologger v1.1.4 +require ( + github.com/projectdiscovery/gologger v1.1.4 + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/go.sum b/go.sum index 82f8703..bd1e991 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/tcpserver/responseengine.go b/pkg/tcpserver/responseengine.go new file mode 100644 index 0000000..c3286f8 --- /dev/null +++ b/pkg/tcpserver/responseengine.go @@ -0,0 +1,15 @@ +package tcpserver + +import ( + "errors" +) + +func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { + // Process all the rules + for _, rule := range t.options.rules { + if rule.matchRegex.Match(data) { + return []byte(rule.Response), nil + } + } + return nil, errors.New("No matched rule") +} diff --git a/pkg/tcpserver/rule.go b/pkg/tcpserver/rule.go new file mode 100644 index 0000000..ba31839 --- /dev/null +++ b/pkg/tcpserver/rule.go @@ -0,0 +1,22 @@ +package tcpserver + +import "regexp" + +type RulesConfiguration struct { + Rules []Rule `yaml:"rules"` +} + +type Rule struct { + Match string `yaml:"match,omitempty"` + matchRegex *regexp.Regexp + Response string `yaml:"response,omitempty"` +} + +func NewRule(match string, response string) (*Rule, error) { + regxp, err := regexp.Compile(match) + if err != nil { + return nil, err + } + + return &Rule{Match: match, matchRegex: regxp, Response: response}, nil +} diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go new file mode 100644 index 0000000..607afe1 --- /dev/null +++ b/pkg/tcpserver/tcpserver.go @@ -0,0 +1,124 @@ +package tcpserver + +import ( + "crypto/tls" + "io/ioutil" + "net" + "time" + + "gopkg.in/yaml.v2" +) + +type Options struct { + Listen string + TLS bool + Certificate string + Key string + Domain string + rules []Rule +} + +type TCPServer struct { + options Options + listener net.Listener +} + +func New(options Options) (*TCPServer, error) { + return &TCPServer{options: options}, nil +} + +func (t *TCPServer) AddRule(rule Rule) error { + t.options.rules = append(t.options.rules, rule) + return nil +} + +func (t *TCPServer) ListenAndServe() error { + listener, err := net.Listen("tcp4", t.options.Listen) + if err != nil { + return err + } + t.listener = listener + return t.run() +} + +func (t *TCPServer) handleConnection(conn net.Conn) error { + defer conn.Close() + + buf := make([]byte, 4096) + for { + conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))) + _, err := conn.Read(buf) + if err != nil { + return err + } + + resp, err := t.BuildResponse(buf) + if err != nil { + return err + } + + conn.Write(resp) + } +} + +func (t *TCPServer) ListenAndServeTLS() error { + var tlsConfig *tls.Config + if t.options.Certificate != "" && t.options.Key != "" { + cert, err := tls.LoadX509KeyPair(t.options.Certificate, t.options.Key) + if err != nil { + return err + } + tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} + } else { + tlsOptions := sslcert.DefaultOptions + tlsOptions.Host = opts.Domain + cfg, err := sslcert.NewTLSConfig(tlsOptions) + if err != nil { + return err + } + tlsConfig = cfg + } + + listener, err := tls.Listen("tcp", t.options.Listen, tlsConfig) + if err != nil { + return err + } + t.listener = listener + return t.run() +} + +func (t *TCPServer) run() error { + for { + c, err := t.listener.Accept() + if err != nil { + return err + } + go t.handleConnection(c) + } +} + +func (t *TCPServer) Close() error { + return t.listener.Close() +} + +func (t *TCPServer) LoadTemplate(templatePath string) error { + var config RulesConfiguration + yamlFile, err := ioutil.ReadFile(templatePath) + if err != nil { + return err + } + err = yaml.Unmarshal(yamlFile, &config) + if err != nil { + return err + } + + for _, ruleTemplate := range config.Rules { + rule, err := NewRule(ruleTemplate.Match, ruleTemplate.Response) + if err != nil { + return err + } + t.options.rules = append(t.options.rules, *rule) + } + + return nil +} diff --git a/simplehttpserver.go b/simplehttpserver.go index 6e5f22d..1335ce1 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" ) type options struct { @@ -26,12 +27,18 @@ type options struct { HTTPS bool Verbose bool Upload bool + TCP bool + RulesFile string + TLS bool } var opts options func main() { flag.StringVar(&opts.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") + flag.BoolVar(&opts.TCP, "tcp", false, "TCP Server") + flag.BoolVar(&opts.TLS, "tls", false, "Enable TCP TLS") + flag.StringVar(&opts.RulesFile, "rules", "", "Rules yaml file") flag.StringVar(&opts.Folder, "path", ".", "Folder") flag.BoolVar(&opts.Upload, "upload", false, "Enable upload via PUT") flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") @@ -47,6 +54,19 @@ func main() { opts.Folder = flag.Args()[0] } + if opts.TCP { + serverTCP, err := tcpserver.New(tcpserver.Options{Listen: opts.ListenAddress, TLS: opts.TLS, Domain: "local.host"}) + if err != nil { + gologger.Fatal().Msgf("%s\n", err) + } + err = serverTCP.LoadTemplate(opts.RulesFile) + if err != nil { + gologger.Fatal().Msgf("%s\n", err) + } + + gologger.Print().Msgf("%s\n", serverTCP.ListenAndServe()) + } + gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) layers := loglayer(http.FileServer(http.Dir(opts.Folder))) if opts.BasicAuth != "" { From c8614c543900bda208d63a5103e0a40b1be5fc33 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 02:51:41 +0100 Subject: [PATCH 020/121] fixing conflict --- pkg/sslcert/options.go | 21 ++++++ pkg/sslcert/sslcert.go | 151 +++++++++++++++++++++++++++++++++++++++ pkg/sslcert/tlsconfig.go | 19 +++++ simplehttpserver.go | 19 ++++- 4 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 pkg/sslcert/options.go create mode 100644 pkg/sslcert/sslcert.go create mode 100644 pkg/sslcert/tlsconfig.go diff --git a/pkg/sslcert/options.go b/pkg/sslcert/options.go new file mode 100644 index 0000000..54cbc0d --- /dev/null +++ b/pkg/sslcert/options.go @@ -0,0 +1,21 @@ +package sslcert + +import "time" + +type Options struct { + Host string // Comma-separated hostnames and IPs to generate a certificate for") + Organization string + ValidFrom string // Creation date formatted as Jan 1 15:04:05 2011 + ValidFor time.Duration // 365*24*time.Hour Duration that certificate is valid for + IsCA bool // whether this cert should be its own Certificate Authority + RSABits int // 2048 Size of RSA key to generate. Ignored if --ecdsa-curve is set + EcdsaCurve string // ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 + Ed25519Key bool // Generate an Ed25519 key +} + +var DefaultOptions = Options{ + ValidFor: time.Duration(365 * 24 * time.Hour), + IsCA: false, + RSABits: 2048, + Organization: "Acme Co", +} diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go new file mode 100644 index 0000000..6469b78 --- /dev/null +++ b/pkg/sslcert/sslcert.go @@ -0,0 +1,151 @@ +// Package sslcert contains a reworked version of https://golang.org/src/crypto/tls/generate_cert.go +package sslcert + +import ( + "bufio" + "bytes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "math/big" + "net" + "strings" + "time" +) + +func pubKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} + +func Generate(options Options) (privateKey, publicKey []byte, err error) { + if options.Host == "" { + return nil, nil, errors.New("Empty host value") + } + + var priv interface{} + switch options.EcdsaCurve { + case "": + if options.Ed25519Key { + _, priv, err = ed25519.GenerateKey(rand.Reader) + } else { + priv, err = rsa.GenerateKey(rand.Reader, options.RSABits) + } + case "P224": + priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + case "P256": + priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + case "P384": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + case "P521": + priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + default: + err = fmt.Errorf("Unrecognized elliptic curve: %q", options.EcdsaCurve) + return + } + if err != nil { + err = fmt.Errorf("Failed to generate private key: %v", err) + return + } + + // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature + // KeyUsage bits set in the x509.Certificate template + keyUsage := x509.KeyUsageDigitalSignature + // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In + // the context of TLS this KeyUsage is particular to RSA key exchange and + // authentication. + if _, isRSA := priv.(*rsa.PrivateKey); isRSA { + keyUsage |= x509.KeyUsageKeyEncipherment + } + + var notBefore time.Time + if len(options.ValidFrom) == 0 { + notBefore = time.Now() + } else { + notBefore, err = time.Parse("Jan 2 15:04:05 2006", options.ValidFrom) + if err != nil { + err = fmt.Errorf("Failed to parse creation date: %v", err) + return + } + } + + notAfter := notBefore.Add(options.ValidFor) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + err = fmt.Errorf("Failed to generate serial number: %v", err) + return + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{options.Organization}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + + hosts := strings.Split(options.Host, ",") + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, h) + } + } + + if options.IsCA { + template.IsCA = true + template.KeyUsage |= x509.KeyUsageCertSign + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey(priv), priv) + if err != nil { + err = fmt.Errorf("Failed to create certificate: %v", err) + return + } + + var pubKeyBuf bytes.Buffer + pubKeyBufb := bufio.NewWriter(&pubKeyBuf) + err = pem.Encode(pubKeyBufb, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + err = fmt.Errorf("Failed to write data to cert.pem: %v", err) + return + } + + privBytes, err := x509.MarshalPKCS8PrivateKey(priv) + if err != nil { + err = fmt.Errorf("Unable to marshal private key: %v", err) + return + } + var privKeyBuf bytes.Buffer + privKeyBufb := bufio.NewWriter(&privKeyBuf) + err = pem.Encode(privKeyBufb, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) + if err != nil { + err = fmt.Errorf("Failed to write data to key.pem: %v", err) + return + } + + return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil +} diff --git a/pkg/sslcert/tlsconfig.go b/pkg/sslcert/tlsconfig.go new file mode 100644 index 0000000..e2bbe92 --- /dev/null +++ b/pkg/sslcert/tlsconfig.go @@ -0,0 +1,19 @@ +package sslcert + +import ( + "crypto/tls" +) + +func NewTLSConfig(options Options) (*tls.Config, error) { + pubKey, privKey, err := Generate(options) + if err != nil { + return nil, err + } + + cert, err := tls.X509KeyPair(pubKey, privKey) + if err != nil { + return nil, err + } + + return &tls.Config{Certificates: []tls.Certificate{cert}}, nil +} diff --git a/simplehttpserver.go b/simplehttpserver.go index 1335ce1..db3195c 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" ) @@ -24,6 +25,7 @@ type options struct { Realm string Certificate string Key string + Domain string HTTPS bool Verbose bool Upload bool @@ -44,6 +46,7 @@ func main() { flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") flag.StringVar(&opts.Certificate, "cert", "", "Certificate") flag.StringVar(&opts.Key, "key", "", "Key") + flag.StringVar(&opts.Domain, "domain", "", "Domain") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") flag.StringVar(&opts.BasicAuth, "basic-auth", "", "Basic auth (username:password)") flag.StringVar(&opts.Realm, "realm", "Please enter username and password", "Realm") @@ -85,9 +88,21 @@ func main() { } if opts.HTTPS { if opts.Certificate == "" || opts.Key == "" { - gologger.Fatal().Msgf("Certificate or Key file not specified") + tlsOptions := sslcert.DefaultOptions + tlsOptions.Host = opts.Domain + tlsConfig, err := sslcert.NewTLSConfig(tlsOptions) + if err != nil { + gologger.Fatal().Msgf("%s\n", err) + } + httpServer := &http.Server{ + Addr: opts.ListenAddress, + TLSConfig: tlsConfig, + } + httpServer.Handler = layers + gologger.Print().Msgf("%s\n", httpServer.ListenAndServeTLS("", "")) + } else { + gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) } - gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) } else { gologger.Print().Msgf("%s\n", http.ListenAndServe(opts.ListenAddress, layers)) } From ca04767a3b974785646d4612270b598e3daa6404 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 17:58:09 +0100 Subject: [PATCH 021/121] adding missing buffer flush --- pkg/sslcert/sslcert.go | 2 ++ simplehttpserver.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go index 6469b78..862ee21 100644 --- a/pkg/sslcert/sslcert.go +++ b/pkg/sslcert/sslcert.go @@ -133,6 +133,7 @@ func Generate(options Options) (privateKey, publicKey []byte, err error) { err = fmt.Errorf("Failed to write data to cert.pem: %v", err) return } + pubKeyBufb.Flush() privBytes, err := x509.MarshalPKCS8PrivateKey(priv) if err != nil { @@ -146,6 +147,7 @@ func Generate(options Options) (privateKey, publicKey []byte, err error) { err = fmt.Errorf("Failed to write data to key.pem: %v", err) return } + privKeyBufb.Flush() return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil } diff --git a/simplehttpserver.go b/simplehttpserver.go index db3195c..fff559f 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -46,7 +46,7 @@ func main() { flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") flag.StringVar(&opts.Certificate, "cert", "", "Certificate") flag.StringVar(&opts.Key, "key", "", "Key") - flag.StringVar(&opts.Domain, "domain", "", "Domain") + flag.StringVar(&opts.Domain, "domain", "local.host", "Domain") flag.BoolVar(&opts.Verbose, "v", false, "Verbose") flag.StringVar(&opts.BasicAuth, "basic-auth", "", "Basic auth (username:password)") flag.StringVar(&opts.Realm, "realm", "Please enter username and password", "Realm") From 7bfbf59c6bd11b08fde92673d37975d271be4234 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 20:22:29 +0100 Subject: [PATCH 022/121] fixing name --- pkg/tcpserver/tcpserver.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 607afe1..fc08f03 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -6,6 +6,7 @@ import ( "net" "time" + "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" "gopkg.in/yaml.v2" ) @@ -71,7 +72,7 @@ func (t *TCPServer) ListenAndServeTLS() error { tlsConfig = &tls.Config{Certificates: []tls.Certificate{cert}} } else { tlsOptions := sslcert.DefaultOptions - tlsOptions.Host = opts.Domain + tlsOptions.Host = t.options.Domain cfg, err := sslcert.NewTLSConfig(tlsOptions) if err != nil { return err From d728e2fb4dfa8cd35af9220d7a2edb4a478a00b5 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Tue, 23 Feb 2021 20:24:06 +0100 Subject: [PATCH 023/121] replacing log => gologger --- simplehttpserver.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index fff559f..47d516f 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "io/ioutil" - "log" "net/http" "net/http/httputil" "path" @@ -118,11 +117,11 @@ func loglayer(handler http.Handler) http.Handler { if opts.Upload && r.Method == http.MethodPut { data, err := ioutil.ReadAll(r.Body) if err != nil { - log.Println(err) + gologger.Print().Msgf("%s\n", err) } err = handleUpload(path.Base(r.URL.Path), data) if err != nil { - log.Println(err) + gologger.Print().Msgf("%s\n", err) } } From ca921084993fcf7cd7b8b2e606276a2c29e3f87b Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 24 Feb 2021 23:09:19 +0100 Subject: [PATCH 024/121] removing log package --- simplehttpserver.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 62cb4e6..50a8af1 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -6,7 +6,6 @@ import ( "flag" "fmt" "io/ioutil" - "log" "net" "net/http" "net/http/httputil" @@ -102,11 +101,11 @@ func loglayer(handler http.Handler) http.Handler { if opts.Upload && r.Method == http.MethodPut { data, err := ioutil.ReadAll(r.Body) if err != nil { - log.Println(err) + gologger.Print().Msgf("%s\n", err) } err = handleUpload(path.Base(r.URL.Path), data) if err != nil { - log.Println(err) + gologger.Print().Msgf("%s\n", err) } } From 9be5b1adc6427e6f6d9ec737d915cdfe6a90be40 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 24 Feb 2021 23:18:32 +0100 Subject: [PATCH 025/121] removing unused log --- simplehttpserver.go | 1 - 1 file changed, 1 deletion(-) diff --git a/simplehttpserver.go b/simplehttpserver.go index 1ad66e8..f03f258 100644 --- a/simplehttpserver.go +++ b/simplehttpserver.go @@ -6,7 +6,6 @@ import ( "flag" "fmt" "io/ioutil" - "log" "net" "net/http" "net/http/httputil" From c339cd798c40d8ec5ead8ec17b96d7bbac57df49 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 26 Feb 2021 08:42:34 +0100 Subject: [PATCH 026/121] code refactor --- .github/workflows/build.yaml | 4 +- .goreleaser.yml | 2 +- Dockerfile | 4 +- gen_cert.sh | 5 - internal/runner/banner.go | 24 ++++ internal/runner/doc.go | 2 + internal/runner/options.go | 93 ++++++++++++++ internal/runner/runner.go | 70 ++++++++++ pkg/httpserver/authlayer.go | 19 +++ pkg/httpserver/httpserver.go | 120 +++++++++++++++++ pkg/httpserver/loglayer.go | 69 ++++++++++ pkg/httpserver/uploadlayer.go | 7 + pkg/tcpserver/tcpserver.go | 7 + simplehttpserver.go | 233 ---------------------------------- 14 files changed, 416 insertions(+), 243 deletions(-) delete mode 100644 gen_cert.sh create mode 100644 internal/runner/banner.go create mode 100644 internal/runner/doc.go create mode 100644 internal/runner/options.go create mode 100644 internal/runner/runner.go create mode 100644 pkg/httpserver/authlayer.go create mode 100644 pkg/httpserver/httpserver.go create mode 100644 pkg/httpserver/loglayer.go create mode 100644 pkg/httpserver/uploadlayer.go delete mode 100644 simplehttpserver.go diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 008bca6..11d1658 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,8 +32,8 @@ jobs: - name: Test run: go test . - working-directory: . + working-directory: cmd/simplehttpserver/ - name: Build run: go build . - working-directory: . + working-directory: cmd/simplehttpserver/ diff --git a/.goreleaser.yml b/.goreleaser.yml index 50bb74f..f6cb1e2 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,6 +1,6 @@ builds: - binary: simplehttpserver - main: simplehttpserver.go + main: cmd/simplehttpserver/simplehttpserver.go goos: - linux - windows diff --git a/Dockerfile b/Dockerfile index a01590c..4603b20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM golang:1.14-alpine AS builder +FROM golang:1.16-alpine AS builder RUN apk add --no-cache git -RUN GO111MODULE=auto go get -u -v github.com/projectdiscovery/simplehttpserver +RUN GO111MODULE=auto go get -u -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest COPY --from=builder /go/bin/simplehttpserver /usr/local/bin/ diff --git a/gen_cert.sh b/gen_cert.sh deleted file mode 100644 index 0cba96a..0000000 --- a/gen_cert.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -openssl genrsa -out server.key 2048 -openssl ecparam -genkey -name secp384r1 -out server.key -openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 \ No newline at end of file diff --git a/internal/runner/banner.go b/internal/runner/banner.go new file mode 100644 index 0000000..c8972db --- /dev/null +++ b/internal/runner/banner.go @@ -0,0 +1,24 @@ +package runner + +import "github.com/projectdiscovery/gologger" + +const banner = ` + _ _ _ _ _ + ___(_)_ __ ___ _ __ | | ___| |__ | |_| |_ _ __ ___ ___ _ ____ _____ _ __ +/ __| | '_ ' _ \| '_ \| |/ _ \ '_ \| __| __| '_ \/ __|/ _ \ '__\ \ / / _ \ '__| +\__ \ | | | | | | |_) | | __/ | | | |_| |_| |_) \__ \ __/ | \ V / __/ | +|___/_|_| |_| |_| .__/|_|\___|_| |_|\__|\__| .__/|___/\___|_| \_/ \___|_| + |_| |_| +` + +// Version is the current version +const Version = `0.0.1` + +// showBanner is used to show the banner to the user +func showBanner() { + gologger.Print().Msgf("%s\n", banner) + gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n") + + gologger.Print().Msgf("Use with caution. You are responsible for your actions\n") + gologger.Print().Msgf("Developers assume no liability and are not responsible for any misuse or damage.\n") +} diff --git a/internal/runner/doc.go b/internal/runner/doc.go new file mode 100644 index 0000000..6d6e364 --- /dev/null +++ b/internal/runner/doc.go @@ -0,0 +1,2 @@ +// Package runner contains the internal logic +package runner diff --git a/internal/runner/options.go b/internal/runner/options.go new file mode 100644 index 0000000..3170cd3 --- /dev/null +++ b/internal/runner/options.go @@ -0,0 +1,93 @@ +package runner + +import ( + "flag" + "os" + "strings" + + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/gologger/levels" +) + +type Options struct { + ListenAddress string + Folder string + BasicAuth string + username string + password string + Realm string + TLSCertificate string + TLSKey string + TLSDomain string + HTTPS bool + Verbose bool + EnableUpload bool + EnableTCP bool + RulesFile string + TCPWithTLS bool + Version bool + Silent bool +} + +// ParseOptions parses the command line options for application +func ParseOptions() *Options { + options := &Options{} + flag.StringVar(&options.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") + flag.BoolVar(&options.EnableTCP, "tcp", false, "TCP Server") + flag.BoolVar(&options.TCPWithTLS, "tls", false, "Enable TCP TLS") + flag.StringVar(&options.RulesFile, "rules", "", "Rules yaml file") + flag.StringVar(&options.Folder, "path", ".", "Folder") + flag.BoolVar(&options.EnableUpload, "upload", false, "Enable upload via PUT") + flag.BoolVar(&options.HTTPS, "https", false, "HTTPS") + flag.StringVar(&options.TLSCertificate, "cert", "", "HTTPS Certificate") + flag.StringVar(&options.TLSKey, "key", "", "HTTPS Certificate Key") + flag.StringVar(&options.TLSDomain, "domain", "local.host", "Domain") + flag.BoolVar(&options.Verbose, "verbose", false, "Verbose") + flag.StringVar(&options.BasicAuth, "basic-auth", "", "Basic auth (username:password)") + flag.StringVar(&options.Realm, "realm", "Please enter username and password", "Realm") + flag.BoolVar(&options.Version, "version", false, "Show version of the software") + flag.BoolVar(&options.Silent, "silent", false, "Show only results in the output") + + flag.Parse() + + // Read the inputs and configure the logging + options.configureOutput() + + showBanner() + + if options.Version { + gologger.Info().Msgf("Current Version: %s\n", Version) + os.Exit(0) + } + + options.validateOptions() + + return options +} + +func (options *Options) validateOptions() { + if flag.NArg() > 0 && options.Folder == "." { + options.Folder = flag.Args()[0] + } + + if options.BasicAuth != "" { + baTokens := strings.SplitN(options.BasicAuth, ":", 2) + if len(baTokens) > 0 { + options.username = baTokens[0] + } + if len(baTokens) > 1 { + options.password = baTokens[1] + } + } +} + +// configureOutput configures the output on the screen +func (options *Options) configureOutput() { + // If the user desires verbose output, show verbose output + if options.Verbose { + gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose) + } + if options.Silent { + gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) + } +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go new file mode 100644 index 0000000..a5d5230 --- /dev/null +++ b/internal/runner/runner.go @@ -0,0 +1,70 @@ +package runner + +import ( + "github.com/projectdiscovery/simplehttpserver/pkg/httpserver" + "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" +) + +// Runner is a client for running the enumeration process. +type Runner struct { + options *Options + serverTCP *tcpserver.TCPServer + httpServer *httpserver.HTTPServer +} + +func New(options *Options) (*Runner, error) { + r := Runner{options: options} + if r.options.EnableTCP { + serverTCP, err := tcpserver.New(tcpserver.Options{ + Listen: r.options.ListenAddress, + TLS: r.options.TCPWithTLS, + Domain: "local.host", + Verbose: r.options.Verbose, + }) + if err != nil { + return nil, err + } + err = serverTCP.LoadTemplate(r.options.RulesFile) + if err != nil { + return nil, err + } + r.serverTCP = serverTCP + return &r, nil + } + + httpServer, err := httpserver.New(&httpserver.Options{ + Folder: r.options.Folder, + EnableUpload: r.options.EnableUpload, + ListenAddress: r.options.ListenAddress, + TLS: r.options.HTTPS, + Certificate: r.options.TLSCertificate, + CertificateKey: r.options.TLSKey, + CertificateDomain: r.options.TLSDomain, + BasicAuthUsername: r.options.username, + BasicAuthPassword: r.options.password, + BasicAuthReal: r.options.Realm, + Verbose: r.options.Verbose, + }) + if err != nil { + return nil, err + } + r.httpServer = httpServer + + return &r, nil +} + +func (r *Runner) Run() error { + if r.options.EnableTCP { + return r.serverTCP.ListenAndServe() + } + + if r.options.HTTPS { + return r.httpServer.ListenAndServeTLS() + } + + return r.httpServer.ListenAndServe() +} + +func (r *Runner) Close() error { + return nil +} diff --git a/pkg/httpserver/authlayer.go b/pkg/httpserver/authlayer.go new file mode 100644 index 0000000..f2eff4b --- /dev/null +++ b/pkg/httpserver/authlayer.go @@ -0,0 +1,19 @@ +package httpserver + +import ( + "fmt" + "net/http" +) + +func (t *HTTPServer) basicauthlayer(handler http.Handler) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + user, pass, ok := r.BasicAuth() + if !ok || user != t.options.BasicAuthUsername || pass != t.options.BasicAuthPassword { + w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", t.options.BasicAuthReal)) + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte("Unauthorized.\n")) //nolint + return + } + handler.ServeHTTP(w, r) + }) +} diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go new file mode 100644 index 0000000..6e817d3 --- /dev/null +++ b/pkg/httpserver/httpserver.go @@ -0,0 +1,120 @@ +package httpserver + +import ( + "errors" + "net" + "net/http" + "os" + "runtime" + "strconv" + "syscall" + + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" +) + +type Options struct { + Folder string + EnableUpload bool + ListenAddress string + TLS bool + Certificate string + CertificateKey string + CertificateDomain string + BasicAuthUsername string + BasicAuthPassword string + BasicAuthReal string + Verbose bool +} + +type HTTPServer struct { + options *Options + layers http.Handler + listener net.Listener +} + +func New(options *Options) (*HTTPServer, error) { + var h HTTPServer + EnableUpload = options.EnableUpload + EnableVerbose = options.Verbose + layers := h.loglayer(http.FileServer(http.Dir(options.Folder))) + if options.BasicAuthUsername != "" || options.BasicAuthPassword != "" { + layers = h.loglayer(h.basicauthlayer(http.FileServer(http.Dir(options.Folder)))) + } + + return &HTTPServer{options: options, layers: layers}, nil +} + +func (t *HTTPServer) ListenAndServe() error { + var err error +retry_listen: + gologger.Print().Msgf("Serving %s on http://%s/...", t.options.Folder, t.options.ListenAddress) + err = http.ListenAndServe(t.options.ListenAddress, t.layers) + if err != nil { + if isErrorAddressAlreadyInUse(err) { + gologger.Print().Msgf("Can't listen on %s: %s - retrying with another port\n", t.options.ListenAddress, err) + newListenAddress, err := incPort(t.options.ListenAddress) + if err != nil { + return err + } + t.options.ListenAddress = newListenAddress + goto retry_listen + } + } + return nil +} + +func (t *HTTPServer) ListenAndServeTLS() error { + gologger.Print().Msgf("Serving %s on https://%s/...", t.options.Folder, t.options.ListenAddress) + if t.options.Certificate == "" || t.options.CertificateKey == "" { + tlsOptions := sslcert.DefaultOptions + tlsOptions.Host = t.options.CertificateDomain + tlsConfig, err := sslcert.NewTLSConfig(tlsOptions) + if err != nil { + return err + } + httpServer := &http.Server{ + Addr: t.options.ListenAddress, + TLSConfig: tlsConfig, + } + httpServer.Handler = t.layers + return httpServer.ListenAndServeTLS("", "") + } + return http.ListenAndServeTLS(t.options.ListenAddress, t.options.Certificate, t.options.CertificateKey, t.layers) +} + +func isErrorAddressAlreadyInUse(err error) bool { + var eOsSyscall *os.SyscallError + if !errors.As(err, &eOsSyscall) { + return false + } + var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr) + if !errors.As(eOsSyscall, &errErrno) { + return false + } + if errErrno == syscall.EADDRINUSE { + return true + } + const WSAEADDRINUSE = 10048 + if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE { + return true + } + return false +} + +func incPort(address string) (string, error) { + addrOrig, portOrig, err := net.SplitHostPort(address) + if err != nil { + return address, err + } + + // increment port + portNumber, err := strconv.Atoi(portOrig) + if err != nil { + return address, err + } + portNumber++ + newPort := strconv.FormatInt(int64(portNumber), 10) + + return net.JoinHostPort(addrOrig, newPort), nil +} diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go new file mode 100644 index 0000000..2d84d9a --- /dev/null +++ b/pkg/httpserver/loglayer.go @@ -0,0 +1,69 @@ +package httpserver + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/http/httputil" + "path" + + "github.com/projectdiscovery/gologger" +) + +// Convenience globals +var ( + EnableUpload bool + EnableVerbose bool +) + +func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fullRequest, _ := httputil.DumpRequest(r, true) + lrw := newLoggingResponseWriter(w) + handler.ServeHTTP(lrw, r) + + // Handles file write if enabled + if EnableUpload && r.Method == http.MethodPut { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + gologger.Print().Msgf("%s\n", err) + } + err = handleUpload(path.Base(r.URL.Path), data) + if err != nil { + gologger.Print().Msgf("%s\n", err) + } + } + + if EnableVerbose { + headers := new(bytes.Buffer) + lrw.Header().Write(headers) //nolint + gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) + } else { + gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data)) + } + }) +} + +type loggingResponseWriter struct { + http.ResponseWriter + statusCode int + Data []byte +} + +func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { + return &loggingResponseWriter{w, http.StatusOK, []byte{}} +} + +func (lrw *loggingResponseWriter) Write(data []byte) (int, error) { + lrw.Data = append(lrw.Data, data...) + return lrw.ResponseWriter.Write(data) +} + +func (lrw *loggingResponseWriter) Header() http.Header { + return lrw.ResponseWriter.Header() +} + +func (lrw *loggingResponseWriter) WriteHeader(code int) { + lrw.statusCode = code + lrw.ResponseWriter.WriteHeader(code) +} diff --git a/pkg/httpserver/uploadlayer.go b/pkg/httpserver/uploadlayer.go new file mode 100644 index 0000000..2663fba --- /dev/null +++ b/pkg/httpserver/uploadlayer.go @@ -0,0 +1,7 @@ +package httpserver + +import "io/ioutil" + +func handleUpload(file string, data []byte) error { + return ioutil.WriteFile(file, data, 0655) +} diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index fc08f03..15be615 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -6,6 +6,7 @@ import ( "net" "time" + "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" "gopkg.in/yaml.v2" ) @@ -17,6 +18,7 @@ type Options struct { Key string Domain string rules []Rule + Verbose bool } type TCPServer struct { @@ -34,6 +36,7 @@ func (t *TCPServer) AddRule(rule Rule) error { } func (t *TCPServer) ListenAndServe() error { + gologger.Print().Msgf("Serving %s on tcp://%s", t.options.Listen) listener, err := net.Listen("tcp4", t.options.Listen) if err != nil { return err @@ -53,12 +56,16 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { return err } + gologger.Print().Msgf("%s\n", buf) + resp, err := t.BuildResponse(buf) if err != nil { return err } conn.Write(resp) + + gologger.Print().Msgf("%s\n", resp) } } diff --git a/simplehttpserver.go b/simplehttpserver.go deleted file mode 100644 index f03f258..0000000 --- a/simplehttpserver.go +++ /dev/null @@ -1,233 +0,0 @@ -package main - -import ( - "bytes" - "errors" - "flag" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/http/httputil" - "os" - "path" - "runtime" - "strconv" - "strings" - "syscall" - - "github.com/projectdiscovery/gologger" - "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" - "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" -) - -type options struct { - ListenAddress string - Folder string - BasicAuth string - username string - password string - Realm string - Certificate string - Key string - Domain string - HTTPS bool - Verbose bool - Upload bool - TCP bool - RulesFile string - TLS bool -} - -var opts options - -func main() { - flag.StringVar(&opts.ListenAddress, "listen", "0.0.0.0:8000", "Address:Port") - flag.BoolVar(&opts.TCP, "tcp", false, "TCP Server") - flag.BoolVar(&opts.TLS, "tls", false, "Enable TCP TLS") - flag.StringVar(&opts.RulesFile, "rules", "", "Rules yaml file") - flag.StringVar(&opts.Folder, "path", ".", "Folder") - flag.BoolVar(&opts.Upload, "upload", false, "Enable upload via PUT") - flag.BoolVar(&opts.HTTPS, "https", false, "HTTPS") - flag.StringVar(&opts.Certificate, "cert", "", "Certificate") - flag.StringVar(&opts.Key, "key", "", "Key") - flag.StringVar(&opts.Domain, "domain", "local.host", "Domain") - flag.BoolVar(&opts.Verbose, "v", false, "Verbose") - flag.StringVar(&opts.BasicAuth, "basic-auth", "", "Basic auth (username:password)") - flag.StringVar(&opts.Realm, "realm", "Please enter username and password", "Realm") - - flag.Parse() - - if flag.NArg() > 0 && opts.Folder == "." { - opts.Folder = flag.Args()[0] - } - - if opts.TCP { - serverTCP, err := tcpserver.New(tcpserver.Options{Listen: opts.ListenAddress, TLS: opts.TLS, Domain: "local.host"}) - if err != nil { - gologger.Fatal().Msgf("%s\n", err) - } - err = serverTCP.LoadTemplate(opts.RulesFile) - if err != nil { - gologger.Fatal().Msgf("%s\n", err) - } - - gologger.Print().Msgf("%s\n", serverTCP.ListenAndServe()) - } - - gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) - layers := loglayer(http.FileServer(http.Dir(opts.Folder))) - if opts.BasicAuth != "" { - baTokens := strings.SplitN(opts.BasicAuth, ":", 2) - if len(baTokens) > 0 { - opts.username = baTokens[0] - } - if len(baTokens) > 1 { - opts.password = baTokens[1] - } - layers = loglayer(basicauthlayer(http.FileServer(http.Dir(opts.Folder)))) - } - if opts.Upload { - gologger.Print().Msg("Starting service with Upload enabled") - } -retry_listen: - gologger.Print().Msgf("Serving %s on http://%s/...", opts.Folder, opts.ListenAddress) - var err error - if opts.HTTPS { - if opts.Certificate == "" || opts.Key == "" { - tlsOptions := sslcert.DefaultOptions - tlsOptions.Host = opts.Domain - tlsConfig, err := sslcert.NewTLSConfig(tlsOptions) - if err != nil { - gologger.Fatal().Msgf("%s\n", err) - } - httpServer := &http.Server{ - Addr: opts.ListenAddress, - TLSConfig: tlsConfig, - } - httpServer.Handler = layers - gologger.Print().Msgf("%s\n", httpServer.ListenAndServeTLS("", "")) - } else { - gologger.Print().Msgf("%s\n", http.ListenAndServeTLS(opts.ListenAddress, opts.Certificate, opts.Key, layers)) - } - } else { - err = http.ListenAndServe(opts.ListenAddress, layers) - } - if err != nil { - if isErrorAddressAlreadyInUse(err) { - gologger.Print().Msgf("Can't listen on %s: %s - retrying with another port\n", opts.ListenAddress, err) - newListenAddress, err := incPort(opts.ListenAddress) - if err != nil { - gologger.Fatal().Msgf("%s\n", err) - } - opts.ListenAddress = newListenAddress - goto retry_listen - } - gologger.Print().Msgf("%s\n", err) - } -} - -func loglayer(handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fullRequest, _ := httputil.DumpRequest(r, true) - lrw := newLoggingResponseWriter(w) - handler.ServeHTTP(lrw, r) - - // Handles file write if enabled - if opts.Upload && r.Method == http.MethodPut { - data, err := ioutil.ReadAll(r.Body) - if err != nil { - gologger.Print().Msgf("%s\n", err) - } - err = handleUpload(path.Base(r.URL.Path), data) - if err != nil { - gologger.Print().Msgf("%s\n", err) - } - } - - if opts.Verbose { - headers := new(bytes.Buffer) - lrw.Header().Write(headers) //nolint - gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) - } else { - gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data)) - } - }) -} - -func basicauthlayer(handler http.Handler) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - user, pass, ok := r.BasicAuth() - if !ok || user != opts.username || pass != opts.password { - w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=\"%s\"", opts.Realm)) - w.WriteHeader(http.StatusUnauthorized) - w.Write([]byte("Unauthorized.\n")) //nolint - return - } - handler.ServeHTTP(w, r) - }) -} - -type loggingResponseWriter struct { - http.ResponseWriter - statusCode int - Data []byte -} - -func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { - return &loggingResponseWriter{w, http.StatusOK, []byte{}} -} - -func (lrw *loggingResponseWriter) Write(data []byte) (int, error) { - lrw.Data = append(lrw.Data, data...) - return lrw.ResponseWriter.Write(data) -} - -func (lrw *loggingResponseWriter) Header() http.Header { - return lrw.ResponseWriter.Header() -} - -func (lrw *loggingResponseWriter) WriteHeader(code int) { - lrw.statusCode = code - lrw.ResponseWriter.WriteHeader(code) -} - -func handleUpload(file string, data []byte) error { - return ioutil.WriteFile(file, data, 0655) -} - -func isErrorAddressAlreadyInUse(err error) bool { - var eOsSyscall *os.SyscallError - if !errors.As(err, &eOsSyscall) { - return false - } - var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr) - if !errors.As(eOsSyscall, &errErrno) { - return false - } - if errErrno == syscall.EADDRINUSE { - return true - } - const WSAEADDRINUSE = 10048 - if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE { - return true - } - return false -} - -func incPort(address string) (string, error) { - addrOrig, portOrig, err := net.SplitHostPort(address) - if err != nil { - return address, err - } - - // increment port - portNumber, err := strconv.Atoi(portOrig) - if err != nil { - return address, err - } - portNumber++ - newPort := strconv.FormatInt(int64(portNumber), 10) - - return net.JoinHostPort(addrOrig, newPort), nil -} From ced71943a55da047f29d9b990bdd0a6bab459a11 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 26 Feb 2021 21:11:20 +0100 Subject: [PATCH 027/121] bind logic refactor --- go.mod | 1 + go.sum | 2 ++ internal/runner/runner.go | 21 +++++++++++++ pkg/binder/binder.go | 32 +++++++++++++++++++ pkg/httpserver/httpserver.go | 60 ++---------------------------------- 5 files changed, 59 insertions(+), 57 deletions(-) create mode 100644 pkg/binder/binder.go diff --git a/go.mod b/go.mod index 2bc0442..f8bb144 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.15 require ( + github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index bd1e991..6757769 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI= diff --git a/internal/runner/runner.go b/internal/runner/runner.go index a5d5230..94b8c37 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -1,6 +1,8 @@ package runner import ( + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/binder" "github.com/projectdiscovery/simplehttpserver/pkg/httpserver" "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" ) @@ -14,6 +16,16 @@ type Runner struct { func New(options *Options) (*Runner, error) { r := Runner{options: options} + // Check if the process can listen on the specified ip:port + if !binder.CanListenOn(r.options.ListenAddress) { + newListenAddress, err := binder.GetRandomListenAddress(r.options.ListenAddress) + if err != nil { + return nil, err + } + gologger.Print().Msgf("Can't listen on %s: %s - Using\n", r.options.ListenAddress, err, newListenAddress) + r.options.ListenAddress = newListenAddress + } + if r.options.EnableTCP { serverTCP, err := tcpserver.New(tcpserver.Options{ Listen: r.options.ListenAddress, @@ -55,16 +67,25 @@ func New(options *Options) (*Runner, error) { func (r *Runner) Run() error { if r.options.EnableTCP { + gologger.Print().Msgf("Serving TCP rule based server on tcp://%s", r.options.ListenAddress) return r.serverTCP.ListenAndServe() } if r.options.HTTPS { + gologger.Print().Msgf("Serving %s on https://%s/...", r.options.Folder, r.options.ListenAddress) return r.httpServer.ListenAndServeTLS() } + gologger.Print().Msgf("Serving %s on http://%s/...", r.options.Folder, r.options.ListenAddress) return r.httpServer.ListenAndServe() } func (r *Runner) Close() error { + if r.serverTCP != nil { + r.serverTCP.Close() + } + if r.httpServer != nil { + r.httpServer.Close() + } return nil } diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go new file mode 100644 index 0000000..2a248a1 --- /dev/null +++ b/pkg/binder/binder.go @@ -0,0 +1,32 @@ +package binder + +import ( + "fmt" + "net" + + "github.com/phayes/freeport" +) + +func CanListenOn(address string) bool { + listener, err := net.Listen("tcp4", address) + if err != nil { + return false + } + defer listener.Close() + return true +} + +func GetRandomListenAddress(currentAddress string) (string, error) { + addrOrig, _, err := net.SplitHostPort(currentAddress) + if err != nil { + return "", err + } + + newPort, err := freeport.GetFreePort() + if err != nil { + return "", err + } + + return net.JoinHostPort(addrOrig, fmt.Sprintf("%d", newPort)), nil + +} diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 6e817d3..c37355e 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -1,15 +1,9 @@ package httpserver import ( - "errors" "net" "net/http" - "os" - "runtime" - "strconv" - "syscall" - "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" ) @@ -46,26 +40,10 @@ func New(options *Options) (*HTTPServer, error) { } func (t *HTTPServer) ListenAndServe() error { - var err error -retry_listen: - gologger.Print().Msgf("Serving %s on http://%s/...", t.options.Folder, t.options.ListenAddress) - err = http.ListenAndServe(t.options.ListenAddress, t.layers) - if err != nil { - if isErrorAddressAlreadyInUse(err) { - gologger.Print().Msgf("Can't listen on %s: %s - retrying with another port\n", t.options.ListenAddress, err) - newListenAddress, err := incPort(t.options.ListenAddress) - if err != nil { - return err - } - t.options.ListenAddress = newListenAddress - goto retry_listen - } - } - return nil + return http.ListenAndServe(t.options.ListenAddress, t.layers) } func (t *HTTPServer) ListenAndServeTLS() error { - gologger.Print().Msgf("Serving %s on https://%s/...", t.options.Folder, t.options.ListenAddress) if t.options.Certificate == "" || t.options.CertificateKey == "" { tlsOptions := sslcert.DefaultOptions tlsOptions.Host = t.options.CertificateDomain @@ -83,38 +61,6 @@ func (t *HTTPServer) ListenAndServeTLS() error { return http.ListenAndServeTLS(t.options.ListenAddress, t.options.Certificate, t.options.CertificateKey, t.layers) } -func isErrorAddressAlreadyInUse(err error) bool { - var eOsSyscall *os.SyscallError - if !errors.As(err, &eOsSyscall) { - return false - } - var errErrno syscall.Errno // doesn't need a "*" (ptr) because it's already a ptr (uintptr) - if !errors.As(eOsSyscall, &errErrno) { - return false - } - if errErrno == syscall.EADDRINUSE { - return true - } - const WSAEADDRINUSE = 10048 - if runtime.GOOS == "windows" && errErrno == WSAEADDRINUSE { - return true - } - return false -} - -func incPort(address string) (string, error) { - addrOrig, portOrig, err := net.SplitHostPort(address) - if err != nil { - return address, err - } - - // increment port - portNumber, err := strconv.Atoi(portOrig) - if err != nil { - return address, err - } - portNumber++ - newPort := strconv.FormatInt(int64(portNumber), 10) - - return net.JoinHostPort(addrOrig, newPort), nil +func (t *HTTPServer) Close() error { + return nil } From 254d46196632274f3cc7b6b3a8252d0b7b27d59b Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 26 Feb 2021 21:14:27 +0100 Subject: [PATCH 028/121] misc --- internal/runner/runner.go | 2 +- pkg/tcpserver/tcpserver.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 94b8c37..6603d50 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -22,7 +22,7 @@ func New(options *Options) (*Runner, error) { if err != nil { return nil, err } - gologger.Print().Msgf("Can't listen on %s: %s - Using\n", r.options.ListenAddress, err, newListenAddress) + gologger.Print().Msgf("Can't listen on %s: %s - Using %s\n", r.options.ListenAddress, err, newListenAddress) r.options.ListenAddress = newListenAddress } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 15be615..7d46b3a 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -36,7 +36,6 @@ func (t *TCPServer) AddRule(rule Rule) error { } func (t *TCPServer) ListenAndServe() error { - gologger.Print().Msgf("Serving %s on tcp://%s", t.options.Listen) listener, err := net.Listen("tcp4", t.options.Listen) if err != nil { return err From 80f5074a7d0769b32c31af5c78a77821516990c2 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 26 Feb 2021 22:45:27 +0100 Subject: [PATCH 029/121] adding missing files --- .gitignore | 1 - cmd/simplehttpserver/simplehttpserver.go | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 cmd/simplehttpserver/simplehttpserver.go diff --git a/.gitignore b/.gitignore index dabd7a7..b883f1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ *.exe -simplehttpserver diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go new file mode 100644 index 0000000..0dbbe6c --- /dev/null +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -0,0 +1,18 @@ +package main + +import ( + "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/internal/runner" +) + +func main() { + // Parse the command line flags and read config files + options := runner.ParseOptions() + runner, err := runner.New(options) + if err != nil { + gologger.Fatal().Msgf("Could not create runner: %s\n", err) + } + + runner.Run() + runner.Close() +} From fb9d1df1004215a31b89b5ad47911ca43475613e Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:06:42 +0200 Subject: [PATCH 030/121] adding common tools to docker --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 4603b20..0919a3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,7 @@ RUN apk add --no-cache git RUN GO111MODULE=auto go get -u -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest +RUN apk add --no-cache bind-tools ca-certificates COPY --from=builder /go/bin/simplehttpserver /usr/local/bin/ ENTRYPOINT ["simplehttpserver"] From 49ceaa7165da0d8fe1bb991b1094d0d95b8f17aa Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:07:06 +0200 Subject: [PATCH 031/121] removing sslcert + deps bump --- go.mod | 1 + go.sum | 2 + pkg/httpserver/httpserver.go | 8 +- pkg/sslcert/options.go | 21 ----- pkg/sslcert/sslcert.go | 153 ----------------------------------- pkg/sslcert/tlsconfig.go | 19 ----- pkg/tcpserver/tcpserver.go | 2 +- 7 files changed, 7 insertions(+), 199 deletions(-) delete mode 100644 pkg/sslcert/options.go delete mode 100644 pkg/sslcert/sslcert.go delete mode 100644 pkg/sslcert/tlsconfig.go diff --git a/go.mod b/go.mod index f8bb144..1d88f80 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.15 require ( github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 + github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 6757769..aafe4a2 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI= github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY= +github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e h1:IZa08TUGbU7I0HUb9QQt/8wuu2fPZqfnMXwWhtMxei8= +github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e/go.mod h1:jSp8W5zIkNPxAqVdcoFlfv0K5cqogTe65fMinR0Fvuk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index c37355e..958a6e7 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -1,10 +1,9 @@ package httpserver import ( - "net" "net/http" - "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" + "github.com/projectdiscovery/sslcert" ) type Options struct { @@ -22,9 +21,8 @@ type Options struct { } type HTTPServer struct { - options *Options - layers http.Handler - listener net.Listener + options *Options + layers http.Handler } func New(options *Options) (*HTTPServer, error) { diff --git a/pkg/sslcert/options.go b/pkg/sslcert/options.go deleted file mode 100644 index 54cbc0d..0000000 --- a/pkg/sslcert/options.go +++ /dev/null @@ -1,21 +0,0 @@ -package sslcert - -import "time" - -type Options struct { - Host string // Comma-separated hostnames and IPs to generate a certificate for") - Organization string - ValidFrom string // Creation date formatted as Jan 1 15:04:05 2011 - ValidFor time.Duration // 365*24*time.Hour Duration that certificate is valid for - IsCA bool // whether this cert should be its own Certificate Authority - RSABits int // 2048 Size of RSA key to generate. Ignored if --ecdsa-curve is set - EcdsaCurve string // ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 - Ed25519Key bool // Generate an Ed25519 key -} - -var DefaultOptions = Options{ - ValidFor: time.Duration(365 * 24 * time.Hour), - IsCA: false, - RSABits: 2048, - Organization: "Acme Co", -} diff --git a/pkg/sslcert/sslcert.go b/pkg/sslcert/sslcert.go deleted file mode 100644 index 862ee21..0000000 --- a/pkg/sslcert/sslcert.go +++ /dev/null @@ -1,153 +0,0 @@ -// Package sslcert contains a reworked version of https://golang.org/src/crypto/tls/generate_cert.go -package sslcert - -import ( - "bufio" - "bytes" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "errors" - "fmt" - "math/big" - "net" - "strings" - "time" -) - -func pubKey(priv interface{}) interface{} { - switch k := priv.(type) { - case *rsa.PrivateKey: - return &k.PublicKey - case *ecdsa.PrivateKey: - return &k.PublicKey - case ed25519.PrivateKey: - return k.Public().(ed25519.PublicKey) - default: - return nil - } -} - -func Generate(options Options) (privateKey, publicKey []byte, err error) { - if options.Host == "" { - return nil, nil, errors.New("Empty host value") - } - - var priv interface{} - switch options.EcdsaCurve { - case "": - if options.Ed25519Key { - _, priv, err = ed25519.GenerateKey(rand.Reader) - } else { - priv, err = rsa.GenerateKey(rand.Reader, options.RSABits) - } - case "P224": - priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) - case "P256": - priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - case "P384": - priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) - case "P521": - priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) - default: - err = fmt.Errorf("Unrecognized elliptic curve: %q", options.EcdsaCurve) - return - } - if err != nil { - err = fmt.Errorf("Failed to generate private key: %v", err) - return - } - - // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature - // KeyUsage bits set in the x509.Certificate template - keyUsage := x509.KeyUsageDigitalSignature - // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In - // the context of TLS this KeyUsage is particular to RSA key exchange and - // authentication. - if _, isRSA := priv.(*rsa.PrivateKey); isRSA { - keyUsage |= x509.KeyUsageKeyEncipherment - } - - var notBefore time.Time - if len(options.ValidFrom) == 0 { - notBefore = time.Now() - } else { - notBefore, err = time.Parse("Jan 2 15:04:05 2006", options.ValidFrom) - if err != nil { - err = fmt.Errorf("Failed to parse creation date: %v", err) - return - } - } - - notAfter := notBefore.Add(options.ValidFor) - - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - err = fmt.Errorf("Failed to generate serial number: %v", err) - return - } - - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{options.Organization}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - - KeyUsage: keyUsage, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - } - - hosts := strings.Split(options.Host, ",") - for _, h := range hosts { - if ip := net.ParseIP(h); ip != nil { - template.IPAddresses = append(template.IPAddresses, ip) - } else { - template.DNSNames = append(template.DNSNames, h) - } - } - - if options.IsCA { - template.IsCA = true - template.KeyUsage |= x509.KeyUsageCertSign - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pubKey(priv), priv) - if err != nil { - err = fmt.Errorf("Failed to create certificate: %v", err) - return - } - - var pubKeyBuf bytes.Buffer - pubKeyBufb := bufio.NewWriter(&pubKeyBuf) - err = pem.Encode(pubKeyBufb, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - if err != nil { - err = fmt.Errorf("Failed to write data to cert.pem: %v", err) - return - } - pubKeyBufb.Flush() - - privBytes, err := x509.MarshalPKCS8PrivateKey(priv) - if err != nil { - err = fmt.Errorf("Unable to marshal private key: %v", err) - return - } - var privKeyBuf bytes.Buffer - privKeyBufb := bufio.NewWriter(&privKeyBuf) - err = pem.Encode(privKeyBufb, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) - if err != nil { - err = fmt.Errorf("Failed to write data to key.pem: %v", err) - return - } - privKeyBufb.Flush() - - return pubKeyBuf.Bytes(), privKeyBuf.Bytes(), nil -} diff --git a/pkg/sslcert/tlsconfig.go b/pkg/sslcert/tlsconfig.go deleted file mode 100644 index e2bbe92..0000000 --- a/pkg/sslcert/tlsconfig.go +++ /dev/null @@ -1,19 +0,0 @@ -package sslcert - -import ( - "crypto/tls" -) - -func NewTLSConfig(options Options) (*tls.Config, error) { - pubKey, privKey, err := Generate(options) - if err != nil { - return nil, err - } - - cert, err := tls.X509KeyPair(pubKey, privKey) - if err != nil { - return nil, err - } - - return &tls.Config{Certificates: []tls.Certificate{cert}}, nil -} diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 7d46b3a..f78f876 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -7,7 +7,7 @@ import ( "time" "github.com/projectdiscovery/gologger" - "github.com/projectdiscovery/simplehttpserver/pkg/sslcert" + "github.com/projectdiscovery/sslcert" "gopkg.in/yaml.v2" ) From d068ebe21e9a746612bc357a8cda8fa29d7720c6 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:40:25 +0200 Subject: [PATCH 032/121] using go 1.14 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1d88f80..f4c4a9d 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectdiscovery/simplehttpserver -go 1.15 +go 1.14 require ( github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 From e55d3feac94109c6eded54b0a6a98edd7933921e Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 16:41:26 +0200 Subject: [PATCH 033/121] updated readme --- README.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f88164f..00daf9c 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ [![Docker Images](https://img.shields.io/docker/pulls/projectdiscovery/simplehttpserver.svg)](https://hub.docker.com/r/projectdiscovery/simplehttpserver) [![Chat on Discord](https://img.shields.io/discord/695645237418131507.svg?logo=discord)](https://discord.gg/KECAGdH) -simplehttpserver is a go enhanced version of the well known python simplehttpserver. +simplehttpserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. # Resources - [Features](#features) - [Usage](#usage) - [Installation Instructions](#installation-instructions) -- [Running simplehttpserver](#running-simplehttpserver-in-the-current-folder ) +- [Running simplehttpserver](#running-simplehttpserver-in-the-current-folder) - [Thanks](#thanks) # Features @@ -28,9 +28,11 @@ simplehttpserver is a go enhanced version of the well known python simplehttpser
- - File server in arbitrary directory - - Full request/response dump - - Configurable ip address and listening port +- HTTPS support +- File server in arbitrary directory +- Full request/response dump +- Configurable ip address and listening port +- Configurable HTTP/TCP server with customizable response via YAML template # Installation Instructions @@ -70,11 +72,23 @@ simplehttpserver -h This will display help for the tool. Here are all the switches it supports. -| Flag | Description | Example | -| ------ | ---------------------------------------------------- | --------------------------------------- | -| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | -| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | -| v | Verbose (dump request/response, default false) | simplehttpserver -v | +| Flag | Description | Example | +| ----------- | -------------------------------------------------------------------- | ------------------------------------------------- | +| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | +| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | +| verbose | Verbose (dump request/response, default false) | simplehttpserver -v | +| tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | +| tls | Enable TLS for TCP server | simplehttpserver -tls | +| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | | +| upload | Enable file upload in case of http server | simplehttpserver -upload | +| https | Enable HTTPS in case of http server | simplehttpserver -https | +| cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | +| key | HTTPS/TLS certificate private key (self generated if not specified) | simplehttpserver -key cert.key | +| domain | Domain name to use for the self-generated certificate | simplehttpserver -domain projectdiscovery.io | +| basic-auth | Basic auth (username:password) | simplehttpserver -basic-auth user:password | +| realm | Basic auth message | simplehttpserver -realm "insert the credentials" | +| version | Show version | simplehttpserver -version | +| silent | Show only results | simplehttpserver -silent | ### Running simplehttpserver in the current folder @@ -87,6 +101,91 @@ This will run the tool exposing the current directory on port 8000 2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 ``` +### Running simplehttpserver in the current folder with HTTPS + +This will run the tool exposing the current directory on port 8000 over HTTPS with user provided certificate: + +```sh +▶ simplehttpserver -https -cert cert.pen -key cert.key +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 +2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 +``` + +Instead, to run with self-signed certificate and specific domain name: +```sh +▶ simplehttpserver -https -domain localhost +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 +2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 +``` + +### Running simplehttpserver with basic auth and file upload + +This will run the tool and will request the user to enter username and password before authorizing file uploads + +```sh +▶ simplehttpserver -basic-auth root:root -upload +2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... +``` + +To upload files use the following curl request with basic auth header: +```sh +▶ curl -v --user 'root:root' --upload-file file.txt http://localhost:8000/file.txt +``` + +### Running TCP server with custom responses + +This will run the tool as TLS TCP server and enable custom responses based on YAML templates: + +```sh +▶ simplehttpserver -rule rules.yaml -tcp -tls -domain localhost +``` + +The rules are written as follows: +```yaml +rules: + - match: regex + response: response data +``` + +For example to handle two different paths simulating an HTTP server or SMTP commands: +```yaml +rules: + # HTTP Requests + - match: GET /path1 + response: | + HTTP/1.0 200 OK + Server: httpd/2.0 + x-frame-options: SAMEORIGIN + x-xss-protection: 1; mode=block + Date: Fri, 16 Apr 2021 14:30:32 GMT + Content-Type: text/html + Connection: close + + + + - match: GET /path2 + response: | + HTTP/1.0 404 OK + Server: httpd/2.0 + + Not found + # SMTP Commands + - match: "EHLO example.com" + response: | + 250-localhost Nice to meet you, [127.0.0.1] + 250-PIPELINING + 250-8BITMIME + 250-SMTPUTF8 + 250-AUTH LOGIN PLAIN + 250 STARTTLS + - match: "MAIL FROM: " + response: 250 Accepted + - match: "RCPT TO: " + response: 250 Accepted +``` + # Thanks simplehttpserver is made with 🖤 by the [projectdiscovery](https://projectdiscovery.io) team. Community contributions have made the project what it is. See the **[Thanks.md](https://github.com/projectdiscovery/simplehttpserver/blob/master/THANKS.md)** file for more details. From ef3b178ae32b8499bc25fb38933e31d8ed168394 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Fri, 16 Apr 2021 22:08:06 +0530 Subject: [PATCH 034/121] Update build.yaml --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 11d1658..008bca6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,8 +32,8 @@ jobs: - name: Test run: go test . - working-directory: cmd/simplehttpserver/ + working-directory: . - name: Build run: go build . - working-directory: cmd/simplehttpserver/ + working-directory: . From bce92ad125f31668a58d4bcdff509a061f04d1d0 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Fri, 16 Apr 2021 22:15:35 +0530 Subject: [PATCH 035/121] reverting working-directory --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 008bca6..4179b91 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,8 +32,8 @@ jobs: - name: Test run: go test . - working-directory: . + working-directory: cmd/simplehttpserver - name: Build run: go build . - working-directory: . + working-directory: cmd/simplehttpserver/ From 566a82a76a360d0dce6cac9c479041d86a302612 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:09:45 +0200 Subject: [PATCH 036/121] adding absolute path --- internal/runner/options.go | 9 +++++++++ internal/runner/runner.go | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/runner/options.go b/internal/runner/options.go index 3170cd3..9104c4a 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -3,6 +3,7 @@ package runner import ( "flag" "os" + "path/filepath" "strings" "github.com/projectdiscovery/gologger" @@ -91,3 +92,11 @@ func (options *Options) configureOutput() { gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent) } } + +func (o Options) FolderAbsPath() string { + abspath, err := filepath.Abs(o.Folder) + if err != nil { + return o.Folder + } + return abspath +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 6603d50..820dc51 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -72,11 +72,11 @@ func (r *Runner) Run() error { } if r.options.HTTPS { - gologger.Print().Msgf("Serving %s on https://%s/...", r.options.Folder, r.options.ListenAddress) + gologger.Print().Msgf("Serving %s on https://%s/", r.options.FolderAbsPath(), r.options.ListenAddress) return r.httpServer.ListenAndServeTLS() } - gologger.Print().Msgf("Serving %s on http://%s/...", r.options.Folder, r.options.ListenAddress) + gologger.Print().Msgf("Serving %s on http://%s/", r.options.FolderAbsPath(), r.options.ListenAddress) return r.httpServer.ListenAndServe() } From 1fe30e15f17c64dc45e59b840512b1c8c78b38d8 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:19:24 +0200 Subject: [PATCH 037/121] adding comments --- cmd/simplehttpserver/simplehttpserver.go | 6 +++--- internal/runner/options.go | 1 + internal/runner/runner.go | 3 +++ pkg/binder/binder.go | 2 ++ pkg/httpserver/httpserver.go | 6 ++++++ pkg/httpserver/loglayer.go | 3 +++ pkg/tcpserver/responseengine.go | 3 ++- pkg/tcpserver/rule.go | 5 ++++- pkg/tcpserver/tcpserver.go | 7 +++++++ 9 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 0dbbe6c..36ae61d 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -8,11 +8,11 @@ import ( func main() { // Parse the command line flags and read config files options := runner.ParseOptions() - runner, err := runner.New(options) + r, err := runner.New(options) if err != nil { gologger.Fatal().Msgf("Could not create runner: %s\n", err) } - runner.Run() - runner.Close() + r.Run() + defer r.Close() } diff --git a/internal/runner/options.go b/internal/runner/options.go index 9104c4a..6c8e1f9 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -93,6 +93,7 @@ func (options *Options) configureOutput() { } } +// FolderAbsPath of the fileserver folder func (o Options) FolderAbsPath() string { abspath, err := filepath.Abs(o.Folder) if err != nil { diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 820dc51..653cbed 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -14,6 +14,7 @@ type Runner struct { httpServer *httpserver.HTTPServer } +// New instance of runner func New(options *Options) (*Runner, error) { r := Runner{options: options} // Check if the process can listen on the specified ip:port @@ -65,6 +66,7 @@ func New(options *Options) (*Runner, error) { return &r, nil } +// Run logic func (r *Runner) Run() error { if r.options.EnableTCP { gologger.Print().Msgf("Serving TCP rule based server on tcp://%s", r.options.ListenAddress) @@ -80,6 +82,7 @@ func (r *Runner) Run() error { return r.httpServer.ListenAndServe() } +// Close the listening services func (r *Runner) Close() error { if r.serverTCP != nil { r.serverTCP.Close() diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index 2a248a1..a530cf1 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -7,6 +7,7 @@ import ( "github.com/phayes/freeport" ) +// CanListenOn the specified address func CanListenOn(address string) bool { listener, err := net.Listen("tcp4", address) if err != nil { @@ -16,6 +17,7 @@ func CanListenOn(address string) bool { return true } +// GetRandomListenAddress from the specified one func GetRandomListenAddress(currentAddress string) (string, error) { addrOrig, _, err := net.SplitHostPort(currentAddress) if err != nil { diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 958a6e7..1747017 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -6,6 +6,7 @@ import ( "github.com/projectdiscovery/sslcert" ) +// Options of the http server type Options struct { Folder string EnableUpload bool @@ -20,11 +21,13 @@ type Options struct { Verbose bool } +// HTTPServer instance type HTTPServer struct { options *Options layers http.Handler } +// New http server instance with options func New(options *Options) (*HTTPServer, error) { var h HTTPServer EnableUpload = options.EnableUpload @@ -37,10 +40,12 @@ func New(options *Options) (*HTTPServer, error) { return &HTTPServer{options: options, layers: layers}, nil } +// ListenAndServe requests over http func (t *HTTPServer) ListenAndServe() error { return http.ListenAndServe(t.options.ListenAddress, t.layers) } +// ListenAndServeTLS requests over https func (t *HTTPServer) ListenAndServeTLS() error { if t.options.Certificate == "" || t.options.CertificateKey == "" { tlsOptions := sslcert.DefaultOptions @@ -59,6 +64,7 @@ func (t *HTTPServer) ListenAndServeTLS() error { return http.ListenAndServeTLS(t.options.ListenAddress, t.options.Certificate, t.options.CertificateKey, t.layers) } +// Close the service func (t *HTTPServer) Close() error { return nil } diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 2d84d9a..1e64b8f 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -54,15 +54,18 @@ func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { return &loggingResponseWriter{w, http.StatusOK, []byte{}} } +// Write the data func (lrw *loggingResponseWriter) Write(data []byte) (int, error) { lrw.Data = append(lrw.Data, data...) return lrw.ResponseWriter.Write(data) } +// Header of the response func (lrw *loggingResponseWriter) Header() http.Header { return lrw.ResponseWriter.Header() } +// WriteHeader status code func (lrw *loggingResponseWriter) WriteHeader(code int) { lrw.statusCode = code lrw.ResponseWriter.WriteHeader(code) diff --git a/pkg/tcpserver/responseengine.go b/pkg/tcpserver/responseengine.go index c3286f8..ec15da0 100644 --- a/pkg/tcpserver/responseengine.go +++ b/pkg/tcpserver/responseengine.go @@ -4,6 +4,7 @@ import ( "errors" ) +// BuildResponse according to rules func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { // Process all the rules for _, rule := range t.options.rules { @@ -11,5 +12,5 @@ func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { return []byte(rule.Response), nil } } - return nil, errors.New("No matched rule") + return nil, errors.New("no matched rule") } diff --git a/pkg/tcpserver/rule.go b/pkg/tcpserver/rule.go index ba31839..903331b 100644 --- a/pkg/tcpserver/rule.go +++ b/pkg/tcpserver/rule.go @@ -2,17 +2,20 @@ package tcpserver import "regexp" +// RulesConfiguration from yaml type RulesConfiguration struct { Rules []Rule `yaml:"rules"` } +// Rule to apply to various requests type Rule struct { Match string `yaml:"match,omitempty"` matchRegex *regexp.Regexp Response string `yaml:"response,omitempty"` } -func NewRule(match string, response string) (*Rule, error) { +// NewRule from model +func NewRule(match, response string) (*Rule, error) { regxp, err := regexp.Compile(match) if err != nil { return nil, err diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index f78f876..7bff39e 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -11,6 +11,7 @@ import ( "gopkg.in/yaml.v2" ) +// Options of the tcp server type Options struct { Listen string TLS bool @@ -21,20 +22,24 @@ type Options struct { Verbose bool } +// TCPServer instance type TCPServer struct { options Options listener net.Listener } +// New tcp server instance with specified options func New(options Options) (*TCPServer, error) { return &TCPServer{options: options}, nil } +// AddRule to the server func (t *TCPServer) AddRule(rule Rule) error { t.options.rules = append(t.options.rules, rule) return nil } +// ListenAndServe requests func (t *TCPServer) ListenAndServe() error { listener, err := net.Listen("tcp4", t.options.Listen) if err != nil { @@ -68,6 +73,7 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { } } +// ListenAndServe requests over tls func (t *TCPServer) ListenAndServeTLS() error { var tlsConfig *tls.Config if t.options.Certificate != "" && t.options.Key != "" { @@ -108,6 +114,7 @@ func (t *TCPServer) Close() error { return t.listener.Close() } +// LoadTemplate from yaml func (t *TCPServer) LoadTemplate(templatePath string) error { var config RulesConfiguration yamlFile, err := ioutil.ReadFile(templatePath) From b0911c1316fb5c187fe71b1f5372af0372b65852 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:30:13 +0200 Subject: [PATCH 038/121] adding missing error checks --- cmd/simplehttpserver/simplehttpserver.go | 4 +++- internal/runner/options.go | 3 ++- internal/runner/runner.go | 8 ++++++-- pkg/binder/binder.go | 5 ++++- pkg/tcpserver/tcpserver.go | 11 ++++++++--- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 36ae61d..9d37de8 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -13,6 +13,8 @@ func main() { gologger.Fatal().Msgf("Could not create runner: %s\n", err) } - r.Run() + if err := r.Run(); err != nil { + gologger.Info().Msgf("%s\n", err) + } defer r.Close() } diff --git a/internal/runner/options.go b/internal/runner/options.go index 6c8e1f9..0b5e587 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -10,6 +10,7 @@ import ( "github.com/projectdiscovery/gologger/levels" ) +// Options of the tool type Options struct { ListenAddress string Folder string @@ -94,7 +95,7 @@ func (options *Options) configureOutput() { } // FolderAbsPath of the fileserver folder -func (o Options) FolderAbsPath() string { +func (o *Options) FolderAbsPath() string { abspath, err := filepath.Abs(o.Folder) if err != nil { return o.Folder diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 653cbed..4bda588 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -85,10 +85,14 @@ func (r *Runner) Run() error { // Close the listening services func (r *Runner) Close() error { if r.serverTCP != nil { - r.serverTCP.Close() + if err := r.serverTCP.Close(); err != nil { + return err + } } if r.httpServer != nil { - r.httpServer.Close() + if err := r.httpServer.Close(); err != nil { + return err + } } return nil } diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index a530cf1..88a051b 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -5,6 +5,7 @@ import ( "net" "github.com/phayes/freeport" + "github.com/projectdiscovery/gologger" ) // CanListenOn the specified address @@ -13,7 +14,9 @@ func CanListenOn(address string) bool { if err != nil { return false } - defer listener.Close() + if err := listener.Close(); err != nil { + gologger.Info().Msgf("%s\n", err) + } return true } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 7bff39e..dfcb18b 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -54,7 +54,9 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { buf := make([]byte, 4096) for { - conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))) + if err := conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))); err != nil { + gologger.Info().Msgf("%s\n", err) + } _, err := conn.Read(buf) if err != nil { return err @@ -67,7 +69,9 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { return err } - conn.Write(resp) + if _, err := conn.Write(resp); err != nil { + gologger.Info().Msgf("%s\n", err) + } gologger.Print().Msgf("%s\n", resp) } @@ -106,10 +110,11 @@ func (t *TCPServer) run() error { if err != nil { return err } - go t.handleConnection(c) + go t.handleConnection(c) //nolint } } +// Close the service func (t *TCPServer) Close() error { return t.listener.Close() } From 309e6bc1170114b3bb80ddb5e403cce4bd77dc0b Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Fri, 16 Apr 2021 19:33:04 +0200 Subject: [PATCH 039/121] adding missing go docs --- pkg/binder/doc.go | 2 ++ pkg/httpserver/doc.go | 2 ++ pkg/tcpserver/doc.go | 2 ++ 3 files changed, 6 insertions(+) create mode 100644 pkg/binder/doc.go create mode 100644 pkg/httpserver/doc.go create mode 100644 pkg/tcpserver/doc.go diff --git a/pkg/binder/doc.go b/pkg/binder/doc.go new file mode 100644 index 0000000..709dc10 --- /dev/null +++ b/pkg/binder/doc.go @@ -0,0 +1,2 @@ +// Package binder contains binding helpers +package binder diff --git a/pkg/httpserver/doc.go b/pkg/httpserver/doc.go new file mode 100644 index 0000000..5344c9f --- /dev/null +++ b/pkg/httpserver/doc.go @@ -0,0 +1,2 @@ +// Package httpserver contains the http server logic +package httpserver diff --git a/pkg/tcpserver/doc.go b/pkg/tcpserver/doc.go new file mode 100644 index 0000000..4ab6d69 --- /dev/null +++ b/pkg/tcpserver/doc.go @@ -0,0 +1,2 @@ +// Package tcpserver contains the tcp server logic +package tcpserver From 89bbfaac877c637c32f56dc98d2d3a6ece77c9b9 Mon Sep 17 00:00:00 2001 From: mzack Date: Fri, 16 Apr 2021 20:10:40 +0200 Subject: [PATCH 040/121] fixing misc lint errors --- .golangci.yml | 6 +----- cmd/simplehttpserver/simplehttpserver.go | 2 +- internal/runner/options.go | 6 +++--- internal/runner/runner.go | 2 +- pkg/binder/binder.go | 1 - pkg/tcpserver/tcpserver.go | 12 +++++++----- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d5e9089..31b66f3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -41,8 +41,6 @@ linters-settings: - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf # lll: # line-length: 140 - maligned: - suggest-new: true misspell: locale: US nolintlint: @@ -73,14 +71,12 @@ linters: - gosimple - govet - ineffassign - - interfacer - - maligned - misspell - nakedret - noctx - nolintlint - rowserrcheck - - scopelint + - exportloopref - staticcheck - structcheck - stylecheck diff --git a/cmd/simplehttpserver/simplehttpserver.go b/cmd/simplehttpserver/simplehttpserver.go index 9d37de8..ed82b40 100644 --- a/cmd/simplehttpserver/simplehttpserver.go +++ b/cmd/simplehttpserver/simplehttpserver.go @@ -16,5 +16,5 @@ func main() { if err := r.Run(); err != nil { gologger.Info().Msgf("%s\n", err) } - defer r.Close() + defer r.Close() //nolint } diff --git a/internal/runner/options.go b/internal/runner/options.go index 0b5e587..bf69db3 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -95,10 +95,10 @@ func (options *Options) configureOutput() { } // FolderAbsPath of the fileserver folder -func (o *Options) FolderAbsPath() string { - abspath, err := filepath.Abs(o.Folder) +func (options *Options) FolderAbsPath() string { + abspath, err := filepath.Abs(options.Folder) if err != nil { - return o.Folder + return options.Folder } return abspath } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 4bda588..7d69e25 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -28,7 +28,7 @@ func New(options *Options) (*Runner, error) { } if r.options.EnableTCP { - serverTCP, err := tcpserver.New(tcpserver.Options{ + serverTCP, err := tcpserver.New(&tcpserver.Options{ Listen: r.options.ListenAddress, TLS: r.options.TCPWithTLS, Domain: "local.host", diff --git a/pkg/binder/binder.go b/pkg/binder/binder.go index 88a051b..549e9d9 100644 --- a/pkg/binder/binder.go +++ b/pkg/binder/binder.go @@ -33,5 +33,4 @@ func GetRandomListenAddress(currentAddress string) (string, error) { } return net.JoinHostPort(addrOrig, fmt.Sprintf("%d", newPort)), nil - } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index dfcb18b..876fbb4 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -11,6 +11,8 @@ import ( "gopkg.in/yaml.v2" ) +const readTimeout = 5 + // Options of the tcp server type Options struct { Listen string @@ -24,12 +26,12 @@ type Options struct { // TCPServer instance type TCPServer struct { - options Options + options *Options listener net.Listener } // New tcp server instance with specified options -func New(options Options) (*TCPServer, error) { +func New(options *Options) (*TCPServer, error) { return &TCPServer{options: options}, nil } @@ -50,11 +52,11 @@ func (t *TCPServer) ListenAndServe() error { } func (t *TCPServer) handleConnection(conn net.Conn) error { - defer conn.Close() + defer conn.Close() //nolint buf := make([]byte, 4096) for { - if err := conn.SetReadDeadline(time.Now().Add(time.Duration(5 * time.Second))); err != nil { + if err := conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second)); err != nil { gologger.Info().Msgf("%s\n", err) } _, err := conn.Read(buf) @@ -77,7 +79,7 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { } } -// ListenAndServe requests over tls +// ListenAndServeTLS requests over tls func (t *TCPServer) ListenAndServeTLS() error { var tlsConfig *tls.Config if t.options.Certificate != "" && t.options.Key != "" { From 8a339ee35b4f329b9b4c2f2f830e4594769751ba Mon Sep 17 00:00:00 2001 From: mzack Date: Fri, 16 Apr 2021 20:12:26 +0200 Subject: [PATCH 041/121] bumping version --- internal/runner/banner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index c8972db..2d31eb8 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -12,7 +12,7 @@ const banner = ` ` // Version is the current version -const Version = `0.0.1` +const Version = `0.0.2` // showBanner is used to show the banner to the user func showBanner() { From 1b9328d08132f01a31dd1e8bd79c16017fe5854b Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Sat, 17 Apr 2021 00:47:40 +0530 Subject: [PATCH 042/121] Update README.md --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 00daf9c..d2b4e5b 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@ -

- simplehttpserver -
-

+

SimpleHTTPserver

+

Go alternative of python SimpleHTTPServer

+ + +

+ + + + + + +

-[![License](https://img.shields.io/badge/license-MIT-_red.svg)](https://opensource.org/licenses/MIT) -[![Go Report Card](https://goreportcard.com/badge/github.com/projectdiscovery/simplehttpserver)](https://goreportcard.com/report/github.com/projectdiscovery/simplehttpserver) -[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/projectdiscovery/simplehttpserver/issues) -[![GitHub Release](https://img.shields.io/github/release/projectdiscovery/simplehttpserver)](https://github.com/projectdiscovery/simplehttpserver/releases) -[![Follow on Twitter](https://img.shields.io/twitter/follow/pdiscoveryio.svg?logo=twitter)](https://twitter.com/pdiscoveryio) -[![Docker Images](https://img.shields.io/docker/pulls/projectdiscovery/simplehttpserver.svg)](https://hub.docker.com/r/projectdiscovery/simplehttpserver) -[![Chat on Discord](https://img.shields.io/discord/695645237418131507.svg?logo=discord)](https://discord.gg/KECAGdH) -simplehttpserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. +SimpleHTTPserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. # Resources From d490ff6b074db5233af1e6dd126ee9a0cc4915a7 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Sat, 17 Apr 2021 00:57:03 +0530 Subject: [PATCH 043/121] Update README.md --- README.md | 50 +++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index d2b4e5b..426fd74 100644 --- a/README.md +++ b/README.md @@ -11,24 +11,21 @@

+

+ Features • + Usage • + Installation • + Run SimpleHTTPserver • + Join Discord +

-SimpleHTTPserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. +--- -# Resources +SimpleHTTPserver is a go enhanced version of the well known python simplehttpserver with in addition a fully customizable TCP server, both supporting TLS. -- [Features](#features) -- [Usage](#usage) -- [Installation Instructions](#installation-instructions) -- [Running simplehttpserver](#running-simplehttpserver-in-the-current-folder) -- [Thanks](#thanks) # Features -

- simplehttpserver -
-

- - HTTPS support - File server in arbitrary directory - Full request/response dump @@ -36,33 +33,12 @@ SimpleHTTPserver is a go enhanced version of the well known python simplehttpser - Configurable HTTP/TCP server with customizable response via YAML template -# Installation Instructions - - -### From Binary - -The installation is easy. You can download the pre-built binaries for your platform from the [Releases](https://github.com/projectdiscovery/simplehttpserver/releases/) page. Extract them using tar, move it to your `$PATH`and you're ready to go. - -```sh -Download latest binary from https://github.com/projectdiscovery/simplehttpserver/releases - -▶ tar -xvf simplehttpserver-linux-amd64.tar -▶ mv simplehttpserver-linux-amd64 /usr/local/bin/simplehttpserver -▶ simplehttpserver -h -``` - -### From Source - -simplehttpserver requires **go1.14+** to install successfully. Run the following command to get the repo - - -```sh -▶ GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver -``` +# Installing SimpleHTTPserver -### From Github +SimpleHTTPserver requires **go1.14+** to install successfully. Run the following command to get the repo - ```sh -▶ git clone https://github.com/projectdiscovery/simplehttpserver.git; cd simplehttpserver; go build; mv simplehttpserver /usr/local/bin/; simplehttpserver -h +▶ GO111MODULE=on go get -v github.com/projectdiscovery/cmd/simplehttpserver ``` # Usage @@ -189,4 +165,4 @@ rules: # Thanks -simplehttpserver is made with 🖤 by the [projectdiscovery](https://projectdiscovery.io) team. Community contributions have made the project what it is. See the **[Thanks.md](https://github.com/projectdiscovery/simplehttpserver/blob/master/THANKS.md)** file for more details. +SimpleHTTPserver is made with 🖤 by the [projectdiscovery](https://projectdiscovery.io) team. From 63f26b4949f406b0f8a5c6fa293176ede8a02429 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:16:28 +0530 Subject: [PATCH 044/121] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b883f1f..4f9c0f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.exe +cmd/simplehttpserver/simplehttpserver From 80695a67430e38372ce7188a24175bbaa2267722 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:27:47 +0530 Subject: [PATCH 045/121] banner update --- internal/runner/banner.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index 2d31eb8..f727190 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -3,12 +3,12 @@ package runner import "github.com/projectdiscovery/gologger" const banner = ` - _ _ _ _ _ - ___(_)_ __ ___ _ __ | | ___| |__ | |_| |_ _ __ ___ ___ _ ____ _____ _ __ -/ __| | '_ ' _ \| '_ \| |/ _ \ '_ \| __| __| '_ \/ __|/ _ \ '__\ \ / / _ \ '__| -\__ \ | | | | | | |_) | | __/ | | | |_| |_| |_) \__ \ __/ | \ V / __/ | -|___/_|_| |_| |_| .__/|_|\___|_| |_|\__|\__| .__/|___/\___|_| \_/ \___|_| - |_| |_| + _____ _ __ __ __________________ + / ___/(_)___ ___ ____ / /__ / / / /_ __/_ __/ __ \________ ______ _____ _____ + \__ \/ / __ -__ \/ __ \/ / _ \/ /_/ / / / / / / /_/ / ___/ _ \/ ___/ | / / _ \/ ___/ + ___/ / / / / / / / /_/ / / __/ __ / / / / / / ____(__ ) __/ / | |/ / __/ / +/____/_/_/ /_/ /_/ .___/_/\___/_/ /_/ /_/ /_/ /_/ /____/\___/_/ |___/\___/_/ + /_/ - v0.0.2 ` // Version is the current version From b51596ccf30d6ee4ff59978a26b59e573db3c8da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Apr 2021 20:02:07 +0000 Subject: [PATCH 046/121] chore(deps): bump golangci/golangci-lint-action from v2.4.0 to v2.5.2 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from v2.4.0 to v2.5.2. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v2.4.0...5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018) Signed-off-by: dependabot[bot] --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4179b91..8d43441 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -12,7 +12,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.4.0 + uses: golangci/golangci-lint-action@v2.5.2 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. version: v1.31 From 130323d2de80d3473819b4934fd34deac15ee018 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:34:09 +0530 Subject: [PATCH 047/121] install fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 426fd74..d8b7396 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ SimpleHTTPserver is a go enhanced version of the well known python simplehttpser SimpleHTTPserver requires **go1.14+** to install successfully. Run the following command to get the repo - ```sh -▶ GO111MODULE=on go get -v github.com/projectdiscovery/cmd/simplehttpserver +▶ GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver ``` # Usage From 97d5e907cdec305fafffb9efb682726078c453dd Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:37:27 +0530 Subject: [PATCH 048/121] Update Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0919a3c..136d06f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.16-alpine AS builder RUN apk add --no-cache git -RUN GO111MODULE=auto go get -u -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver +RUN GO111MODULE=auto go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest RUN apk add --no-cache bind-tools ca-certificates From 1c31a483a0125e78955ea55ceeb3edc19bcdbb2f Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:47:06 +0530 Subject: [PATCH 049/121] docker fix --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 136d06f..ebec407 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM golang:1.16-alpine AS builder RUN apk add --no-cache git -RUN GO111MODULE=auto go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver +RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest RUN apk add --no-cache bind-tools ca-certificates From 38b760a3d93ceb31d6150638ac1b570181474b91 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sat, 17 Apr 2021 22:58:24 +0530 Subject: [PATCH 050/121] flag update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8b7396..fba4ea3 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,10 @@ This will display help for the tool. Here are all the switches it supports. | ----------- | -------------------------------------------------------------------- | ------------------------------------------------- | | listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | | path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | -| verbose | Verbose (dump request/response, default false) | simplehttpserver -v | +| verbose | Verbose (dump request/response, default false) | simplehttpserver -verbose | | tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | | tls | Enable TLS for TCP server | simplehttpserver -tls | -| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | | +| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | | upload | Enable file upload in case of http server | simplehttpserver -upload | | https | Enable HTTPS in case of http server | simplehttpserver -https | | cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | From 0712f0b78ca7a9f301ba14e5813755977b1f266f Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Sat, 17 Apr 2021 20:45:12 +0200 Subject: [PATCH 051/121] fixing crash in #27 --- pkg/httpserver/httpserver.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 1747017..d516caf 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -32,12 +32,13 @@ func New(options *Options) (*HTTPServer, error) { var h HTTPServer EnableUpload = options.EnableUpload EnableVerbose = options.Verbose - layers := h.loglayer(http.FileServer(http.Dir(options.Folder))) + h.layers = h.loglayer(http.FileServer(http.Dir(options.Folder))) if options.BasicAuthUsername != "" || options.BasicAuthPassword != "" { - layers = h.loglayer(h.basicauthlayer(http.FileServer(http.Dir(options.Folder)))) + h.layers = h.loglayer(h.basicauthlayer(http.FileServer(http.Dir(options.Folder)))) } + h.options = options - return &HTTPServer{options: options, layers: layers}, nil + return &h, nil } // ListenAndServe requests over http From 435e88ce9662a905bca7f3f28cf8ca885bcfcc8a Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sun, 18 Apr 2021 13:04:11 +0530 Subject: [PATCH 052/121] version update --- internal/runner/banner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index f727190..a6b729d 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -8,11 +8,11 @@ const banner = ` \__ \/ / __ -__ \/ __ \/ / _ \/ /_/ / / / / / / /_/ / ___/ _ \/ ___/ | / / _ \/ ___/ ___/ / / / / / / / /_/ / / __/ __ / / / / / / ____(__ ) __/ / | |/ / __/ / /____/_/_/ /_/ /_/ .___/_/\___/_/ /_/ /_/ /_/ /_/ /____/\___/_/ |___/\___/_/ - /_/ - v0.0.2 + /_/ - v0.0.3 ` // Version is the current version -const Version = `0.0.2` +const Version = `0.0.3` // showBanner is used to show the banner to the user func showBanner() { From 4db054d50bc81dfe3c18d1b2192f8cd160144677 Mon Sep 17 00:00:00 2001 From: sandeep <8293321+ehsandeep@users.noreply.github.com> Date: Sun, 18 Apr 2021 13:06:20 +0530 Subject: [PATCH 053/121] Update Dockerfile --- Dockerfile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index ebec407..806904b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,7 @@ -FROM golang:1.16-alpine AS builder -RUN apk add --no-cache git +FROM golang:1.16-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest RUN apk add --no-cache bind-tools ca-certificates -COPY --from=builder /go/bin/simplehttpserver /usr/local/bin/ - -ENTRYPOINT ["simplehttpserver"] +COPY --from=build-env /go/bin/simplehttpserver /usr/local/bin/simplehttpserver +ENTRYPOINT ["simplehttpserver"] \ No newline at end of file From 0917068048eca8316b5c066e00613d002566beaa Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 19 Apr 2021 00:40:51 +0200 Subject: [PATCH 054/121] begin of work on pseudo-sandbox mode --- internal/runner/options.go | 4 +++ internal/runner/runner.go | 2 ++ pkg/httpserver/httpserver.go | 22 +++++++++++++-- pkg/httpserver/loglayer.go | 44 ++++++++++++++++++++++++++++- pkg/httpserver/sandboxfs.go | 55 ++++++++++++++++++++++++++++++++++++ pkg/httpserver/util.go | 5 ++++ 6 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 pkg/httpserver/sandboxfs.go create mode 100644 pkg/httpserver/util.go diff --git a/internal/runner/options.go b/internal/runner/options.go index bf69db3..78f8579 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -29,6 +29,8 @@ type Options struct { TCPWithTLS bool Version bool Silent bool + Sandbox bool + MaxFileSize int } // ParseOptions parses the command line options for application @@ -49,6 +51,8 @@ func ParseOptions() *Options { flag.StringVar(&options.Realm, "realm", "Please enter username and password", "Realm") flag.BoolVar(&options.Version, "version", false, "Show version of the software") flag.BoolVar(&options.Silent, "silent", false, "Show only results in the output") + flag.BoolVar(&options.Sandbox, "sandbox", false, "Enable sandbox mode") + flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") flag.Parse() diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 7d69e25..5806044 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -57,6 +57,8 @@ func New(options *Options) (*Runner, error) { BasicAuthPassword: r.options.password, BasicAuthReal: r.options.Realm, Verbose: r.options.Verbose, + Sandbox: r.options.Sandbox, + MaxFileSize: r.options.MaxFileSize, }) if err != nil { return nil, err diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index d516caf..72da466 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -1,7 +1,10 @@ package httpserver import ( + "errors" "net/http" + "os" + "path/filepath" "github.com/projectdiscovery/sslcert" ) @@ -19,6 +22,8 @@ type Options struct { BasicAuthPassword string BasicAuthReal string Verbose bool + Sandbox bool + MaxFileSize int // 50Mb } // HTTPServer instance @@ -32,9 +37,22 @@ func New(options *Options) (*HTTPServer, error) { var h HTTPServer EnableUpload = options.EnableUpload EnableVerbose = options.Verbose - h.layers = h.loglayer(http.FileServer(http.Dir(options.Folder))) + folder, err := filepath.Abs(options.Folder) + if err != nil { + return nil, err + } + if _, err := os.Stat(folder); os.IsNotExist(err) { + return nil, errors.New("path does not exist") + } + options.Folder = folder + var dir http.FileSystem + dir = http.Dir(options.Folder) + if options.Sandbox { + dir = SandboxFileSystem{fs: http.Dir(options.Folder), RootFolder: options.Folder} + } + h.layers = h.loglayer(http.FileServer(dir)) if options.BasicAuthUsername != "" || options.BasicAuthPassword != "" { - h.layers = h.loglayer(h.basicauthlayer(http.FileServer(http.Dir(options.Folder)))) + h.layers = h.loglayer(h.basicauthlayer(http.FileServer(dir))) } h.options = options diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 1e64b8f..75f4ba6 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httputil" "path" + "path/filepath" "github.com/projectdiscovery/gologger" ) @@ -24,13 +25,54 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { // Handles file write if enabled if EnableUpload && r.Method == http.MethodPut { - data, err := ioutil.ReadAll(r.Body) + // sandbox - calcolate absolute path + if t.options.Sandbox { + absPath, err := filepath.Abs(filepath.Join(t.options.Folder, r.URL.Path)) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } + // check if the path is within the configured folder + pattern := t.options.Folder + string(filepath.Separator) + "*" + matched, err := filepath.Match(pattern, absPath) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } else if !matched { + gologger.Print().Msg("pointing to unauthorized directory") + w.WriteHeader(http.StatusBadRequest) + return + } + } + + var ( + data []byte + err error + ) + if t.options.Sandbox { + maxFileSize := toMb(t.options.MaxFileSize) + // check header content length + if r.ContentLength > maxFileSize { + gologger.Print().Msg("request too large") + return + } + // body max length + r.Body = http.MaxBytesReader(w, r.Body, maxFileSize) + } + + data, err = ioutil.ReadAll(r.Body) if err != nil { gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusInternalServerError) + return } err = handleUpload(path.Base(r.URL.Path), data) if err != nil { gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusInternalServerError) + return } } diff --git a/pkg/httpserver/sandboxfs.go b/pkg/httpserver/sandboxfs.go new file mode 100644 index 0000000..41fcadf --- /dev/null +++ b/pkg/httpserver/sandboxfs.go @@ -0,0 +1,55 @@ +package httpserver + +import ( + "errors" + "net/http" + "path/filepath" +) + +type SandboxFileSystem struct { + fs http.FileSystem + RootFolder string +} + +func (sbfs SandboxFileSystem) Open(path string) (http.File, error) { + abspath, err := filepath.Abs(filepath.Join(sbfs.RootFolder, path)) + if err != nil { + return nil, err + } + + filename := filepath.Base(abspath) + // rejects names starting with a dot like .file + dotmatch, err := filepath.Match(".*", filename) + if err != nil { + return nil, err + } else if dotmatch { + return nil, errors.New("invalid file") + } + + // reject symlinks + symlinkCheck, err := filepath.EvalSymlinks(abspath) + if err != nil { + return nil, err + } + if symlinkCheck != abspath { + return nil, errors.New("symlinks not allowed") + } + + // check if the path is within the configured folder + if sbfs.RootFolder != abspath { + pattern := sbfs.RootFolder + string(filepath.Separator) + "*" + matched, err := filepath.Match(pattern, abspath) + if err != nil { + return nil, err + } else if !matched { + return nil, errors.New("invalid file") + } + } + + f, err := sbfs.fs.Open(path) + if err != nil { + return nil, err + } + + return f, nil +} diff --git a/pkg/httpserver/util.go b/pkg/httpserver/util.go new file mode 100644 index 0000000..4c69d6f --- /dev/null +++ b/pkg/httpserver/util.go @@ -0,0 +1,5 @@ +package httpserver + +func toMb(n int) int64 { + return int64(n) * 1024 * 1024 +} From a8c31d49cbf355a165b85725fbf631b1bd46f978 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 19 Apr 2021 00:53:04 +0200 Subject: [PATCH 055/121] adding missing comments --- pkg/httpserver/sandboxfs.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/httpserver/sandboxfs.go b/pkg/httpserver/sandboxfs.go index 41fcadf..cde5c04 100644 --- a/pkg/httpserver/sandboxfs.go +++ b/pkg/httpserver/sandboxfs.go @@ -6,11 +6,13 @@ import ( "path/filepath" ) +// SandboxFileSystem implements superbasic security checks type SandboxFileSystem struct { fs http.FileSystem RootFolder string } +// Open performs basic security checks before providing folder/file content func (sbfs SandboxFileSystem) Open(path string) (http.File, error) { abspath, err := filepath.Abs(filepath.Join(sbfs.RootFolder, path)) if err != nil { From 0e6bfeeeb800eeb5f770cd09adbfacd9ce463180 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Wed, 26 May 2021 00:34:47 +0200 Subject: [PATCH 056/121] Deprecating golint --- .github/workflows/build.yaml | 4 +- .golangci.yml | 118 ----------------------------------- 2 files changed, 2 insertions(+), 120 deletions(-) delete mode 100644 .golangci.yml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8d43441..70b19c6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -12,10 +12,10 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2.5.2 + uses: golangci/golangci-lint-action@v2 with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.31 + version: latest args: --timeout 5m build: diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 31b66f3..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,118 +0,0 @@ -linters-settings: - dupl: - threshold: 100 - exhaustive: - default-signifies-exhaustive: false - # funlen: - # lines: 100 - # statements: 50 - goconst: - min-len: 2 - min-occurrences: 2 - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - # gocyclo: - # min-complexity: 15 - goimports: - local-prefixes: github.com/golangci/golangci-lint - golint: - min-confidence: 0 - gomnd: - settings: - mnd: - # don't include the "operation" and "assign" - checks: argument,case,condition,return - govet: - check-shadowing: true - settings: - printf: - funcs: - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - # lll: - # line-length: 140 - misspell: - locale: US - nolintlint: - allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) - allow-unused: false # report any unused nolint directives - require-explanation: false # don't require an explanation for nolint directives - require-specific: false # don't require nolint directives to be specific about which linter is being skipped - -linters: - # please, do not use `enable-all`: it's deprecated and will be removed soon. - # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint - disable-all: true - enable: - - bodyclose - - deadcode - - dogsled - - dupl - - errcheck - - exhaustive - - gochecknoinits - - goconst - - gocritic - - gofmt - - goimports - - golint - - gomnd - - goprintffuncname - - gosimple - - govet - - ineffassign - - misspell - - nakedret - - noctx - - nolintlint - - rowserrcheck - - exportloopref - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unparam - - unused - - varcheck - - whitespace - - # don't enable: - # - depguard - # - asciicheck - # - funlen - # - gochecknoglobals - # - gocognit - # - gocyclo - # - godot - # - godox - # - goerr113 - # - gosec - # - lll - # - nestif - # - prealloc - # - testpackage - # - wsl - -issues: - exclude-use-default: false - exclude: - # should have a package comment, unless it's in another file for this package (golint) - - 'in another file for this package' - -# golangci.com configuration -# https://github.com/golangci/golangci/wiki/Configuration -service: - golangci-lint-version: 1.31.x # use the fixed version to not introduce new linters unexpectedly - prepare: - - echo "here I can run custom commands, but no preparation needed for this repo" From 74c20cef99513c7ef98b79b1155e64762bc70a09 Mon Sep 17 00:00:00 2001 From: mzack Date: Wed, 16 Jun 2021 18:23:52 +0200 Subject: [PATCH 057/121] adding additional checks --- internal/runner/options.go | 6 +++++- pkg/httpserver/loglayer.go | 2 +- pkg/httpserver/uploadlayer.go | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/internal/runner/options.go b/internal/runner/options.go index 78f8579..a5869d6 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -40,7 +40,11 @@ func ParseOptions() *Options { flag.BoolVar(&options.EnableTCP, "tcp", false, "TCP Server") flag.BoolVar(&options.TCPWithTLS, "tls", false, "Enable TCP TLS") flag.StringVar(&options.RulesFile, "rules", "", "Rules yaml file") - flag.StringVar(&options.Folder, "path", ".", "Folder") + currentPath := "." + if p, err := os.Getwd(); err == nil { + currentPath = p + } + flag.StringVar(&options.Folder, "path", currentPath, "Folder") flag.BoolVar(&options.EnableUpload, "upload", false, "Enable upload via PUT") flag.BoolVar(&options.HTTPS, "https", false, "HTTPS") flag.StringVar(&options.TLSCertificate, "cert", "", "HTTPS Certificate") diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 75f4ba6..0e1a87a 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -68,7 +68,7 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { w.WriteHeader(http.StatusInternalServerError) return } - err = handleUpload(path.Base(r.URL.Path), data) + err = handleUpload(t.options.Folder, path.Base(r.URL.Path), data) if err != nil { gologger.Print().Msgf("%s\n", err) w.WriteHeader(http.StatusInternalServerError) diff --git a/pkg/httpserver/uploadlayer.go b/pkg/httpserver/uploadlayer.go index 2663fba..928ac60 100644 --- a/pkg/httpserver/uploadlayer.go +++ b/pkg/httpserver/uploadlayer.go @@ -1,7 +1,23 @@ package httpserver -import "io/ioutil" +import ( + "errors" + "io/ioutil" + "path/filepath" + "strings" +) + +func handleUpload(base, file string, data []byte) error { + // rejects all paths containing a non exhaustive list of invalid characters - This is only a best effort as the tool is meant for development + if strings.ContainsAny(file, "\\`\"':") { + return errors.New("invalid character") + } + + // allow upload only in subfolders + rel, err := filepath.Rel(base, file) + if rel == "" || err != nil { + return err + } -func handleUpload(file string, data []byte) error { return ioutil.WriteFile(file, data, 0655) } From 62f74db5d66382867c1c44f4aea74cf36b08cd38 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Fri, 16 Jul 2021 16:29:36 +0530 Subject: [PATCH 058/121] Added SECURITY.MD --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..fc8033f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +DO NOT CREATE AN ISSUE to report a security problem. Instead, please send an email to security@projectdiscovery.io and we will acknowledge it within 3 working days. From 5efe87f3af8697acb31dbbba50628a040cdb0191 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jul 2021 12:03:30 +0000 Subject: [PATCH 059/121] chore(deps): bump golang from 1.16-alpine to 1.16.6-alpine Bumps golang from 1.16-alpine to 1.16.6-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 806904b..1f80a97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16-alpine as build-env +FROM golang:1.16.6-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 42ca7aa08772af77dc3db44f27c3cdac54425793 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:04:09 +0000 Subject: [PATCH 060/121] chore(deps): bump golang from 1.16-alpine to 1.16.6-alpine Bumps golang from 1.16-alpine to 1.16.6-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 806904b..1f80a97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16-alpine as build-env +FROM golang:1.16.6-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 37af337de65d69cbb15eab5bcb1dfe96bd0392df Mon Sep 17 00:00:00 2001 From: sandeep Date: Wed, 28 Jul 2021 21:26:33 +0530 Subject: [PATCH 061/121] Updated workflow --- .github/dependabot.yml | 5 ++- .github/workflows/build-test.yml | 27 ++++++++++++ .github/workflows/build.yaml | 39 ------------------ .github/workflows/codeql-analysis.yml | 38 +++++++++++++++++ .github/workflows/dockerhub-push.yml | 41 +++++++++++++------ .github/workflows/lint-test.yml | 19 +++++++++ .../{release.yml => release-binary.yml} | 8 ++-- 7 files changed, 122 insertions(+), 55 deletions(-) create mode 100644 .github/workflows/build-test.yml delete mode 100644 .github/workflows/build.yaml create mode 100644 .github/workflows/codeql-analysis.yml create mode 100644 .github/workflows/lint-test.yml rename .github/workflows/{release.yml => release-binary.yml} (80%) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4d5617f..69d9543 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,6 +11,7 @@ updates: directory: "/" schedule: interval: "weekly" + target-branch: "dev" commit-message: prefix: "chore" include: "scope" @@ -20,6 +21,7 @@ updates: directory: "/" schedule: interval: "weekly" + target-branch: "dev" commit-message: prefix: "chore" include: "scope" @@ -29,6 +31,7 @@ updates: directory: "/" schedule: interval: "weekly" + target-branch: "dev" commit-message: prefix: "chore" - include: "scope" + include: "scope" \ No newline at end of file diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 0000000..6bfe472 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,27 @@ +name: 🔨 Build Test +on: + push: + pull_request: + workflow_dispatch: + + +jobs: + build: + name: Test Builds + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.15 + + - name: Check out code + uses: actions/checkout@v2 + + - name: Test + run: go test . + working-directory: cmd/simplehttpserver/ + + - name: Build + run: go build . + working-directory: cmd/simplehttpserver/ \ No newline at end of file diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 70b19c6..0000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: Build -on: - push: - branches: - - master - pull_request: - -jobs: - golangci-lint: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2 - with: - # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: latest - args: --timeout 5m - - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: 1.14 - - - name: Check out code - uses: actions/checkout@v2 - - - name: Test - run: go test . - working-directory: cmd/simplehttpserver - - - name: Build - run: go build . - working-directory: cmd/simplehttpserver/ diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..545cdea --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,38 @@ +name: 🚨 CodeQL Analysis + +on: + workflow_dispatch: + pull_request: + branches: + - dev + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 \ No newline at end of file diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index b46f4e0..49369db 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -1,17 +1,34 @@ -# dockerhub-push pushes docker build to dockerhub automatically -# on the creation of a new release -name: Publish to Dockerhub on creation of a new release -on: +name: 🌥 Docker Push + +on: release: types: [published] + workflow_dispatch: + jobs: - build: + docker: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - - name: Publish to Dockerhub Registry - uses: elgohr/Publish-Docker-Github-Action@master - with: - name: projectdiscovery/simplehttpserver - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} \ No newline at end of file + - + name: Checkout + uses: actions/checkout@v2 + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64,linux/arm + push: true + tags: projectdiscovery/simplehttpserver:latest \ No newline at end of file diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml new file mode 100644 index 0000000..794d073 --- /dev/null +++ b/.github/workflows/lint-test.yml @@ -0,0 +1,19 @@ +name: 🙏🏻 Lint Test +on: + push: + pull_request: + workflow_dispatch: + +jobs: + lint: + name: Lint Test + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest + args: --timeout 5m + working-directory: . \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release-binary.yml similarity index 80% rename from .github/workflows/release.yml rename to .github/workflows/release-binary.yml index 70cb60a..6fe8c82 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release-binary.yml @@ -1,8 +1,9 @@ -name: Release +name: 🎉 Release Binary on: create: tags: - v* + workflow_dispatch: jobs: release: @@ -17,7 +18,7 @@ jobs: name: "Set up Go" uses: actions/setup-go@v2 with: - go-version: 1.14 + go-version: 1.16 - env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" @@ -25,4 +26,5 @@ jobs: uses: goreleaser/goreleaser-action@v2 with: args: "release --rm-dist" - version: latest \ No newline at end of file + version: latest + workdir: . \ No newline at end of file From a40ede72ac439c69da106a86ab2a94d55bcf2429 Mon Sep 17 00:00:00 2001 From: sandeep Date: Wed, 28 Jul 2021 21:29:40 +0530 Subject: [PATCH 062/121] version update --- internal/runner/banner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index a6b729d..9093db8 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -8,11 +8,11 @@ const banner = ` \__ \/ / __ -__ \/ __ \/ / _ \/ /_/ / / / / / / /_/ / ___/ _ \/ ___/ | / / _ \/ ___/ ___/ / / / / / / / /_/ / / __/ __ / / / / / / ____(__ ) __/ / | |/ / __/ / /____/_/_/ /_/ /_/ .___/_/\___/_/ /_/ /_/ /_/ /_/ /____/\___/_/ |___/\___/_/ - /_/ - v0.0.3 + /_/ - v0.0.4 ` // Version is the current version -const Version = `0.0.3` +const Version = `0.0.4` // showBanner is used to show the banner to the user func showBanner() { From 5ae0683445932534dbe508ea068c5c98ab6fd8d6 Mon Sep 17 00:00:00 2001 From: sandeep Date: Wed, 28 Jul 2021 21:46:34 +0530 Subject: [PATCH 063/121] readme update and notes --- README.md | 60 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index fba4ea3..5580afc 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ SimpleHTTPserver is a go enhanced version of the well known python simplehttpser # Features -- HTTPS support -- File server in arbitrary directory -- Full request/response dump +- HTTP/S Web Server +- File Server with arbitrary directory support +- HTTP request/response dump - Configurable ip address and listening port - Configurable HTTP/TCP server with customizable response via YAML template @@ -38,7 +38,7 @@ SimpleHTTPserver is a go enhanced version of the well known python simplehttpser SimpleHTTPserver requires **go1.14+** to install successfully. Run the following command to get the repo - ```sh -▶ GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver +GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver ``` # Usage @@ -49,30 +49,33 @@ simplehttpserver -h This will display help for the tool. Here are all the switches it supports. -| Flag | Description | Example | -| ----------- | -------------------------------------------------------------------- | ------------------------------------------------- | -| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | -| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | -| verbose | Verbose (dump request/response, default false) | simplehttpserver -verbose | -| tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | -| tls | Enable TLS for TCP server | simplehttpserver -tls | -| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | -| upload | Enable file upload in case of http server | simplehttpserver -upload | -| https | Enable HTTPS in case of http server | simplehttpserver -https | -| cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | -| key | HTTPS/TLS certificate private key (self generated if not specified) | simplehttpserver -key cert.key | -| domain | Domain name to use for the self-generated certificate | simplehttpserver -domain projectdiscovery.io | -| basic-auth | Basic auth (username:password) | simplehttpserver -basic-auth user:password | -| realm | Basic auth message | simplehttpserver -realm "insert the credentials" | -| version | Show version | simplehttpserver -version | -| silent | Show only results | simplehttpserver -silent | +| Flag | Description | Example | +| ------------- | ------------------------------------------------------- | ------------------------------------------------ | +| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | +| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | +| verbose | Verbose (dump request/response, default false) | simplehttpserver -verbose | +| tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | +| tls | Enable TLS for TCP server | simplehttpserver -tls | +| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | +| upload | Enable file upload in case of http server | simplehttpserver -upload | +| max-file-size | Max Upload File Size (default 50 MB) | simplehttpserver -max-file-size 100 | +| sandbox | Enable sandbox mode | simplehttpserver -sandbox | +| https | Enable HTTPS in case of http server | simplehttpserver -https | +| cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | +| key | HTTPS/TLS certificate private key | simplehttpserver -key cert.key | +| domain | Domain name to use for the self-generated certificate | simplehttpserver -domain projectdiscovery.io | +| basic-auth | Basic auth (username:password) | simplehttpserver -basic-auth user:password | +| realm | Basic auth message | simplehttpserver -realm "insert the credentials" | +| version | Show version | simplehttpserver -version | +| silent | Show only results | simplehttpserver -silent | ### Running simplehttpserver in the current folder This will run the tool exposing the current directory on port 8000 ```sh -▶ simplehttpserver +simplehttpserver + 2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... 2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 @@ -83,7 +86,8 @@ This will run the tool exposing the current directory on port 8000 This will run the tool exposing the current directory on port 8000 over HTTPS with user provided certificate: ```sh -▶ simplehttpserver -https -cert cert.pen -key cert.key +simplehttpserver -https -cert cert.pen -key cert.key + 2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... 2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 @@ -91,7 +95,8 @@ This will run the tool exposing the current directory on port 8000 over HTTPS wi Instead, to run with self-signed certificate and specific domain name: ```sh -▶ simplehttpserver -https -domain localhost +simplehttpserver -https -domain localhost + 2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... 2021/01/11 21:41:15 [::1]:50181 "GET / HTTP/1.1" 200 383 2021/01/11 21:41:15 [::1]:50181 "GET /favicon.ico HTTP/1.1" 404 19 @@ -102,13 +107,14 @@ Instead, to run with self-signed certificate and specific domain name: This will run the tool and will request the user to enter username and password before authorizing file uploads ```sh -▶ simplehttpserver -basic-auth root:root -upload +simplehttpserver -basic-auth root:root -upload + 2021/01/11 21:40:48 Serving . on http://0.0.0.0:8000/... ``` To upload files use the following curl request with basic auth header: ```sh -▶ curl -v --user 'root:root' --upload-file file.txt http://localhost:8000/file.txt +curl -v --user 'root:root' --upload-file file.txt http://localhost:8000/file.txt ``` ### Running TCP server with custom responses @@ -116,7 +122,7 @@ To upload files use the following curl request with basic auth header: This will run the tool as TLS TCP server and enable custom responses based on YAML templates: ```sh -▶ simplehttpserver -rule rules.yaml -tcp -tls -domain localhost +simplehttpserver -rule rules.yaml -tcp -tls -domain localhost ``` The rules are written as follows: From 9b9c1051ae9ce406361ea181533995b17e8a5c5a Mon Sep 17 00:00:00 2001 From: sandeep Date: Wed, 28 Jul 2021 21:51:55 +0530 Subject: [PATCH 064/121] Added notes --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fba4ea3..f1e6b7c 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,10 @@ rules: response: 250 Accepted ``` +## Note + +- This project is intended for development purposes only; it should not be used in production. + # Thanks SimpleHTTPserver is made with 🖤 by the [projectdiscovery](https://projectdiscovery.io) team. From 501692e028829032ede750677f9a65c0e7e97be0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Aug 2021 12:04:29 +0000 Subject: [PATCH 065/121] chore(deps): bump golang from 1.16.6-alpine to 1.16.7-alpine Bumps golang from 1.16.6-alpine to 1.16.7-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1f80a97..7210e7f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16.6-alpine as build-env +FROM golang:1.16.7-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 67007c899f2ff8f5f601e576102cebb978bc8331 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 12:03:57 +0000 Subject: [PATCH 066/121] chore(deps): bump golang from 1.16.7-alpine to 1.17.0-alpine Bumps golang from 1.16.7-alpine to 1.17.0-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7210e7f..df1a483 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16.7-alpine as build-env +FROM golang:1.17.0-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 0a0a56111b299f41dcbbf7f4dd48012f4253316f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Oct 2021 12:04:06 +0000 Subject: [PATCH 067/121] chore(deps): bump golang from 1.17.0-alpine to 1.17.2-alpine Bumps golang from 1.17.0-alpine to 1.17.2-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index df1a483..9461edd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.0-alpine as build-env +FROM golang:1.17.2-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From dae25034d7cedb96fbfe8b426861b14923cf3dde Mon Sep 17 00:00:00 2001 From: mzack Date: Sat, 16 Oct 2021 14:58:17 +0200 Subject: [PATCH 068/121] Adding support for http1 mode only --- internal/runner/options.go | 4 +++- internal/runner/runner.go | 1 + pkg/httpserver/httpserver.go | 23 ++++++++++++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/internal/runner/options.go b/internal/runner/options.go index a5869d6..6094c7a 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -31,6 +31,7 @@ type Options struct { Silent bool Sandbox bool MaxFileSize int + HTTP1Only bool } // ParseOptions parses the command line options for application @@ -56,7 +57,8 @@ func ParseOptions() *Options { flag.BoolVar(&options.Version, "version", false, "Show version of the software") flag.BoolVar(&options.Silent, "silent", false, "Show only results in the output") flag.BoolVar(&options.Sandbox, "sandbox", false, "Enable sandbox mode") - flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") + flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size in Mb") + flag.BoolVar(&options.HTTP1Only, "http1", false, "Enable only HTTP1") flag.Parse() diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 5806044..88fe753 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -59,6 +59,7 @@ func New(options *Options) (*Runner, error) { Verbose: r.options.Verbose, Sandbox: r.options.Sandbox, MaxFileSize: r.options.MaxFileSize, + HTTP1Only: r.options.HTTP1Only, }) if err != nil { return nil, err diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 72da466..be44567 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -1,6 +1,7 @@ package httpserver import ( + "crypto/tls" "errors" "net/http" "os" @@ -23,7 +24,8 @@ type Options struct { BasicAuthReal string Verbose bool Sandbox bool - MaxFileSize int // 50Mb + MaxFileSize int + HTTP1Only bool } // HTTPServer instance @@ -59,9 +61,20 @@ func New(options *Options) (*HTTPServer, error) { return &h, nil } +func (t *HTTPServer) makeHTTPServer(tlsConfig *tls.Config) *http.Server { + httpServer := &http.Server{Addr: t.options.ListenAddress} + if t.options.HTTP1Only { + httpServer.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler)) + } + httpServer.TLSConfig = tlsConfig + httpServer.Handler = t.layers + return httpServer +} + // ListenAndServe requests over http func (t *HTTPServer) ListenAndServe() error { - return http.ListenAndServe(t.options.ListenAddress, t.layers) + httpServer := t.makeHTTPServer(nil) + return httpServer.ListenAndServe() } // ListenAndServeTLS requests over https @@ -73,11 +86,7 @@ func (t *HTTPServer) ListenAndServeTLS() error { if err != nil { return err } - httpServer := &http.Server{ - Addr: t.options.ListenAddress, - TLSConfig: tlsConfig, - } - httpServer.Handler = t.layers + httpServer := t.makeHTTPServer(tlsConfig) return httpServer.ListenAndServeTLS("", "") } return http.ListenAndServeTLS(t.options.ListenAddress, t.options.Certificate, t.options.CertificateKey, t.layers) From 99ee9320c9c3089acd50475c421308668c8a93c6 Mon Sep 17 00:00:00 2001 From: mzack Date: Sat, 16 Oct 2021 21:12:05 +0200 Subject: [PATCH 069/121] Fixing memory leak on large file dump via max-dump-body-size --- internal/runner/options.go | 40 +++++++++++++++++++----------------- internal/runner/runner.go | 2 ++ pkg/httpserver/httpserver.go | 1 + pkg/httpserver/loglayer.go | 33 +++++++++++++++++++++-------- pkg/httpserver/util.go | 5 ----- pkg/unit/unit.go | 6 ++++++ 6 files changed, 54 insertions(+), 33 deletions(-) delete mode 100644 pkg/httpserver/util.go create mode 100644 pkg/unit/unit.go diff --git a/internal/runner/options.go b/internal/runner/options.go index a5869d6..95b7e03 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -12,25 +12,26 @@ import ( // Options of the tool type Options struct { - ListenAddress string - Folder string - BasicAuth string - username string - password string - Realm string - TLSCertificate string - TLSKey string - TLSDomain string - HTTPS bool - Verbose bool - EnableUpload bool - EnableTCP bool - RulesFile string - TCPWithTLS bool - Version bool - Silent bool - Sandbox bool - MaxFileSize int + ListenAddress string + Folder string + BasicAuth string + username string + password string + Realm string + TLSCertificate string + TLSKey string + TLSDomain string + HTTPS bool + Verbose bool + EnableUpload bool + EnableTCP bool + RulesFile string + TCPWithTLS bool + Version bool + Silent bool + Sandbox bool + MaxFileSize int + MaxDumpBodySize int } // ParseOptions parses the command line options for application @@ -57,6 +58,7 @@ func ParseOptions() *Options { flag.BoolVar(&options.Silent, "silent", false, "Show only results in the output") flag.BoolVar(&options.Sandbox, "sandbox", false, "Enable sandbox mode") flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") + flag.IntVar(&options.MaxDumpBodySize, "max-dump-body-size", -1, "Max Dump Body Size") flag.Parse() diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 5806044..e9f6cbe 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -5,6 +5,7 @@ import ( "github.com/projectdiscovery/simplehttpserver/pkg/binder" "github.com/projectdiscovery/simplehttpserver/pkg/httpserver" "github.com/projectdiscovery/simplehttpserver/pkg/tcpserver" + "github.com/projectdiscovery/simplehttpserver/pkg/unit" ) // Runner is a client for running the enumeration process. @@ -59,6 +60,7 @@ func New(options *Options) (*Runner, error) { Verbose: r.options.Verbose, Sandbox: r.options.Sandbox, MaxFileSize: r.options.MaxFileSize, + MaxDumpBodySize: unit.ToMb(r.options.MaxDumpBodySize), }) if err != nil { return nil, err diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 72da466..d1d8fef 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -24,6 +24,7 @@ type Options struct { Verbose bool Sandbox bool MaxFileSize int // 50Mb + MaxDumpBodySize int64 } // HTTPServer instance diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 0e1a87a..04c5550 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -9,6 +9,7 @@ import ( "path/filepath" "github.com/projectdiscovery/gologger" + "github.com/projectdiscovery/simplehttpserver/pkg/unit" ) // Convenience globals @@ -17,10 +18,19 @@ var ( EnableVerbose bool ) +func (t *HTTPServer) shouldDumpBody(bodysize int64) bool { + return t.options.MaxDumpBodySize > 0 && bodysize > t.options.MaxDumpBodySize +} + func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fullRequest, _ := httputil.DumpRequest(r, true) - lrw := newLoggingResponseWriter(w) + var fullRequest []byte + if t.shouldDumpBody(r.ContentLength) { + fullRequest, _ = httputil.DumpRequest(r, false) + } else { + fullRequest, _ = httputil.DumpRequest(r, true) + } + lrw := newLoggingResponseWriter(w, t.options.MaxDumpBodySize) handler.ServeHTTP(lrw, r) // Handles file write if enabled @@ -52,7 +62,7 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { err error ) if t.options.Sandbox { - maxFileSize := toMb(t.options.MaxFileSize) + maxFileSize := unit.ToMb(t.options.MaxFileSize) // check header content length if r.ContentLength > maxFileSize { gologger.Print().Msg("request too large") @@ -81,24 +91,29 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { lrw.Header().Write(headers) //nolint gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) } else { - gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, len(lrw.Data)) + gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, lrw.Size) } }) } type loggingResponseWriter struct { http.ResponseWriter - statusCode int - Data []byte + statusCode int + Data []byte + Size int + MaxDumpSize int64 } -func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter { - return &loggingResponseWriter{w, http.StatusOK, []byte{}} +func newLoggingResponseWriter(w http.ResponseWriter, maxSize int64) *loggingResponseWriter { + return &loggingResponseWriter{w, http.StatusOK, []byte{}, 0, maxSize} } // Write the data func (lrw *loggingResponseWriter) Write(data []byte) (int, error) { - lrw.Data = append(lrw.Data, data...) + if len(lrw.Data) < int(lrw.MaxDumpSize) { + lrw.Data = append(lrw.Data, data...) + } + lrw.Size += len(data) return lrw.ResponseWriter.Write(data) } diff --git a/pkg/httpserver/util.go b/pkg/httpserver/util.go deleted file mode 100644 index 4c69d6f..0000000 --- a/pkg/httpserver/util.go +++ /dev/null @@ -1,5 +0,0 @@ -package httpserver - -func toMb(n int) int64 { - return int64(n) * 1024 * 1024 -} diff --git a/pkg/unit/unit.go b/pkg/unit/unit.go new file mode 100644 index 0000000..98cdb35 --- /dev/null +++ b/pkg/unit/unit.go @@ -0,0 +1,6 @@ +package unit + +// ToMb converts bytes to megabytes +func ToMb(n int) int64 { + return int64(n) * 1024 * 1024 +} From e04edde1a0e2d1f237005fcb3da181953ff2622a Mon Sep 17 00:00:00 2001 From: sandeep Date: Wed, 20 Oct 2021 05:59:26 +0530 Subject: [PATCH 070/121] issue template update --- .github/ISSUE_TEMPLATE/config.yml | 14 +++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 18 ++++++++++++ .github/ISSUE_TEMPLATE/issue-report.md | 36 +++++++++++++++++++++++ .github/feature_request.md | 14 --------- .github/issue-report.md | 18 ------------ 5 files changed, 68 insertions(+), 32 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/issue-report.md delete mode 100644 .github/feature_request.md delete mode 100644 .github/issue-report.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..cbf59f9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false + +contact_links: + - name: Ask an question / advise on using simplehttpserver + url: https://github.com/projectdiscovery/simplehttpserver/discussions/categories/q-a + about: Ask a question or request support for using simplehttpserver + + - name: Share idea / feature to discuss for simplehttpserver + url: https://github.com/projectdiscovery/simplehttpserver/discussions/categories/ideas + about: Share idea / feature to discuss for simplehttpserver + + - name: Connect with PD Team (Discord) + url: https://discord.gg/projectdiscovery + about: Connect with PD Team for direct communication \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7d33dd1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,18 @@ +--- +name: Feature request +about: Request feature to implement in this project +labels: 'Type: Enhancement' +--- + + + +### Please describe your feature request: + + +### Describe the use case of this feature: + diff --git a/.github/ISSUE_TEMPLATE/issue-report.md b/.github/ISSUE_TEMPLATE/issue-report.md new file mode 100644 index 0000000..d689b0f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-report.md @@ -0,0 +1,36 @@ +--- +name: Issue report +about: Create a report to help us to improve the project +labels: 'Type: Bug' + +--- + + + + + +### simplehttpserver version: + + + + +### Current Behavior: + + +### Expected Behavior: + + +### Steps To Reproduce: + + + +### Anything else: + \ No newline at end of file diff --git a/.github/feature_request.md b/.github/feature_request.md deleted file mode 100644 index 5a71fc0..0000000 --- a/.github/feature_request.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[feature]" -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. diff --git a/.github/issue-report.md b/.github/issue-report.md deleted file mode 100644 index 691d1f4..0000000 --- a/.github/issue-report.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: Issue report -about: Create a report to help us improve -title: "[issue]" -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**Nuclei version** -Please share the version of the nuclei you are running with `simplehttpserver -version` - - -**Screenshot of the error or bug** -please add the screenshot showing bug or issue you are facing. From 8dd2098c0d6b4156475fb406161f9cc9425255c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Nov 2021 12:05:03 +0000 Subject: [PATCH 071/121] chore(deps): bump golang from 1.17.2-alpine to 1.17.3-alpine Bumps golang from 1.17.2-alpine to 1.17.3-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9461edd..4fd0e6e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.2-alpine as build-env +FROM golang:1.17.3-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From d75fcd070f90c7fe2cb815ba58cb4f022b606ca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Dec 2021 12:07:07 +0000 Subject: [PATCH 072/121] chore(deps): bump golang from 1.17.3-alpine to 1.17.4-alpine Bumps golang from 1.17.3-alpine to 1.17.4-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4fd0e6e..63ee89c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.3-alpine as build-env +FROM golang:1.17.4-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From d4fd4c417f843f1bda013176f0928b6187d87483 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Dec 2021 12:03:40 +0000 Subject: [PATCH 073/121] chore(deps): bump golang from 1.17.4-alpine to 1.17.5-alpine Bumps golang from 1.17.4-alpine to 1.17.5-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 63ee89c..ec90ef9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.4-alpine as build-env +FROM golang:1.17.5-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From d55e2f8dfea49661e06934a7400cad1d80b5caca Mon Sep 17 00:00:00 2001 From: invist <35263248+c-f@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:59:36 +0200 Subject: [PATCH 074/121] smalle upload refactoring --- pkg/httpserver/authlayer.go | 2 +- pkg/httpserver/httpserver.go | 22 ++++++++- pkg/httpserver/loglayer.go | 56 ----------------------- pkg/httpserver/uploadlayer.go | 85 ++++++++++++++++++++++++++++++++--- 4 files changed, 101 insertions(+), 64 deletions(-) diff --git a/pkg/httpserver/authlayer.go b/pkg/httpserver/authlayer.go index f2eff4b..297d863 100644 --- a/pkg/httpserver/authlayer.go +++ b/pkg/httpserver/authlayer.go @@ -5,7 +5,7 @@ import ( "net/http" ) -func (t *HTTPServer) basicauthlayer(handler http.Handler) http.HandlerFunc { +func (t *HTTPServer) basicauthlayer(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { user, pass, ok := r.BasicAuth() if !ok || user != t.options.BasicAuthUsername || pass != t.options.BasicAuthPassword { diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 72da466..439de3c 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -32,6 +32,9 @@ type HTTPServer struct { layers http.Handler } +// LayerHandler is the interface of all layer funcs +type Middleware func(http.Handler) http.Handler + // New http server instance with options func New(options *Options) (*HTTPServer, error) { var h HTTPServer @@ -50,10 +53,25 @@ func New(options *Options) (*HTTPServer, error) { if options.Sandbox { dir = SandboxFileSystem{fs: http.Dir(options.Folder), RootFolder: options.Folder} } - h.layers = h.loglayer(http.FileServer(dir)) + + httpHandler := http.FileServer(dir) + addHandler := func(newHandler Middleware) { + httpHandler = newHandler(httpHandler) + } + + // middleware + if options.EnableUpload { + addHandler(h.uploadlayer) + } + if options.BasicAuthUsername != "" || options.BasicAuthPassword != "" { - h.layers = h.loglayer(h.basicauthlayer(http.FileServer(dir))) + addHandler(h.basicauthlayer) } + + httpHandler = h.loglayer(httpHandler) + + // add handler + h.layers = httpHandler h.options = options return &h, nil diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index 0e1a87a..468fb6a 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -2,11 +2,8 @@ package httpserver import ( "bytes" - "io/ioutil" "net/http" "net/http/httputil" - "path" - "path/filepath" "github.com/projectdiscovery/gologger" ) @@ -23,59 +20,6 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { lrw := newLoggingResponseWriter(w) handler.ServeHTTP(lrw, r) - // Handles file write if enabled - if EnableUpload && r.Method == http.MethodPut { - // sandbox - calcolate absolute path - if t.options.Sandbox { - absPath, err := filepath.Abs(filepath.Join(t.options.Folder, r.URL.Path)) - if err != nil { - gologger.Print().Msgf("%s\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } - // check if the path is within the configured folder - pattern := t.options.Folder + string(filepath.Separator) + "*" - matched, err := filepath.Match(pattern, absPath) - if err != nil { - gologger.Print().Msgf("%s\n", err) - w.WriteHeader(http.StatusBadRequest) - return - } else if !matched { - gologger.Print().Msg("pointing to unauthorized directory") - w.WriteHeader(http.StatusBadRequest) - return - } - } - - var ( - data []byte - err error - ) - if t.options.Sandbox { - maxFileSize := toMb(t.options.MaxFileSize) - // check header content length - if r.ContentLength > maxFileSize { - gologger.Print().Msg("request too large") - return - } - // body max length - r.Body = http.MaxBytesReader(w, r.Body, maxFileSize) - } - - data, err = ioutil.ReadAll(r.Body) - if err != nil { - gologger.Print().Msgf("%s\n", err) - w.WriteHeader(http.StatusInternalServerError) - return - } - err = handleUpload(t.options.Folder, path.Base(r.URL.Path), data) - if err != nil { - gologger.Print().Msgf("%s\n", err) - w.WriteHeader(http.StatusInternalServerError) - return - } - } - if EnableVerbose { headers := new(bytes.Buffer) lrw.Header().Write(headers) //nolint diff --git a/pkg/httpserver/uploadlayer.go b/pkg/httpserver/uploadlayer.go index 928ac60..9f4821f 100644 --- a/pkg/httpserver/uploadlayer.go +++ b/pkg/httpserver/uploadlayer.go @@ -3,21 +3,96 @@ package httpserver import ( "errors" "io/ioutil" + "net/http" + "os" + "path" "path/filepath" "strings" + + "github.com/projectdiscovery/gologger" ) +// uploadlayer handles PUT requests and save the file to disk +func (t *HTTPServer) uploadlayer(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Handles file write if enabled + if EnableUpload && r.Method == http.MethodPut { + // sandbox - calcolate absolute path + if t.options.Sandbox { + absPath, err := filepath.Abs(filepath.Join(t.options.Folder, r.URL.Path)) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } + // check if the path is within the configured folder + pattern := t.options.Folder + string(filepath.Separator) + "*" + matched, err := filepath.Match(pattern, absPath) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusBadRequest) + return + } else if !matched { + gologger.Print().Msg("pointing to unauthorized directory") + w.WriteHeader(http.StatusBadRequest) + return + } + } + + var ( + data []byte + err error + ) + if t.options.Sandbox { + maxFileSize := toMb(t.options.MaxFileSize) + // check header content length + if r.ContentLength > maxFileSize { + gologger.Print().Msg("request too large") + return + } + // body max length + r.Body = http.MaxBytesReader(w, r.Body, maxFileSize) + } + + data, err = ioutil.ReadAll(r.Body) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + sanitizedPath := filepath.FromSlash(path.Clean("/" + strings.Trim(r.URL.Path, "/"))) + + err = handleUpload(t.options.Folder, sanitizedPath, data) + if err != nil { + gologger.Print().Msgf("%s\n", err) + w.WriteHeader(http.StatusInternalServerError) + return + } else { + w.WriteHeader(http.StatusCreated) + return + } + } + + handler.ServeHTTP(w, r) + }) +} + func handleUpload(base, file string, data []byte) error { // rejects all paths containing a non exhaustive list of invalid characters - This is only a best effort as the tool is meant for development if strings.ContainsAny(file, "\\`\"':") { return errors.New("invalid character") } - // allow upload only in subfolders - rel, err := filepath.Rel(base, file) - if rel == "" || err != nil { - return err + untrustedPath := filepath.Clean(filepath.Join(base, file)) + if !strings.HasPrefix(untrustedPath, filepath.Clean(base)) { + return errors.New("invalid path") + } + trustedPath := untrustedPath + + if _, err := os.Stat(path.Dir(trustedPath)); os.IsNotExist(err) { + return errors.New("invalid path") } - return ioutil.WriteFile(file, data, 0655) + return ioutil.WriteFile(trustedPath, data, 0655) } From 4fb2abb558e98ae03d11f2220d7f0d2618efb0e8 Mon Sep 17 00:00:00 2001 From: c-f <35263248+c-f@users.noreply.github.com> Date: Mon, 20 Dec 2021 16:46:39 +0100 Subject: [PATCH 075/121] remove bug of reading previous messages --- pkg/tcpserver/tcpserver.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index 876fbb4..bed8e95 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -59,14 +59,14 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { if err := conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second)); err != nil { gologger.Info().Msgf("%s\n", err) } - _, err := conn.Read(buf) + n, err := conn.Read(buf) if err != nil { return err } - gologger.Print().Msgf("%s\n", buf) + gologger.Print().Msgf("%s\n", buf[:n]) - resp, err := t.BuildResponse(buf) + resp, err := t.BuildResponse(buf[:n]) if err != nil { return err } From e615365be58ccaf78274d0c212a35bf62a9d382a Mon Sep 17 00:00:00 2001 From: c-f <35263248+c-f@users.noreply.github.com> Date: Mon, 20 Dec 2021 17:44:21 +0100 Subject: [PATCH 076/121] add livereloading for rule config --- internal/runner/runner.go | 2 ++ internal/runner/watchdog.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 internal/runner/watchdog.go diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 269dd15..cbd9227 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -42,6 +42,8 @@ func New(options *Options) (*Runner, error) { if err != nil { return nil, err } + watchFile(r.options.RulesFile, serverTCP.LoadTemplate) + r.serverTCP = serverTCP return &r, nil } diff --git a/internal/runner/watchdog.go b/internal/runner/watchdog.go new file mode 100644 index 0000000..2cdde4c --- /dev/null +++ b/internal/runner/watchdog.go @@ -0,0 +1,36 @@ +package runner + +import ( + "log" + + "github.com/fsnotify/fsnotify" +) + +type WatchEvent func(fname string) error + +func watchFile(fname string, callback WatchEvent) (watcher *fsnotify.Watcher, err error) { + watcher, err = fsnotify.NewWatcher() + if err != nil { + return + } + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + continue + } + if event.Op&fsnotify.Write == fsnotify.Write { + if err := callback(fname); err != nil { + log.Println("err", err) + } + } + case <-watcher.Errors: + // ignore errors for now + } + } + }() + + err = watcher.Add(fname) + return +} From 420a99f54aea3a31ce03055cdc0c7792440b9481 Mon Sep 17 00:00:00 2001 From: c-f <35263248+c-f@users.noreply.github.com> Date: Mon, 20 Dec 2021 18:11:53 +0100 Subject: [PATCH 077/121] make linter happy --- README.md | 15 ++++++- go.mod | 1 + go.sum | 4 ++ internal/runner/runner.go | 6 ++- pkg/tcpserver/addr.go | 9 ++++ pkg/tcpserver/responseengine.go | 7 ++- pkg/tcpserver/rule.go | 50 ++++++++++++++++++--- pkg/tcpserver/tcpserver.go | 77 ++++++++++++++++++++++++++++++--- 8 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 pkg/tcpserver/addr.go diff --git a/README.md b/README.md index b533b2a..e08d29a 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,9 @@ simplehttpserver -rule rules.yaml -tcp -tls -domain localhost The rules are written as follows: ```yaml rules: - - match: regex + - match: regex-match + match-contains: literal-match + name: rule-name response: response data ``` @@ -137,6 +139,7 @@ For example to handle two different paths simulating an HTTP server or SMTP comm rules: # HTTP Requests - match: GET /path1 + name: redirect response: | HTTP/1.0 200 OK Server: httpd/2.0 @@ -149,6 +152,7 @@ rules: - match: GET /path2 + name: "404" response: | HTTP/1.0 404 OK Server: httpd/2.0 @@ -156,6 +160,7 @@ rules: Not found # SMTP Commands - match: "EHLO example.com" + name: smtp response: | 250-localhost Nice to meet you, [127.0.0.1] 250-PIPELINING @@ -167,6 +172,14 @@ rules: response: 250 Accepted - match: "RCPT TO: " response: 250 Accepted + + - match-contains: !!binary | + MAwCAQFgBwIBAwQAgAA= + name: "ldap" + # Request: 300c 0201 0160 0702 0103 0400 8000 0....`........ + # Response: 300c 0201 0161 070a 0100 0400 0400 0....a........ + response: !!binary | + MAwCAQFhBwoBAAQABAA= ``` ## Note diff --git a/go.mod b/go.mod index f4c4a9d..7b6de7d 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.14 require ( + github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e diff --git a/go.sum b/go.sum index aafe4a2..e239b8e 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -31,6 +33,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/runner/runner.go b/internal/runner/runner.go index cbd9227..49d5cd3 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -42,7 +42,11 @@ func New(options *Options) (*Runner, error) { if err != nil { return nil, err } - watchFile(r.options.RulesFile, serverTCP.LoadTemplate) + watcher, err := watchFile(r.options.RulesFile, serverTCP.LoadTemplate) + if err != nil { + return nil, err + } + defer watcher.Close() r.serverTCP = serverTCP return &r, nil diff --git a/pkg/tcpserver/addr.go b/pkg/tcpserver/addr.go new file mode 100644 index 0000000..b678b30 --- /dev/null +++ b/pkg/tcpserver/addr.go @@ -0,0 +1,9 @@ +package tcpserver + +// ContextType is the key type stored in ctx +type ContextType string + +var ( + // Addr is the contextKey where the net.Addr is stored + Addr ContextType = "addr" +) diff --git a/pkg/tcpserver/responseengine.go b/pkg/tcpserver/responseengine.go index ec15da0..80fb795 100644 --- a/pkg/tcpserver/responseengine.go +++ b/pkg/tcpserver/responseengine.go @@ -6,9 +6,12 @@ import ( // BuildResponse according to rules func (t *TCPServer) BuildResponse(data []byte) ([]byte, error) { + t.mux.RLock() + defer t.mux.RUnlock() + // Process all the rules - for _, rule := range t.options.rules { - if rule.matchRegex.Match(data) { + for _, rule := range t.rules { + if rule.MatchInput(data) { return []byte(rule.Response), nil } } diff --git a/pkg/tcpserver/rule.go b/pkg/tcpserver/rule.go index 903331b..aa9e6e8 100644 --- a/pkg/tcpserver/rule.go +++ b/pkg/tcpserver/rule.go @@ -1,6 +1,9 @@ package tcpserver -import "regexp" +import ( + "regexp" + "strings" +) // RulesConfiguration from yaml type RulesConfiguration struct { @@ -9,13 +12,20 @@ type RulesConfiguration struct { // Rule to apply to various requests type Rule struct { - Match string `yaml:"match,omitempty"` - matchRegex *regexp.Regexp - Response string `yaml:"response,omitempty"` + Name string `yaml:"name,omitempty"` + Match string `yaml:"match,omitempty"` + MatchContains string `yaml:"match-contains,omitempty"` + matchRegex *regexp.Regexp + Response string `yaml:"response,omitempty"` } -// NewRule from model +// NewRule creates a new Rule - default is regex func NewRule(match, response string) (*Rule, error) { + return NewRegexRule(match, response) +} + +// NewRegexRule returns a new regex-match Rule +func NewRegexRule(match, response string) (*Rule, error) { regxp, err := regexp.Compile(match) if err != nil { return nil, err @@ -23,3 +33,33 @@ func NewRule(match, response string) (*Rule, error) { return &Rule{Match: match, matchRegex: regxp, Response: response}, nil } + +// NewLiteralRule returns a new literal-match Rule +func NewLiteralRule(match, response string) (*Rule, error) { + return &Rule{MatchContains: match, Response: response}, nil +} + +// NewRuleFromTemplate "copies" a new Rule +func NewRuleFromTemplate(r Rule) (newRule *Rule, err error) { + newRule = &Rule{ + Name: r.Name, + Response: r.Response, + MatchContains: r.MatchContains, + Match: r.Match, + } + if newRule.Match != "" { + newRule.matchRegex, err = regexp.Compile(newRule.Match) + } + + return +} + +// MatchInput returns if the input was matches with one of the matchers +func (r *Rule) MatchInput(input []byte) bool { + if r.matchRegex != nil && r.matchRegex.Match(input) { + return true + } else if r.MatchContains != "" && strings.Contains(string(input), r.MatchContains) { + return true + } + return false +} diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index bed8e95..cbdd407 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -1,9 +1,12 @@ package tcpserver import ( + "context" "crypto/tls" + "errors" "io/ioutil" "net" + "sync" "time" "github.com/projectdiscovery/gologger" @@ -24,20 +27,35 @@ type Options struct { Verbose bool } +// CallBackFunc handles what is send back to the client, based on the incomming question +type CallBackFunc func(ctx context.Context, question []byte) (answer []byte, err error) + // TCPServer instance type TCPServer struct { options *Options listener net.Listener + + // Callbacks to retrieve information about the system + HandleMessageFnc CallBackFunc + + mux sync.RWMutex + rules []Rule } // New tcp server instance with specified options func New(options *Options) (*TCPServer, error) { - return &TCPServer{options: options}, nil + srv := &TCPServer{options: options} + srv.HandleMessageFnc = srv.BuildResponseWithContext + srv.rules = options.rules + return srv, nil } // AddRule to the server func (t *TCPServer) AddRule(rule Rule) error { - t.options.rules = append(t.options.rules, rule) + t.mux.Lock() + defer t.mux.Unlock() + + t.rules = append(t.rules, rule) return nil } @@ -51,9 +69,12 @@ func (t *TCPServer) ListenAndServe() error { return t.run() } -func (t *TCPServer) handleConnection(conn net.Conn) error { +func (t *TCPServer) handleConnection(conn net.Conn, callback CallBackFunc) error { defer conn.Close() //nolint + // Create Context + ctx := context.WithValue(context.Background(), Addr, conn.RemoteAddr()) + buf := make([]byte, 4096) for { if err := conn.SetReadDeadline(time.Now().Add(readTimeout * time.Second)); err != nil { @@ -66,8 +87,9 @@ func (t *TCPServer) handleConnection(conn net.Conn) error { gologger.Print().Msgf("%s\n", buf[:n]) - resp, err := t.BuildResponse(buf[:n]) + resp, err := callback(ctx, buf[:n]) if err != nil { + gologger.Info().Msgf("Closing connection: %s\n", err) return err } @@ -112,7 +134,7 @@ func (t *TCPServer) run() error { if err != nil { return err } - go t.handleConnection(c) //nolint + go t.handleConnection(c, t.HandleMessageFnc) //nolint } } @@ -133,13 +155,54 @@ func (t *TCPServer) LoadTemplate(templatePath string) error { return err } + t.mux.Lock() + defer t.mux.Unlock() + + t.rules = make([]Rule, 0) for _, ruleTemplate := range config.Rules { - rule, err := NewRule(ruleTemplate.Match, ruleTemplate.Response) + rule, err := NewRuleFromTemplate(ruleTemplate) if err != nil { return err } - t.options.rules = append(t.options.rules, *rule) + t.rules = append(t.rules, *rule) } + gologger.Info().Msgf("TCP configuration loaded. Rules: %d\n", len(t.rules)) + return nil } + +// MatchRule returns the rule, which was matched first +func (t *TCPServer) MatchRule(data []byte) (rule Rule, err error) { + t.mux.RLock() + defer t.mux.RUnlock() + + // Process all the rules + for _, rule := range t.rules { + if rule.MatchInput(data) { + return rule, nil + } + } + return Rule{}, errors.New("no matched rule") +} + +// BuildResponseWithContext is a wrapper with context +func (t *TCPServer) BuildResponseWithContext(ctx context.Context, data []byte) ([]byte, error) { + return t.BuildResponse(data) +} + +// BuildResponseWithContext is a wrapper with context +func (t *TCPServer) BuildRuleResponse(ctx context.Context, data []byte) ([]byte, error) { + addr := "unknown" + if netAddr, ok := ctx.Value(Addr).(net.Addr); ok { + addr = netAddr.String() + } + rule, err := t.MatchRule(data) + if err != nil { + return []byte(":) "), err + } + + gologger.Info().Msgf("Incoming TCP request(%s) from: %s\n", rule.Name, addr) + + return []byte(rule.Response), nil +} From 5f46aab077a27d85e7035bf93f7d81ce07693c23 Mon Sep 17 00:00:00 2001 From: mzack Date: Tue, 21 Dec 2021 16:43:53 +0100 Subject: [PATCH 078/121] Adding missing logic to enable TCP TLS server --- internal/runner/runner.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 269dd15..94f55f0 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -74,6 +74,10 @@ func New(options *Options) (*Runner, error) { // Run logic func (r *Runner) Run() error { if r.options.EnableTCP { + if r.options.TCPWithTLS { + gologger.Print().Msgf("Serving TCP rule based tls server on tcp://%s", r.options.ListenAddress) + return r.serverTCP.ListenAndServeTLS() + } gologger.Print().Msgf("Serving TCP rule based server on tcp://%s", r.options.ListenAddress) return r.serverTCP.ListenAndServe() } From 342bd07c37abdff4a09c8648ea97959594257a8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jan 2022 12:06:04 +0000 Subject: [PATCH 079/121] chore(deps): bump golang from 1.17.5-alpine to 1.17.6-alpine Bumps golang from 1.17.5-alpine to 1.17.6-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ec90ef9..0535716 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.5-alpine as build-env +FROM golang:1.17.6-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From c8430a9829e68939e941801a43daf2ce41c4507d Mon Sep 17 00:00:00 2001 From: Jon Goodgion <12418879+bridge-four@users.noreply.github.com> Date: Thu, 13 Jan 2022 08:47:31 -0800 Subject: [PATCH 080/121] add timestamps --- pkg/httpserver/loglayer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/httpserver/loglayer.go b/pkg/httpserver/loglayer.go index b0f1023..f3fb4f7 100644 --- a/pkg/httpserver/loglayer.go +++ b/pkg/httpserver/loglayer.go @@ -4,7 +4,7 @@ import ( "bytes" "net/http" "net/http/httputil" - + "time" "github.com/projectdiscovery/gologger" ) @@ -32,9 +32,9 @@ func (t *HTTPServer) loglayer(handler http.Handler) http.Handler { if EnableVerbose { headers := new(bytes.Buffer) lrw.Header().Write(headers) //nolint - gologger.Print().Msgf("\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) + gologger.Print().Msgf("\n[%s]\nRemote Address: %s\n%s\n%s %d %s\n%s\n%s\n", time.Now().Format("2006-01-02 15:04:05"), r.RemoteAddr, string(fullRequest), r.Proto, lrw.statusCode, http.StatusText(lrw.statusCode), headers.String(), string(lrw.Data)) } else { - gologger.Print().Msgf("%s \"%s %s %s\" %d %d", r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, lrw.Size) + gologger.Print().Msgf("[%s] %s \"%s %s %s\" %d %d", time.Now().Format("2006-01-02 15:04:05"), r.RemoteAddr, r.Method, r.URL, r.Proto, lrw.statusCode, lrw.Size) } }) } From 70f410daaf0198594efa4972e3c7cda37cbe7659 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Feb 2022 12:06:24 +0000 Subject: [PATCH 081/121] chore(deps): bump golangci/golangci-lint-action from 2 to 3.1.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 2 to 3.1.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v2...v3.1.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 794d073..5fbc57f 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3.1.0 with: version: latest args: --timeout 5m From f5624c5bd04ffb399a9d09c3728187f6abaccccc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:05:43 +0000 Subject: [PATCH 082/121] chore(deps): bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-test.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dockerhub-push.yml | 2 +- .github/workflows/lint-test.yml | 2 +- .github/workflows/release-binary.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 6bfe472..5ced080 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -16,7 +16,7 @@ jobs: go-version: 1.15 - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Test run: go test . diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 545cdea..601d89a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 49369db..07ba054 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v1 diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 5fbc57f..1531c6b 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Run golangci-lint uses: golangci/golangci-lint-action@v3.1.0 with: diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index 6fe8c82..8025dd8 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -11,7 +11,7 @@ jobs: steps: - name: "Check out code" - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - From cb02ccf72c2d1e1ce4415f1918786c7ecf203218 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Mar 2022 12:27:57 +0000 Subject: [PATCH 083/121] chore(deps): bump golang from 1.17.6-alpine to 1.18.0-alpine Bumps golang from 1.17.6-alpine to 1.18.0-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0535716..a0842da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.17.6-alpine as build-env +FROM golang:1.18.0-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 15f52b0fb31c2044a10c2d5b72d66aaf249b25da Mon Sep 17 00:00:00 2001 From: forgedhallpass <13679401+forgedhallpass@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:21:26 +0300 Subject: [PATCH 084/121] Go version update to 1.18 in GitHub actions * "setup-go", "checkout" and "golangci-lint-action" actions updated to v3 --- .github/workflows/build-test.yml | 6 +++--- .github/workflows/lint-test.yml | 4 ++-- .github/workflows/release-binary.yml | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 6bfe472..00cd9ee 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -11,12 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.15 + go-version: 1.18 - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Test run: go test . diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 794d073..6ba06a6 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -10,9 +10,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: version: latest args: --timeout 5m diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index 6fe8c82..d3c4c9d 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -11,14 +11,14 @@ jobs: steps: - name: "Check out code" - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: "Set up Go" - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.16 + go-version: 1.18 - env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" From af80111b5c6c194788b8015339bcb6b716fadac7 Mon Sep 17 00:00:00 2001 From: forgedhallpass <13679401+forgedhallpass@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:22:42 +0300 Subject: [PATCH 085/121] Dockerfile go version update to 1.18-alpine --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1f80a97..2250723 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM golang:1.16.6-alpine as build-env -RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver +FROM golang:1.18-alpine as build-env +RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest RUN apk add --no-cache bind-tools ca-certificates From c19fbd58a5f15bef9f1c2478cfbe72efde8ad8fe Mon Sep 17 00:00:00 2001 From: forgedhallpass <13679401+forgedhallpass@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:23:01 +0300 Subject: [PATCH 086/121] go.mod version update to 1.17 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index f4c4a9d..bd86ea0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectdiscovery/simplehttpserver -go 1.14 +go 1.17 require ( github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 From 5e118417eae5222617507fb55a8e1bf930474bba Mon Sep 17 00:00:00 2001 From: forgedhallpass <13679401+forgedhallpass@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:24:19 +0300 Subject: [PATCH 087/121] Documentation update: "go install" instead of "go get" --- README.md | 42 +++++++++++++++++++++--------------------- SECURITY.md | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index b533b2a..b6184d9 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,10 @@ SimpleHTTPserver is a go enhanced version of the well known python simplehttpser # Installing SimpleHTTPserver -SimpleHTTPserver requires **go1.14+** to install successfully. Run the following command to get the repo - +SimpleHTTPserver requires **go1.17+** to install successfully. Run the following command to get the repo - ```sh -GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver +go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest ``` # Usage @@ -49,25 +49,25 @@ simplehttpserver -h This will display help for the tool. Here are all the switches it supports. -| Flag | Description | Example | -| ------------- | ------------------------------------------------------- | ------------------------------------------------ | -| listen | Configure listening ip:port (default 127.0.0.1:8000) | simplehttpserver -listen 127.0.0.1:8000 | -| path | Fileserver folder (default current directory) | simplehttpserver -path /var/docs | -| verbose | Verbose (dump request/response, default false) | simplehttpserver -verbose | -| tcp | TCP server (default 127.0.0.1:8000) | simplehttpserver -tcp 127.0.0.1:8000 | -| tls | Enable TLS for TCP server | simplehttpserver -tls | -| rules | File containing yaml rules | simplehttpserver -rules rule.yaml | -| upload | Enable file upload in case of http server | simplehttpserver -upload | -| max-file-size | Max Upload File Size (default 50 MB) | simplehttpserver -max-file-size 100 | -| sandbox | Enable sandbox mode | simplehttpserver -sandbox | -| https | Enable HTTPS in case of http server | simplehttpserver -https | -| cert | HTTPS/TLS certificate (self generated if not specified) | simplehttpserver -cert cert.pem | -| key | HTTPS/TLS certificate private key | simplehttpserver -key cert.key | -| domain | Domain name to use for the self-generated certificate | simplehttpserver -domain projectdiscovery.io | -| basic-auth | Basic auth (username:password) | simplehttpserver -basic-auth user:password | -| realm | Basic auth message | simplehttpserver -realm "insert the credentials" | -| version | Show version | simplehttpserver -version | -| silent | Show only results | simplehttpserver -silent | +| Flag | Description | Example | +|------------------|---------------------------------------------------------|----------------------------------------------------| +| `-listen` | Configure listening ip:port (default 127.0.0.1:8000) | `simplehttpserver -listen 127.0.0.1:8000` | +| `-path` | Fileserver folder (default current directory) | `simplehttpserver -path /var/docs` | +| `-verbose` | Verbose (dump request/response, default false) | `simplehttpserver -verbose` | +| `-tcp` | TCP server (default 127.0.0.1:8000) | `simplehttpserver -tcp 127.0.0.1:8000` | +| `-tls` | Enable TLS for TCP server | `simplehttpserver -tls` | +| `-rules` | File containing yaml rules | `simplehttpserver -rules rule.yaml` | +| `-upload` | Enable file upload in case of http server | `simplehttpserver -upload` | +| `-max-file-size` | Max Upload File Size (default 50 MB) | `simplehttpserver -max-file-size 100` | +| `-sandbox` | Enable sandbox mode | `simplehttpserver -sandbox` | +| `-https` | Enable HTTPS in case of http server | `simplehttpserver -https` | +| `-cert` | HTTPS/TLS certificate (self generated if not specified) | `simplehttpserver -cert cert.pem` | +| `-key` | HTTPS/TLS certificate private key | `simplehttpserver -key cert.key` | +| `-domain` | Domain name to use for the self-generated certificate | `simplehttpserver -domain projectdiscovery.io` | +| `-basic-auth` | Basic auth (username:password) | `simplehttpserver -basic-auth user:password` | +| `-realm` | Basic auth message | `simplehttpserver -realm "insert the credentials"` | +| `-version` | Show version | `simplehttpserver -version` | +| `-silent` | Show only results | `simplehttpserver -silent` | ### Running simplehttpserver in the current folder diff --git a/SECURITY.md b/SECURITY.md index fc8033f..7052910 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,4 +2,4 @@ ## Reporting a Vulnerability -DO NOT CREATE AN ISSUE to report a security problem. Instead, please send an email to security@projectdiscovery.io and we will acknowledge it within 3 working days. +DO NOT CREATE AN ISSUE to report a security problem. Instead, please send an email to [security@projectdiscovery.io](mailto:security@projectdiscovery.io), and we will acknowledge it within 3 working days. From 9f02213a8121e6401a135691ff05c784c9a9669f Mon Sep 17 00:00:00 2001 From: forgedhallpass <13679401+forgedhallpass@users.noreply.github.com> Date: Thu, 14 Apr 2022 13:30:21 +0300 Subject: [PATCH 088/121] go.mod synchronisation --- go.mod | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go.mod b/go.mod index bd86ea0..64bffb3 100644 --- a/go.mod +++ b/go.mod @@ -8,3 +8,10 @@ require ( github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e gopkg.in/yaml.v2 v2.4.0 ) + +require ( + github.com/json-iterator/go v1.1.10 // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect +) From e87cc4084973a39411f8e0c557c2588b3b6e1f5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Apr 2022 12:10:37 +0000 Subject: [PATCH 089/121] chore(deps): bump golang from 1.18.0-alpine to 1.18.1-alpine Bumps golang from 1.18.0-alpine to 1.18.1-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a0842da..2850f62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18.0-alpine as build-env +FROM golang:1.18.1-alpine as build-env RUN GO111MODULE=on go get -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver FROM alpine:latest From 45ffc10bbadbb98418313fb9d5a214d6e64e4000 Mon Sep 17 00:00:00 2001 From: sandeep Date: Mon, 18 Apr 2022 18:18:40 +0530 Subject: [PATCH 090/121] version update --- internal/runner/banner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/runner/banner.go b/internal/runner/banner.go index 9093db8..24febe0 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -8,11 +8,11 @@ const banner = ` \__ \/ / __ -__ \/ __ \/ / _ \/ /_/ / / / / / / /_/ / ___/ _ \/ ___/ | / / _ \/ ___/ ___/ / / / / / / / /_/ / / __/ __ / / / / / / ____(__ ) __/ / | |/ / __/ / /____/_/_/ /_/ /_/ .___/_/\___/_/ /_/ /_/ /_/ /_/ /____/\___/_/ |___/\___/_/ - /_/ - v0.0.4 + /_/ - v0.0.5 ` // Version is the current version -const Version = `0.0.4` +const Version = `0.0.5` // showBanner is used to show the banner to the user func showBanner() { From 6f8863d09ee669fa879208aeea9069529704f772 Mon Sep 17 00:00:00 2001 From: sandeep Date: Mon, 18 Apr 2022 18:22:31 +0530 Subject: [PATCH 091/121] readme update --- README.md | 1 + go.mod | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2afe3bb..0363d59 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ This will display help for the tool. Here are all the switches it supports. | `-max-file-size` | Max Upload File Size (default 50 MB) | `simplehttpserver -max-file-size 100` | | `-sandbox` | Enable sandbox mode | `simplehttpserver -sandbox` | | `-https` | Enable HTTPS in case of http server | `simplehttpserver -https` | +| `-http1` | Enable only HTTP1 | `simplehttpserver -http1` | | `-cert` | HTTPS/TLS certificate (self generated if not specified) | `simplehttpserver -cert cert.pem` | | `-key` | HTTPS/TLS certificate private key | `simplehttpserver -key cert.key` | | `-domain` | Domain name to use for the self-generated certificate | `simplehttpserver -domain projectdiscovery.io` | diff --git a/go.mod b/go.mod index 4e30d64..2f48683 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.17 require ( - github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/fsnotify/fsnotify v1.5.1 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e @@ -15,4 +15,5 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect + golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect ) From 467aea4360fce1bd224baf421c462c1d9139da48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 12:07:02 +0000 Subject: [PATCH 092/121] chore(deps): bump github/codeql-action from 1 to 2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v1...v2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 601d89a..9f533f8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,12 +27,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 \ No newline at end of file + uses: github/codeql-action/analyze@v2 \ No newline at end of file From 2769a8b4f73fb0b4297ab30bc1ea902d39e9063d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 May 2022 12:07:04 +0000 Subject: [PATCH 093/121] chore(deps): bump github.com/fsnotify/fsnotify from 1.5.1 to 1.5.4 Bumps [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify) from 1.5.1 to 1.5.4. - [Release notes](https://github.com/fsnotify/fsnotify/releases) - [Changelog](https://github.com/fsnotify/fsnotify/blob/main/CHANGELOG.md) - [Commits](https://github.com/fsnotify/fsnotify/compare/v1.5.1...v1.5.4) --- updated-dependencies: - dependency-name: github.com/fsnotify/fsnotify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2f48683..f01e559 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.17 require ( - github.com/fsnotify/fsnotify v1.5.1 + github.com/fsnotify/fsnotify v1.5.4 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e @@ -15,5 +15,5 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect ) diff --git a/go.sum b/go.sum index e239b8e..d3940da 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -33,8 +33,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From a5b3896ed23d7be757c252c4ef1fb6b7591b1ff6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 May 2022 12:05:59 +0000 Subject: [PATCH 094/121] chore(deps): bump docker/build-push-action from 2 to 3 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2 to 3. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dockerhub-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 07ba054..1f8a8df 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -26,7 +26,7 @@ jobs: password: ${{ secrets.DOCKER_TOKEN }} - name: Build and push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64,linux/arm64,linux/arm From 40ac088e6c2ea4440a1ba1e8a23bfbcd0278f5d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 May 2022 12:06:01 +0000 Subject: [PATCH 095/121] chore(deps): bump docker/login-action from 1 to 2 Bumps [docker/login-action](https://github.com/docker/login-action) from 1 to 2. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v1...v2) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dockerhub-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 07ba054..f7dfd68 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -20,7 +20,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} From f4b868a6197e35495f04c85a984f650bc05cbf47 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 May 2022 12:06:03 +0000 Subject: [PATCH 096/121] chore(deps): bump docker/setup-buildx-action from 1 to 2 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 2. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v2) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dockerhub-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 07ba054..4d87e65 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -17,7 +17,7 @@ jobs: uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 - name: Login to DockerHub uses: docker/login-action@v1 From 9044fe34f648908b5fd86388580a1bec3dad78a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 May 2022 12:06:05 +0000 Subject: [PATCH 097/121] chore(deps): bump docker/setup-qemu-action from 1 to 2 Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1 to 2. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v1...v2) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dockerhub-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 07ba054..e708870 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v3 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 From 1a953b227d61485dbadc27c1936de34ee0c44fc8 Mon Sep 17 00:00:00 2001 From: Mzack9999 Date: Mon, 20 Jun 2022 11:33:26 +0200 Subject: [PATCH 098/121] Refactoring GitHub actions (#83) --- .github/workflows/lint-test.yml | 4 ++++ .github/workflows/release-binary.yml | 17 +++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 1531c6b..8f0b292 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -9,6 +9,10 @@ jobs: name: Lint Test runs-on: ubuntu-latest steps: + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.18 - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index d3c4c9d..fd600f5 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -9,21 +9,18 @@ jobs: release: runs-on: ubuntu-latest steps: - - - name: "Check out code" - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: "Set up Go" + - name: "Set up Go" uses: actions/setup-go@v3 with: go-version: 1.18 - - + - name: "Check out code" + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: "Create release on GitHub" + uses: goreleaser/goreleaser-action@v2 env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - name: "Create release on GitHub" - uses: goreleaser/goreleaser-action@v2 with: args: "release --rm-dist" version: latest From 7837603fb8f4878f38d5a470bc0e9b15cbf3a39d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Jul 2022 01:49:28 +0530 Subject: [PATCH 099/121] chore(deps): bump golangci/golangci-lint-action from 3.1.0 to 3.2.0 (#84) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 8f0b292..d8b1dbc 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3.1.0 + uses: golangci/golangci-lint-action@v3.2.0 with: version: latest args: --timeout 5m From 7d15504321e403dc5299681bfecac0b3d42edc36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Jul 2022 01:49:40 +0530 Subject: [PATCH 100/121] chore(deps): bump goreleaser/goreleaser-action from 2 to 3 (#85) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 2 to 3. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v2...v3) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-binary.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index fd600f5..feec85f 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: "Create release on GitHub" - uses: goreleaser/goreleaser-action@v2 + uses: goreleaser/goreleaser-action@v3 env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" with: From 1f800063c03167c24464f301712c94d2a0a4b1ed Mon Sep 17 00:00:00 2001 From: Dominic Breuker Date: Mon, 25 Jul 2022 16:56:41 +0200 Subject: [PATCH 101/121] Add support for custom HTTP response headers (#86) * add support for custom HTTP response headers * update flag list in readme * fix readme typo and adjust cases of words Co-authored-by: Sandeep Singh --- README.md | 1 + internal/runner/options.go | 62 ++++++++++++++++++++++++----------- internal/runner/runner.go | 1 + pkg/httpserver/headerlayer.go | 20 +++++++++++ pkg/httpserver/httpserver.go | 2 ++ 5 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 pkg/httpserver/headerlayer.go diff --git a/README.md b/README.md index 0363d59..bea47b3 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ This will display help for the tool. Here are all the switches it supports. | `-realm` | Basic auth message | `simplehttpserver -realm "insert the credentials"` | | `-version` | Show version | `simplehttpserver -version` | | `-silent` | Show only results | `simplehttpserver -silent` | +| `-header` | HTTP response header (can be used multiple times) | `simplehttpserver -header 'X-Powered-By: Go'` | ### Running simplehttpserver in the current folder diff --git a/internal/runner/options.go b/internal/runner/options.go index 5086d8a..8a96c3d 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -2,37 +2,40 @@ package runner import ( "flag" + "fmt" "os" "path/filepath" "strings" "github.com/projectdiscovery/gologger" "github.com/projectdiscovery/gologger/levels" + "github.com/projectdiscovery/simplehttpserver/pkg/httpserver" ) // Options of the tool type Options struct { - ListenAddress string - Folder string - BasicAuth string - username string - password string - Realm string - TLSCertificate string - TLSKey string - TLSDomain string - HTTPS bool - Verbose bool - EnableUpload bool - EnableTCP bool - RulesFile string - TCPWithTLS bool - Version bool - Silent bool - Sandbox bool - MaxFileSize int - HTTP1Only bool + ListenAddress string + Folder string + BasicAuth string + username string + password string + Realm string + TLSCertificate string + TLSKey string + TLSDomain string + HTTPS bool + Verbose bool + EnableUpload bool + EnableTCP bool + RulesFile string + TCPWithTLS bool + Version bool + Silent bool + Sandbox bool + MaxFileSize int + HTTP1Only bool MaxDumpBodySize int + HTTPHeaders HTTPHeaders } // ParseOptions parses the command line options for application @@ -61,6 +64,7 @@ func ParseOptions() *Options { flag.BoolVar(&options.HTTP1Only, "http1", false, "Enable only HTTP1") flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") flag.IntVar(&options.MaxDumpBodySize, "max-dump-body-size", -1, "Max Dump Body Size") + flag.Var(&options.HTTPHeaders, "header", "Add HTTP Response Header (name: value), can be used multiple times") flag.Parse() // Read the inputs and configure the logging @@ -113,3 +117,21 @@ func (options *Options) FolderAbsPath() string { } return abspath } + +// HTTPHeaders is a slice of HTTPHeader structs +type HTTPHeaders []httpserver.HTTPHeader + +func (h *HTTPHeaders) String() string { + return fmt.Sprint(*h) +} + +// Set sets a new header, which must be a string of the form 'name: value' +func (h *HTTPHeaders) Set(value string) error { + tokens := strings.SplitN(value, ":", 2) + if len(tokens) != 2 { + return fmt.Errorf("header '%s' not in format 'name: value'", value) + } + + *h = append(*h, httpserver.HTTPHeader{Name: tokens[0], Value: tokens[1]}) + return nil +} diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 59c28e3..de0c266 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -68,6 +68,7 @@ func New(options *Options) (*Runner, error) { MaxFileSize: r.options.MaxFileSize, HTTP1Only: r.options.HTTP1Only, MaxDumpBodySize: unit.ToMb(r.options.MaxDumpBodySize), + HTTPHeaders: r.options.HTTPHeaders, }) if err != nil { return nil, err diff --git a/pkg/httpserver/headerlayer.go b/pkg/httpserver/headerlayer.go new file mode 100644 index 0000000..0a0dac7 --- /dev/null +++ b/pkg/httpserver/headerlayer.go @@ -0,0 +1,20 @@ +package httpserver + +import ( + "net/http" +) + +// HTTPHeader represents an HTTP header +type HTTPHeader struct { + Name string + Value string +} + +func (t *HTTPServer) headerlayer(handler http.Handler, headers []HTTPHeader) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + for _, header := range headers { + w.Header().Set(header.Name, header.Value) + } + handler.ServeHTTP(w, r) + }) +} diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 94c050e..a41e9eb 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -27,6 +27,7 @@ type Options struct { HTTP1Only bool MaxFileSize int // 50Mb MaxDumpBodySize int64 + HTTPHeaders []HTTPHeader } // HTTPServer instance @@ -72,6 +73,7 @@ func New(options *Options) (*HTTPServer, error) { } httpHandler = h.loglayer(httpHandler) + httpHandler = h.headerlayer(httpHandler, options.HTTPHeaders) // add handler h.layers = httpHandler From fb24d6b2b60e069d5365f351bda09d9df3428079 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 12:07:46 +0000 Subject: [PATCH 102/121] chore(deps): bump golang from 1.18-alpine to 1.19.1-alpine Bumps golang from 1.18-alpine to 1.19.1-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2250723..1c09cc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as build-env +FROM golang:1.19.1-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From 6f6e3ac341f7d9b138910dd99dab898b75cf3386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 12:08:01 +0000 Subject: [PATCH 103/121] chore(deps): bump golang from 1.19.1-alpine to 1.19.2-alpine Bumps golang from 1.19.1-alpine to 1.19.2-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1c09cc5..06c63b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.1-alpine as build-env +FROM golang:1.19.2-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From 274994dd5b22f9c56b7412e4d90d4a770d895862 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 17:40:35 +0530 Subject: [PATCH 104/121] chore(deps): bump github.com/fsnotify/fsnotify from 1.5.4 to 1.6.0 (#90) Bumps [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify) from 1.5.4 to 1.6.0. - [Release notes](https://github.com/fsnotify/fsnotify/releases) - [Changelog](https://github.com/fsnotify/fsnotify/blob/main/CHANGELOG.md) - [Commits](https://github.com/fsnotify/fsnotify/compare/v1.5.4...v1.6.0) --- updated-dependencies: - dependency-name: github.com/fsnotify/fsnotify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f01e559..abe2135 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/projectdiscovery/simplehttpserver go 1.17 require ( - github.com/fsnotify/fsnotify v1.5.4 + github.com/fsnotify/fsnotify v1.6.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/projectdiscovery/gologger v1.1.4 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e @@ -15,5 +15,5 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect ) diff --git a/go.sum b/go.sum index d3940da..163258b 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -33,8 +33,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From a0e5af313aaaaf5861856ba23c1391df3dcdc24f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 12:05:49 +0000 Subject: [PATCH 105/121] chore(deps): bump golangci/golangci-lint-action from 3.2.0 to 3.3.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index d8b1dbc..52adfef 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3.2.0 + uses: golangci/golangci-lint-action@v3.3.0 with: version: latest args: --timeout 5m From 07e7ba8ab0d9f59c82ea1933f3a11e7f2b5360c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 12:00:58 +0000 Subject: [PATCH 106/121] chore(deps): bump golang from 1.19.2-alpine to 1.19.3-alpine Bumps golang from 1.19.2-alpine to 1.19.3-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 06c63b3..dccfd2d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.2-alpine as build-env +FROM golang:1.19.3-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From eac84be90de8da77bf8837d51f419e7d5aa9de53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:49:08 +0530 Subject: [PATCH 107/121] chore(deps): bump golang from 1.19.3-alpine to 1.19.5-alpine (#99) Bumps golang from 1.19.3-alpine to 1.19.5-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dccfd2d..11d642b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.3-alpine as build-env +FROM golang:1.19.5-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From 98c930112c9045465040202c841438c9d2b3f190 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:49:20 +0530 Subject: [PATCH 108/121] chore(deps): bump github.com/projectdiscovery/gologger (#98) Bumps [github.com/projectdiscovery/gologger](https://github.com/projectdiscovery/gologger) from 1.1.4 to 1.1.7. - [Release notes](https://github.com/projectdiscovery/gologger/releases) - [Commits](https://github.com/projectdiscovery/gologger/compare/v1.1.4...v1.1.7) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/gologger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++++++--- go.sum | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index abe2135..2752bf8 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,23 @@ go 1.17 require ( github.com/fsnotify/fsnotify v1.6.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 - github.com/projectdiscovery/gologger v1.1.4 + github.com/projectdiscovery/gologger v1.1.7 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e gopkg.in/yaml.v2 v2.4.0 ) require ( - github.com/json-iterator/go v1.1.10 // indirect + github.com/dsnet/compress v0.0.1 // indirect + github.com/golang/snappy v0.0.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/mholt/archiver v3.1.1+incompatible // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/nwaples/rardecode v1.1.0 // indirect + github.com/pierrec/lz4 v2.6.0+incompatible // indirect + github.com/ulikunitz/xz v0.5.7 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect + gopkg.in/djherbis/times.v1 v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 163258b..5e64a77 100644 --- a/go.sum +++ b/go.sum @@ -2,11 +2,22 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -15,29 +26,43 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= +github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A= +github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/projectdiscovery/gologger v1.1.4 h1:qWxGUq7ukHWT849uGPkagPKF3yBPYAsTtMKunQ8O2VI= -github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY= +github.com/projectdiscovery/gologger v1.1.7 h1:QeByO4NR8vlZ5ZM2XIOJARRj5WOOU5Ix35FBQ1iH5Rk= +github.com/projectdiscovery/gologger v1.1.7/go.mod h1:bNyVaC1U/NpJtFkJltcesn01NR3K8Hg6RsLVce6yvrw= github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e h1:IZa08TUGbU7I0HUb9QQt/8wuu2fPZqfnMXwWhtMxei8= github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e/go.mod h1:jSp8W5zIkNPxAqVdcoFlfv0K5cqogTe65fMinR0Fvuk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.7 h1:YvTNdFzX6+W5m9msiYg/zpkSURPPtOlzbqYjrFn7Yt4= +github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o= +gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From ee16c987977ce2e05aabbb484caec89884df950d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:49:32 +0530 Subject: [PATCH 109/121] chore(deps): bump goreleaser/goreleaser-action from 3 to 4 (#97) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3 to 4. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/v3...v4) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-binary.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index feec85f..47d6b4b 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -18,7 +18,7 @@ jobs: with: fetch-depth: 0 - name: "Create release on GitHub" - uses: goreleaser/goreleaser-action@v3 + uses: goreleaser/goreleaser-action@v4 env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" with: From d9c30c239b5bad74d4c8edcdb09c812f0e4fc258 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:49:43 +0530 Subject: [PATCH 110/121] chore(deps): bump golangci/golangci-lint-action from 3.3.0 to 3.3.1 (#94) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.3.0...v3.3.1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 52adfef..b976c14 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3.3.0 + uses: golangci/golangci-lint-action@v3.3.1 with: version: latest args: --timeout 5m From 1afbebcb34879a51ee0bacff0a2b9864ec0aea1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 12:01:29 +0000 Subject: [PATCH 111/121] chore(deps): bump golangci/golangci-lint-action from 3.3.1 to 3.4.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.3.1 to 3.4.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.3.1...v3.4.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index b976c14..994c36b 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint - uses: golangci/golangci-lint-action@v3.3.1 + uses: golangci/golangci-lint-action@v3.4.0 with: version: latest args: --timeout 5m From ef45d43958256c05723e5199318dd9079147880f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 12:01:01 +0000 Subject: [PATCH 112/121] chore(deps): bump docker/build-push-action from 3 to 4 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 4. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v3...v4) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dockerhub-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index d81a409..829fefb 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -26,7 +26,7 @@ jobs: password: ${{ secrets.DOCKER_TOKEN }} - name: Build and push - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . platforms: linux/amd64,linux/arm64,linux/arm From 05dd808e129368a31f51ce3e8393d7b64d0fa354 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 12:01:06 +0000 Subject: [PATCH 113/121] chore(deps): bump golang from 1.19.5-alpine to 1.20.0-alpine Bumps golang from 1.19.5-alpine to 1.20.0-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 11d642b..9c1c965 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.5-alpine as build-env +FROM golang:1.20.0-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From 376099aaefadf0af91515aec0a5838b0369b45fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:14:29 +0530 Subject: [PATCH 114/121] chore(deps): bump github.com/projectdiscovery/gologger (#103) Bumps [github.com/projectdiscovery/gologger](https://github.com/projectdiscovery/gologger) from 1.1.7 to 1.1.8. - [Release notes](https://github.com/projectdiscovery/gologger/releases) - [Commits](https://github.com/projectdiscovery/gologger/compare/v1.1.7...v1.1.8) --- updated-dependencies: - dependency-name: github.com/projectdiscovery/gologger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2752bf8..fd4d53b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/fsnotify/fsnotify v1.6.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 - github.com/projectdiscovery/gologger v1.1.7 + github.com/projectdiscovery/gologger v1.1.8 github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 5e64a77..866d4e0 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDm github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/projectdiscovery/gologger v1.1.7 h1:QeByO4NR8vlZ5ZM2XIOJARRj5WOOU5Ix35FBQ1iH5Rk= -github.com/projectdiscovery/gologger v1.1.7/go.mod h1:bNyVaC1U/NpJtFkJltcesn01NR3K8Hg6RsLVce6yvrw= +github.com/projectdiscovery/gologger v1.1.8 h1:CFlCzGlqAhPqWIrAXBt1OVh5jkMs1qgoR/z4xhdzLNE= +github.com/projectdiscovery/gologger v1.1.8/go.mod h1:bNyVaC1U/NpJtFkJltcesn01NR3K8Hg6RsLVce6yvrw= github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e h1:IZa08TUGbU7I0HUb9QQt/8wuu2fPZqfnMXwWhtMxei8= github.com/projectdiscovery/sslcert v0.0.0-20210416140253-8f56bec1bb5e/go.mod h1:jSp8W5zIkNPxAqVdcoFlfv0K5cqogTe65fMinR0Fvuk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 32ea075cad4c0c5a52a1b20193a942d34cb0a2a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 20:14:46 +0530 Subject: [PATCH 115/121] chore(deps): bump golang from 1.20.0-alpine to 1.20.2-alpine (#105) Bumps golang from 1.20.0-alpine to 1.20.2-alpine. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9c1c965..cbcb4d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.0-alpine as build-env +FROM golang:1.20.2-alpine as build-env RUN go install -v github.com/projectdiscovery/simplehttpserver/cmd/simplehttpserver@latest FROM alpine:latest From d564b6e23f6b20551f922eb212337a25cd8bb81a Mon Sep 17 00:00:00 2001 From: NoF0rte <64100993+NoF0rte@users.noreply.github.com> Date: Wed, 15 Mar 2023 06:15:46 -0600 Subject: [PATCH 116/121] Adding a very simple CORS implementation (#93) * Added a very simple CORS implementation * Update header add location --------- Co-authored-by: Sandeep Singh Co-authored-by: NoF0rte Co-authored-by: shubhamrasal --- internal/runner/options.go | 2 ++ internal/runner/runner.go | 1 + pkg/httpserver/corslayer.go | 28 ++++++++++++++++++++++++++++ pkg/httpserver/httpserver.go | 5 +++++ 4 files changed, 36 insertions(+) create mode 100644 pkg/httpserver/corslayer.go diff --git a/internal/runner/options.go b/internal/runner/options.go index 8a96c3d..2e99cf1 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -35,6 +35,7 @@ type Options struct { MaxFileSize int HTTP1Only bool MaxDumpBodySize int + CORS bool HTTPHeaders HTTPHeaders } @@ -64,6 +65,7 @@ func ParseOptions() *Options { flag.BoolVar(&options.HTTP1Only, "http1", false, "Enable only HTTP1") flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") flag.IntVar(&options.MaxDumpBodySize, "max-dump-body-size", -1, "Max Dump Body Size") + flag.BoolVar(&options.CORS, "cors", false, "Enable Cross-Origin Resource Sharing (CORS)") flag.Var(&options.HTTPHeaders, "header", "Add HTTP Response Header (name: value), can be used multiple times") flag.Parse() diff --git a/internal/runner/runner.go b/internal/runner/runner.go index de0c266..e7ea127 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -68,6 +68,7 @@ func New(options *Options) (*Runner, error) { MaxFileSize: r.options.MaxFileSize, HTTP1Only: r.options.HTTP1Only, MaxDumpBodySize: unit.ToMb(r.options.MaxDumpBodySize), + CORS: r.options.CORS, HTTPHeaders: r.options.HTTPHeaders, }) if err != nil { diff --git a/pkg/httpserver/corslayer.go b/pkg/httpserver/corslayer.go new file mode 100644 index 0000000..70549d0 --- /dev/null +++ b/pkg/httpserver/corslayer.go @@ -0,0 +1,28 @@ +package httpserver + +import ( + "net/http" + "strings" +) + +func (t *HTTPServer) corslayer(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + headers := w.Header() + headers.Set("Access-Control-Allow-Origin", "*") + if r.Method != http.MethodOptions { + handler.ServeHTTP(w, r) + return + } + + headers.Add("Vary", "Origin") + headers.Add("Vary", "Access-Control-Request-Method") + headers.Add("Vary", "Access-Control-Request-Headers") + + reqMethod := r.Header.Get("Access-Control-Request-Method") + if reqMethod != "" { + headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod)) + } + + w.WriteHeader(http.StatusOK) + }) +} diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index a41e9eb..4dd6682 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -27,6 +27,7 @@ type Options struct { HTTP1Only bool MaxFileSize int // 50Mb MaxDumpBodySize int64 + CORS bool HTTPHeaders []HTTPHeader } @@ -72,6 +73,10 @@ func New(options *Options) (*HTTPServer, error) { addHandler(h.basicauthlayer) } + if options.CORS { + addHandler(h.corslayer) + } + httpHandler = h.loglayer(httpHandler) httpHandler = h.headerlayer(httpHandler, options.HTTPHeaders) From e5e0814873f00c2c0c2d47c7741372667d187d3e Mon Sep 17 00:00:00 2001 From: Li BingMuyou <77159535+li6in9muyou@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:08:06 +0800 Subject: [PATCH 117/121] Add DOCTYPE, header and similar list style as that of python's (#106) * feat: use same page style as python's * test: pythonliststyle_test.go * refactor: make it clearer that we surround original html with proper header and footer * refactor: explain what these lines do * fix: html title is not updated as URL path changes * doc: explain what this fork is for * doc: typo * test: serve a file * fix: file is not served properly * reword * lint: accept gosimple's suggestion * fix: handles any os.Stat() error * made python style optional --------- Co-authored-by: Sandeep Singh Co-authored-by: Mzack9999 --- README.md | 1 + internal/runner/options.go | 2 + internal/runner/runner.go | 1 + pkg/httpserver/httpserver.go | 9 +- pkg/httpserver/pythonliststyle.go | 96 ++++++++++++++++++++++ pkg/httpserver/uploadlayer.go | 2 +- test/fixture/pythonliststyle/test file.txt | 2 + test/pythonliststyle_test.go | 75 +++++++++++++++++ 8 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 pkg/httpserver/pythonliststyle.go create mode 100644 test/fixture/pythonliststyle/test file.txt create mode 100644 test/pythonliststyle_test.go diff --git a/README.md b/README.md index bea47b3..769daa9 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ This will display help for the tool. Here are all the switches it supports. | `-realm` | Basic auth message | `simplehttpserver -realm "insert the credentials"` | | `-version` | Show version | `simplehttpserver -version` | | `-silent` | Show only results | `simplehttpserver -silent` | +| `-py` | Emulate Python Style | `simplehttpserver -py` | | `-header` | HTTP response header (can be used multiple times) | `simplehttpserver -header 'X-Powered-By: Go'` | ### Running simplehttpserver in the current folder diff --git a/internal/runner/options.go b/internal/runner/options.go index 2e99cf1..2890a04 100644 --- a/internal/runner/options.go +++ b/internal/runner/options.go @@ -35,6 +35,7 @@ type Options struct { MaxFileSize int HTTP1Only bool MaxDumpBodySize int + Python bool CORS bool HTTPHeaders HTTPHeaders } @@ -65,6 +66,7 @@ func ParseOptions() *Options { flag.BoolVar(&options.HTTP1Only, "http1", false, "Enable only HTTP1") flag.IntVar(&options.MaxFileSize, "max-file-size", 50, "Max Upload File Size") flag.IntVar(&options.MaxDumpBodySize, "max-dump-body-size", -1, "Max Dump Body Size") + flag.BoolVar(&options.Python, "py", false, "Emulate Python Style") flag.BoolVar(&options.CORS, "cors", false, "Enable Cross-Origin Resource Sharing (CORS)") flag.Var(&options.HTTPHeaders, "header", "Add HTTP Response Header (name: value), can be used multiple times") flag.Parse() diff --git a/internal/runner/runner.go b/internal/runner/runner.go index e7ea127..dc63940 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -68,6 +68,7 @@ func New(options *Options) (*Runner, error) { MaxFileSize: r.options.MaxFileSize, HTTP1Only: r.options.HTTP1Only, MaxDumpBodySize: unit.ToMb(r.options.MaxDumpBodySize), + Python: r.options.Python, CORS: r.options.CORS, HTTPHeaders: r.options.HTTPHeaders, }) diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 4dd6682..5dd65a6 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -27,6 +27,7 @@ type Options struct { HTTP1Only bool MaxFileSize int // 50Mb MaxDumpBodySize int64 + Python bool CORS bool HTTPHeaders []HTTPHeader } @@ -59,7 +60,13 @@ func New(options *Options) (*HTTPServer, error) { dir = SandboxFileSystem{fs: http.Dir(options.Folder), RootFolder: options.Folder} } - httpHandler := http.FileServer(dir) + var httpHandler http.Handler + if options.Python { + httpHandler = PythonStyle(dir.(http.Dir)) + } else { + httpHandler = http.FileServer(dir) + } + addHandler := func(newHandler Middleware) { httpHandler = newHandler(httpHandler) } diff --git a/pkg/httpserver/pythonliststyle.go b/pkg/httpserver/pythonliststyle.go new file mode 100644 index 0000000..65c6b0a --- /dev/null +++ b/pkg/httpserver/pythonliststyle.go @@ -0,0 +1,96 @@ +package httpserver + +import ( + "bytes" + "fmt" + "io" + "net/http" + "os" + "path/filepath" +) + +const ( + preTag = "
"
+	preTagClose = "
" + aTag = " + + + +Directory listing for %s + + +` + htmlFooter = `
+ + +` +) + +type pythonStyleHandler struct { + origWriter http.ResponseWriter + root http.Dir +} + +func (h *pythonStyleHandler) Header() http.Header { + return h.origWriter.Header() +} + +func (h *pythonStyleHandler) writeListItem(b []byte, written *int) { + var i int + i, _ = fmt.Fprint(h.origWriter, "
  • ") + *written += i + i, _ = h.origWriter.Write(bytes.Trim(b, "\r\n")) + *written += i + i, _ = fmt.Fprint(h.origWriter, "
  • \n") + *written += i +} + +func (h *pythonStyleHandler) Write(b []byte) (int, error) { + var i int + written := 0 + + if bytes.HasPrefix(b, []byte(preTag)) { + _, _ = io.Discard.Write(b) + i, _ = fmt.Fprintln(h.origWriter, "
      ") + written += i + return written, nil + } + if bytes.HasPrefix(b, []byte(preTagClose)) { + _, _ = io.Discard.Write(b) + i, _ = fmt.Fprintln(h.origWriter, "
    ") + written += i + return written, nil + } + + if bytes.HasPrefix(b, []byte(aTag)) { + h.writeListItem(b, &written) + } + return i, nil +} + +func (h *pythonStyleHandler) WriteHeader(statusCode int) { + h.origWriter.WriteHeader(statusCode) +} + +func (h *pythonStyleHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { + target := filepath.Join(string(h.root), filepath.Clean(request.URL.Path)) + file, err := os.Stat(target) + + if err != nil || !file.IsDir() { + http.ServeFile(writer, request, target) + return + } else { + _, _ = fmt.Fprintf(writer, htmlHeader, request.URL.Path) + _, _ = fmt.Fprintf(writer, "

    Directory listing for %s

    \n
    \n", request.URL.Path) + h.origWriter = writer + http.ServeFile(h, request, target) + _, _ = fmt.Fprint(writer, htmlFooter) + } +} + +func PythonStyle(root http.Dir) http.Handler { + return &pythonStyleHandler{ + root: root, + } +} diff --git a/pkg/httpserver/uploadlayer.go b/pkg/httpserver/uploadlayer.go index 670d75a..4064714 100644 --- a/pkg/httpserver/uploadlayer.go +++ b/pkg/httpserver/uploadlayer.go @@ -91,7 +91,7 @@ func handleUpload(base, file string, data []byte) error { } trustedPath := untrustedPath - if _, err := os.Stat(path.Dir(trustedPath)); os.IsNotExist(err) { + if _, err := os.Stat(filepath.Dir(trustedPath)); os.IsNotExist(err) { return errors.New("invalid path") } diff --git a/test/fixture/pythonliststyle/test file.txt b/test/fixture/pythonliststyle/test file.txt new file mode 100644 index 0000000..5cd8fbc --- /dev/null +++ b/test/fixture/pythonliststyle/test file.txt @@ -0,0 +1,2 @@ +This is the content of "test file.txt". +这是“test file.txt”文件的内容。 diff --git a/test/pythonliststyle_test.go b/test/pythonliststyle_test.go new file mode 100644 index 0000000..1826c8e --- /dev/null +++ b/test/pythonliststyle_test.go @@ -0,0 +1,75 @@ +package test + +import ( + "bytes" + "github.com/projectdiscovery/simplehttpserver/pkg/httpserver" + "io" + "net/http/httptest" + "os" + "strings" + "testing" +) + +func TestServePythonStyleHtmlPageForDirectories(t *testing.T) { + const want = ` + + + +Directory listing for / + + +

    Directory listing for /

    +
    + +
    + + +` + py := httpserver.PythonStyle("./fixture/pythonliststyle") + + w := httptest.NewRecorder() + py.ServeHTTP(w, httptest.NewRequest("GET", "http://example.com/", nil)) + b, _ := io.ReadAll(w.Result().Body) + + body := string(b) + if strings.Compare(want, body) != 0 { + t.Errorf("want:\n%s\ngot:\n%s", want, body) + } +} + +func TestServeFileContentForFiles(t *testing.T) { + want, _ := os.ReadFile("./fixture/pythonliststyle/test file.txt") + + py := httpserver.PythonStyle("./fixture/pythonliststyle") + + w := httptest.NewRecorder() + py.ServeHTTP(w, httptest.NewRequest( + "GET", + "http://example.com/test%20file.txt", + nil, + )) + got, _ := io.ReadAll(w.Result().Body) + if !bytes.Equal(want, got) { + t.Errorf("want:\n%x\ngot:\n%x", want, got) + } +} + +func TestResponseNotFound(t *testing.T) { + const want = `404 page not found +` + + py := httpserver.PythonStyle("./fixture/pythonliststyle") + + w := httptest.NewRecorder() + py.ServeHTTP(w, httptest.NewRequest( + "GET", + "http://example.com/does-not-exist.txt", + nil, + )) + got, _ := io.ReadAll(w.Result().Body) + if strings.Compare(want, string(got)) != 0 { + t.Errorf("want:\n%s\ngot:\n%s", want, got) + } +} From 89378e4a4b0c7f620e20bdb7d302aa6e9c714a64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 19:38:25 +0530 Subject: [PATCH 118/121] chore(deps): bump actions/setup-go from 3 to 4 (#107) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-test.yml | 2 +- .github/workflows/lint-test.yml | 2 +- .github/workflows/release-binary.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 00cd9ee..69a6eea 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.18 diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 994c36b..2a22228 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.18 - name: Checkout code diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index 47d6b4b..602f907 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: "Set up Go" - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.18 - name: "Check out code" From 0bc13a6bf73fbed91323e57e72342303c02562b4 Mon Sep 17 00:00:00 2001 From: Sandeep Singh Date: Mon, 20 Mar 2023 20:25:38 +0530 Subject: [PATCH 119/121] workflow update (#108) * workflow update * readme update * use os and io pkg to read/write file --------- Co-authored-by: Ramana Reddy --- .github/workflows/build-test.yml | 7 +++++-- .github/workflows/codeql-analysis.yml | 3 +++ .github/workflows/dockerhub-push.yml | 6 ++++-- .github/workflows/lint-test.yml | 7 +++++-- .github/workflows/release-binary.yml | 8 ++++++-- .goreleaser.yml | 28 ++++++++++++++++++++------- README.md | 1 + go.mod | 2 +- internal/runner/banner.go | 7 ++----- pkg/httpserver/uploadlayer.go | 6 +++--- pkg/tcpserver/tcpserver.go | 4 ++-- 11 files changed, 53 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 69a6eea..c9baa4e 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,7 +1,10 @@ name: 🔨 Build Test + on: - push: pull_request: + paths: + - '**.go' + - '**.mod' workflow_dispatch: @@ -13,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.18 + go-version: 1.19 - name: Check out code uses: actions/checkout@v3 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9f533f8..2863865 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,6 +3,9 @@ name: 🚨 CodeQL Analysis on: workflow_dispatch: pull_request: + paths: + - '**.go' + - '**.mod' branches: - dev diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 829fefb..d141bff 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -1,8 +1,10 @@ name: 🌥 Docker Push on: - release: - types: [published] + workflow_run: + workflows: ["🎉 Release Binary"] + types: + - completed workflow_dispatch: jobs: diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 2a22228..7f4c078 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -1,7 +1,10 @@ name: 🙏🏻 Lint Test + on: - push: pull_request: + paths: + - '**.go' + - '**.mod' workflow_dispatch: jobs: @@ -12,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.18 + go-version: 1.19 - name: Checkout code uses: actions/checkout@v3 - name: Run golangci-lint diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml index 602f907..8581b0b 100644 --- a/.github/workflows/release-binary.yml +++ b/.github/workflows/release-binary.yml @@ -1,6 +1,7 @@ name: 🎉 Release Binary + on: - create: + push: tags: - v* workflow_dispatch: @@ -12,7 +13,7 @@ jobs: - name: "Set up Go" uses: actions/setup-go@v4 with: - go-version: 1.18 + go-version: 1.19 - name: "Check out code" uses: actions/checkout@v3 with: @@ -21,6 +22,9 @@ jobs: uses: goreleaser/goreleaser-action@v4 env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}" + DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}" + DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}" with: args: "release --rm-dist" version: latest diff --git a/.goreleaser.yml b/.goreleaser.yml index f6cb1e2..e0a4795 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,3 +1,7 @@ +before: + hooks: + - go mod tidy + builds: - binary: simplehttpserver main: cmd/simplehttpserver/simplehttpserver.go @@ -12,10 +16,20 @@ builds: - arm64 archives: - - id: tgz - format: tar.gz - replacements: - darwin: macOS - format_overrides: - - goos: windows - format: zip \ No newline at end of file +- format: zip + replacements: + darwin: macOS + +checksum: + algorithm: sha256 + +announce: + slack: + enabled: true + channel: '#release' + username: GoReleaser + message_template: 'New Release: {{ .ProjectName }} {{ .Tag }} is published! Check it out at {{ .ReleaseURL }}' + + discord: + enabled: true + message_template: '**New Release: {{ .ProjectName }} {{.Tag}}** is published! Check it out at {{ .ReleaseURL }}' \ No newline at end of file diff --git a/README.md b/README.md index 769daa9..709e1ac 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ This will display help for the tool. Here are all the switches it supports. | `-cert` | HTTPS/TLS certificate (self generated if not specified) | `simplehttpserver -cert cert.pem` | | `-key` | HTTPS/TLS certificate private key | `simplehttpserver -key cert.key` | | `-domain` | Domain name to use for the self-generated certificate | `simplehttpserver -domain projectdiscovery.io` | +| `-cors` | Enable cross-origin resource sharing (CORS) | `simplehttpserver -cors` | | `-basic-auth` | Basic auth (username:password) | `simplehttpserver -basic-auth user:password` | | `-realm` | Basic auth message | `simplehttpserver -realm "insert the credentials"` | | `-version` | Show version | `simplehttpserver -version` | diff --git a/go.mod b/go.mod index fd4d53b..01a2ea1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectdiscovery/simplehttpserver -go 1.17 +go 1.19 require ( github.com/fsnotify/fsnotify v1.6.0 diff --git a/internal/runner/banner.go b/internal/runner/banner.go index 24febe0..ed4193f 100644 --- a/internal/runner/banner.go +++ b/internal/runner/banner.go @@ -8,17 +8,14 @@ const banner = ` \__ \/ / __ -__ \/ __ \/ / _ \/ /_/ / / / / / / /_/ / ___/ _ \/ ___/ | / / _ \/ ___/ ___/ / / / / / / / /_/ / / __/ __ / / / / / / ____(__ ) __/ / | |/ / __/ / /____/_/_/ /_/ /_/ .___/_/\___/_/ /_/ /_/ /_/ /_/ /____/\___/_/ |___/\___/_/ - /_/ - v0.0.5 + /_/ - v0.0.6 ` // Version is the current version -const Version = `0.0.5` +const Version = `0.0.6` // showBanner is used to show the banner to the user func showBanner() { gologger.Print().Msgf("%s\n", banner) gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n") - - gologger.Print().Msgf("Use with caution. You are responsible for your actions\n") - gologger.Print().Msgf("Developers assume no liability and are not responsible for any misuse or damage.\n") } diff --git a/pkg/httpserver/uploadlayer.go b/pkg/httpserver/uploadlayer.go index 4064714..571d3c1 100644 --- a/pkg/httpserver/uploadlayer.go +++ b/pkg/httpserver/uploadlayer.go @@ -2,7 +2,7 @@ package httpserver import ( "errors" - "io/ioutil" + "io" "net/http" "os" "path" @@ -55,7 +55,7 @@ func (t *HTTPServer) uploadlayer(handler http.Handler) http.Handler { r.Body = http.MaxBytesReader(w, r.Body, maxFileSize) } - data, err = ioutil.ReadAll(r.Body) + data, err = io.ReadAll(r.Body) if err != nil { gologger.Print().Msgf("%s\n", err) w.WriteHeader(http.StatusInternalServerError) @@ -95,5 +95,5 @@ func handleUpload(base, file string, data []byte) error { return errors.New("invalid path") } - return ioutil.WriteFile(trustedPath, data, 0655) + return os.WriteFile(trustedPath, data, 0655) } diff --git a/pkg/tcpserver/tcpserver.go b/pkg/tcpserver/tcpserver.go index cbdd407..3b996f5 100644 --- a/pkg/tcpserver/tcpserver.go +++ b/pkg/tcpserver/tcpserver.go @@ -4,7 +4,7 @@ import ( "context" "crypto/tls" "errors" - "io/ioutil" + "os" "net" "sync" "time" @@ -146,7 +146,7 @@ func (t *TCPServer) Close() error { // LoadTemplate from yaml func (t *TCPServer) LoadTemplate(templatePath string) error { var config RulesConfiguration - yamlFile, err := ioutil.ReadFile(templatePath) + yamlFile, err := os.ReadFile(templatePath) if err != nil { return err } From 4ef352de6cb325a5f84f5b9bc0561bb0bc112220 Mon Sep 17 00:00:00 2001 From: brenocss <57222005+brenocss@users.noreply.github.com> Date: Wed, 5 Apr 2023 03:15:16 -0300 Subject: [PATCH 120/121] Update README.md (#113) mistype -rules --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 709e1ac..8d087ae 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ curl -v --user 'root:root' --upload-file file.txt http://localhost:8000/file.txt This will run the tool as TLS TCP server and enable custom responses based on YAML templates: ```sh -simplehttpserver -rule rules.yaml -tcp -tls -domain localhost +simplehttpserver -rules rules.yaml -tcp -tls -domain localhost ``` The rules are written as follows: From 9862845b558ac5b993e94dc7bbd7e543967b89df Mon Sep 17 00:00:00 2001 From: Ivan Latunov Date: Wed, 26 Jul 2023 03:22:35 +0300 Subject: [PATCH 121/121] pythonliststyle: Add viewport meta tag (#121) This makes the rendered HTML appear equally-sized on both mobile and desktop displays Co-authored-by: Ivan Latunov --- pkg/httpserver/pythonliststyle.go | 1 + test/pythonliststyle_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/httpserver/pythonliststyle.go b/pkg/httpserver/pythonliststyle.go index 65c6b0a..ee6342f 100644 --- a/pkg/httpserver/pythonliststyle.go +++ b/pkg/httpserver/pythonliststyle.go @@ -17,6 +17,7 @@ const ( + Directory listing for %s diff --git a/test/pythonliststyle_test.go b/test/pythonliststyle_test.go index 1826c8e..0ee449a 100644 --- a/test/pythonliststyle_test.go +++ b/test/pythonliststyle_test.go @@ -15,6 +15,7 @@ func TestServePythonStyleHtmlPageForDirectories(t *testing.T) { + Directory listing for /