Skip to content

Commit

Permalink
Add (optional) protection against csrf attacks
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelreyna committed Apr 15, 2021
1 parent 32f18ee commit a67e611
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 182 deletions.
270 changes: 138 additions & 132 deletions README.md

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions cmd/conf/configuration.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package conf

import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"strings"
"time"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

const (
Expand All @@ -22,7 +23,7 @@ type Conf struct {
NoInfo bool
NoError bool
Port string
Host string
Host string
Timeout time.Duration
NoDownload bool

Expand Down Expand Up @@ -56,7 +57,7 @@ type Conf struct {
ShellCommand bool
Shell string // only used if shellCommand != ""

Redirect bool
Redirect bool
RedirectStatus int

ReplaceHeaders bool // only valid if cgi is true or shellCommand != ""
Expand All @@ -70,6 +71,9 @@ type Conf struct {

AllowBots bool

NoCSRFToken bool
CustomCSRFToken string

cmdFlagSet *pflag.FlagSet

sstlsLoc string
Expand Down
10 changes: 10 additions & 0 deletions cmd/conf/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,14 @@ See also: --status-code`,
This flag does nothing if not redirecting to a different URL.
See also: -r, --redirect`,
)

flags.BoolVar(&c.NoCSRFToken, "no-csrf-token", false, `Use a CSRF token for uploading.
This flag does nothing if both the -u, --upload and --upload-input flags are not set.
See also: -u, --upload; --upload-input`,
)

flags.StringVar(&c.CustomCSRFToken, "custom-csrf-token", "", `Use a custom CSRF token for uploading.
This flag does nothing if both the -u, --upload and --upload-input flags are not set.
See also: -u, --upload; --upload-input; --no-csrf-token`,
)
}
61 changes: 37 additions & 24 deletions cmd/conf/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"
"text/template"

"github.com/google/uuid"
"github.com/raphaelreyna/oneshot/internal/file"
"github.com/raphaelreyna/oneshot/internal/handlers"
"github.com/raphaelreyna/oneshot/internal/server"
Expand Down Expand Up @@ -69,64 +70,76 @@ func (c *Conf) setupUploadRoute(args []string, srvr *server.Server) (*server.Rou
route.MaxOK = 1
}

base := `<!DOCTYPE html>
base := `{{ define "base" }}<!DOCTYPE html>
<html>
<head>
<link rel="apple-touch-icon" href="/assets/icon.png">
<link rel="icon" type="image/png" href="/assets/icon.png">
</head>
<body>
{{ .FileSection }}
{{ if .InputSection }}
poop
{{ if .FileSection }}
<br/>OR<br/>
{{ template "file-section" .CSRFToken }}
{{ end }}
{{ .InputSection }}
{{ if .InputSection }}
{{ if .FileSection }}
<br/>OR<br/>
{{ end }}
{{ template "input-section" .CSRFToken }}
{{ end }}
</body>
</html>
{{ end }}
`

fileSection := `<form action="/" method="post" enctype="multipart/form-data">
fileSection := `{{ define "file-section" }}<form action="/" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf-token" value="{{ . }}">
<h5>Select a file to upload:</h5>
<input type="file" name="oneshot">
<br><br>
<input type="submit" value="Upload">
</form>`
</form>{{ end }}`

inputSection := `<form action="/" method="post">
inputSection := `{{ define "input-section" }}<form action="/" method="post">
<input type="hidden" name="csrf-token" value="{{ . }}">
<h5>Enter text to send: </h5>
<textarea name="oneshotTextUpload"></textarea>
<br><br>
<input type="submit" value="Upload">
</form>`
</form>{{ end }}`

tmpl, err := template.New("upload").Parse(base)
tmpl, err := template.New("file-section").Parse(fileSection)
if err != nil {
return nil, err
}
tmpl, err = tmpl.Parse(inputSection)
if err != nil {
return nil, err
}
tmpl, err = tmpl.Parse(base)
if err != nil {
return nil, err
}

sections := struct {
FileSection string
InputSection string
}{}

if c.Upload {
c.UploadFile = true
c.UploadInput = true
}
if c.UploadFile {
sections.FileSection = fileSection
FileSection bool
InputSection bool
CSRFToken string
}{
FileSection: true,
InputSection: true,
CSRFToken: c.CustomCSRFToken,
}
if c.UploadInput {
sections.InputSection = inputSection

if sections.CSRFToken == "" && !c.NoCSRFToken {
sections.CSRFToken = uuid.New().String()
}

getHandler := func(w http.ResponseWriter, r *http.Request) error {
tmpl.Execute(w, &sections)
tmpl.ExecuteTemplate(w, "base", &sections)
return server.OKNotDoneErr
}
postHandler := handlers.HandleUpload(file, !c.NoUnixNorm, srvr.InfoLog)
postHandler := handlers.HandleUpload(file, !c.NoUnixNorm, sections.CSRFToken, srvr.InfoLog)

infoLog := func(format string, v ...interface{}) {
if srvr.InfoLog != nil {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/raphaelreyna/oneshot
go 1.16

require (
github.com/google/uuid v1.2.0 // indirect
github.com/gorilla/mux v1.7.4
github.com/grandcat/zeroconf v1.0.0
github.com/jf-tech/iohelper v1.0.2
Expand Down

0 comments on commit a67e611

Please sign in to comment.