Merge pull request #59 from mutantmonkey/csp_referrer_fix
fix CSP referrer policy
This commit is contained in:
commit
ff1d9f56a1
|
@ -25,8 +25,8 @@ Command-line options
|
||||||
- ```-maxsize 4294967296``` maximum upload file size in bytes (default 4GB)
|
- ```-maxsize 4294967296``` maximum upload file size in bytes (default 4GB)
|
||||||
- ```-certfile path/to/your.crt``` -- Path to the ssl certificate (required if you want to use the https server)
|
- ```-certfile path/to/your.crt``` -- Path to the ssl certificate (required if you want to use the https server)
|
||||||
- ```-keyfile path/to/your.key``` -- Path to the ssl key (required if you want to use the https server)
|
- ```-keyfile path/to/your.key``` -- Path to the ssl key (required if you want to use the https server)
|
||||||
- ```-contentsecuritypolicy "..."``` -- Content-Security-Policy header for pages (default is "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; referrer none;")
|
- ```-contentsecuritypolicy "..."``` -- Content-Security-Policy header for pages (default is "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; referrer origin;")
|
||||||
- ```-filecontentsecuritypolicy "..."``` -- Content-Security-Policy header for files (default is "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; sandbox; referrer none;"")
|
- ```-filecontentsecuritypolicy "..."``` -- Content-Security-Policy header for files (default is "default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; sandbox; referrer origin;"")
|
||||||
- ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN")
|
- ```-xframeoptions "..." ``` -- X-Frame-Options header (default is "SAMEORIGIN")
|
||||||
- ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...)
|
- ```-remoteuploads``` -- (optionally) enable remote uploads (/upload?url=https://...)
|
||||||
- ```-realip``` -- (optionally) let linx-server know you (nginx, etc) are providing the X-Real-IP and/or X-Forwarded-For headers.
|
- ```-realip``` -- (optionally) let linx-server know you (nginx, etc) are providing the X-Real-IP and/or X-Forwarded-For headers.
|
||||||
|
|
12
csrf.go
12
csrf.go
|
@ -6,17 +6,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func strictReferrerCheck(r *http.Request, prefix string, whitelistHeaders []string) bool {
|
func strictReferrerCheck(r *http.Request, prefix string, whitelistHeaders []string) bool {
|
||||||
|
p := strings.TrimSuffix(prefix, "/")
|
||||||
|
if origin := r.Header.Get("Origin"); origin != "" {
|
||||||
|
// if there's an Origin header, check it and ignore the rest
|
||||||
|
return strings.HasPrefix(origin, p)
|
||||||
|
}
|
||||||
|
|
||||||
for _, header := range whitelistHeaders {
|
for _, header := range whitelistHeaders {
|
||||||
if r.Header.Get(header) != "" {
|
if r.Header.Get(header) != "" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if referrer := r.Header.Get("Referer"); !strings.HasPrefix(referrer, prefix) {
|
if referrer := r.Header.Get("Referer"); !strings.HasPrefix(referrer, p) {
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if origin := r.Header.Get("Origin"); origin != "" && !strings.HasPrefix(origin, strings.TrimSuffix(prefix, "/")) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ func fileServeHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if !Config.allowHotlink {
|
if !Config.allowHotlink {
|
||||||
referer := r.Header.Get("Referer")
|
referer := r.Header.Get("Referer")
|
||||||
if referer != "" && !strings.HasPrefix(referer, Config.siteURL) {
|
prefix := strings.TrimSuffix(Config.siteURL, "/")
|
||||||
|
if referer != "" && !strings.HasPrefix(referer, prefix) {
|
||||||
w.WriteHeader(403)
|
w.WriteHeader(403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
5
pages.go
5
pages.go
|
@ -86,7 +86,10 @@ func oopsHandler(c web.C, w http.ResponseWriter, r *http.Request, rt RespType, m
|
||||||
|
|
||||||
func badRequestHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func badRequestHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
err := Templates["400.html"].ExecuteWriter(pongo2.Context{}, w)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unauthorizedHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func unauthorizedHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -184,10 +184,10 @@ func main() {
|
||||||
flag.StringVar(&Config.remoteAuthFile, "remoteauthfile", "",
|
flag.StringVar(&Config.remoteAuthFile, "remoteauthfile", "",
|
||||||
"path to a file containing newline-separated scrypted auth keys for remote uploads")
|
"path to a file containing newline-separated scrypted auth keys for remote uploads")
|
||||||
flag.StringVar(&Config.contentSecurityPolicy, "contentsecuritypolicy",
|
flag.StringVar(&Config.contentSecurityPolicy, "contentsecuritypolicy",
|
||||||
"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; referrer none;",
|
"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; referrer origin;",
|
||||||
"value of default Content-Security-Policy header")
|
"value of default Content-Security-Policy header")
|
||||||
flag.StringVar(&Config.fileContentSecurityPolicy, "filecontentsecuritypolicy",
|
flag.StringVar(&Config.fileContentSecurityPolicy, "filecontentsecuritypolicy",
|
||||||
"default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; sandbox; referrer none;",
|
"default-src 'none'; img-src 'self'; object-src 'self'; media-src 'self'; sandbox; referrer origin;",
|
||||||
"value of Content-Security-Policy header for file access")
|
"value of Content-Security-Policy header for file access")
|
||||||
flag.StringVar(&Config.xFrameOptions, "xframeoptions", "SAMEORIGIN",
|
flag.StringVar(&Config.xFrameOptions, "xframeoptions", "SAMEORIGIN",
|
||||||
"value of X-Frame-Options header")
|
"value of X-Frame-Options header")
|
||||||
|
|
|
@ -45,8 +45,9 @@ func populateTemplatesMap(tSet *pongo2.TemplateSet, tMap map[string]*pongo2.Temp
|
||||||
"index.html",
|
"index.html",
|
||||||
"paste.html",
|
"paste.html",
|
||||||
"API.html",
|
"API.html",
|
||||||
"404.html",
|
"400.html",
|
||||||
"401.html",
|
"401.html",
|
||||||
|
"404.html",
|
||||||
"oops.html",
|
"oops.html",
|
||||||
|
|
||||||
"display/audio.html",
|
"display/audio.html",
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
400 Bad Request
|
||||||
|
{% endblock %}
|
|
@ -46,7 +46,7 @@ type Upload struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
func uploadPostHandler(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
if !strictReferrerCheck(r, Config.siteURL, []string{"Linx-Delete-Key", "Linx-Expiry", "Linx-Randomize"}) {
|
if !strictReferrerCheck(r, Config.siteURL, []string{"Linx-Delete-Key", "Linx-Expiry", "Linx-Randomize", "X-Requested-With"}) {
|
||||||
badRequestHandler(c, w, r)
|
badRequestHandler(c, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ func uploadRemote(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// strict referrer checking is mandatory without remote auth keys
|
// strict referrer checking is mandatory without remote auth keys
|
||||||
if !strictReferrerCheck(r, Config.siteURL, []string{"Linx-Delete-Key", "Linx-Expiry", "Linx-Randomize"}) {
|
if !strictReferrerCheck(r, Config.siteURL, []string{"Linx-Delete-Key", "Linx-Expiry", "Linx-Randomize", "X-Requested-With"}) {
|
||||||
badRequestHandler(c, w, r)
|
badRequestHandler(c, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue