Skip to content
Permalink
Browse files

Limit maximum size of uploads to be viewed as code

When using "view code" the whole file is read into RAM before being
echoed back to the user. When large uploads are allowed (e.g. in the
same order of magnitude as the available RAM) this can lead to
performance problems and can easily be abused by a malicious user.

This is a breaking change - if a server operator wants to maintain the
unlimited behaviour he would have to set ViewLimit >= SizeLimit.
  • Loading branch information...
tribut committed Feb 27, 2018
1 parent 573e1c2 commit ffa8967166d7a4b99cecc852d0b4b36ee8a6cfd7
Showing with 23 additions and 6 deletions.
  1. +3 −0 server/conf/conf.go
  2. +4 −0 server/templates/setup.html
  3. +5 −0 server/views/resources.go
  4. +11 −6 server/views/unencrypted.go
@@ -29,6 +29,7 @@ type Conf struct {
UniURILength int `yaml:"uniuri_length" form:"uniuri_length"`
KeyLength int `yaml:"key_length" form:"key_length"`
SizeLimit int64 `yaml:"size_limit" form:"size_limit"`
ViewLimit int64 `yaml:"view_limit" form:"view_limit"`
DiskQuota float64 `yaml:"disk_quota" form:"disk_quota"`
LogLevel string `yaml:"loglevel" form:"loglevel"`

@@ -59,6 +60,7 @@ type UnparsedConf struct {
UniURILength int `yaml:"uniuri_length" form:"uniuri_length"`
KeyLength int `yaml:"key_length" form:"key_length"`
SizeLimit int64 `yaml:"size_limit" form:"size_limit"`
ViewLimit int64 `yaml:"view_limit" form:"view_limit"`
DiskQuota float64 `yaml:"disk_quota" form:"disk_quota"`
LogLevel string `yaml:"loglevel" form:"loglevel"`

@@ -80,6 +82,7 @@ func NewDefault() Conf {
Port: 8080,
UniURILength: 10,
SizeLimit: 20,
ViewLimit: 5,
DiskQuota: 0,
KeyLength: 16,
LogLevel: "info",
@@ -75,6 +75,10 @@ <h4>Uploads and Database</h4>
<span class="float-right"><i>Maximum size of the uploaded files in MB</i></span>
<input placeholder="Default : 20" id="size_limit" name="size_limit" type="text">

<label for="view_limit" class="label-inline"><b>View Limit</b></label>
<span class="float-right"><i>Maximum size for syntax-highlighted code to be shown in MB</i></span>
<input placeholder="Default : 5" id="view_limit" name="view_limit" type="text">

<label for="disk_quota" class="label-inline"><b>Disk Quota</b></label>
<span class="float-right"><i>Disk quota in GB. Set to 0 to disable.</i></span>
<input placeholder="Default : 0" id="disk_quota" name="disk_quota" type="text">
@@ -148,6 +148,11 @@ func ViewCCode(c *gin.Context) {
c.AbortWithStatus(http.StatusNotFound)
return
}
if re.Size > conf.C.ViewLimit*utils.MegaByte {
logger.InfoC(c, "server", fmt.Sprintf("Tried to view %s but it is too large (%s > %s)", re.Key, utils.HumanBytes(uint64(re.Size)), utils.HumanBytes(uint64(conf.C.ViewLimit*utils.MegaByte))))
c.AbortWithStatus(http.StatusForbidden)
return
}
re.LogFetched(c)
f, err := os.Open(path.Join(conf.C.UploadDir, re.Key))
if err != nil {
@@ -1,8 +1,8 @@
package views

import (
"bytes"
"bufio"
"bytes"
"fmt"
"io"
"net/http"
@@ -76,12 +76,12 @@ func Create(c *gin.Context) {
}
del := time.Now().Add(duration)
newres := &models.Resource{
Key: u,
Name: h.Filename,
Once: once,
DeleteAt: del,
Key: u,
Name: h.Filename,
Once: once,
DeleteAt: del,
UnixDeleteAt: del.Unix(),
Size: wr,
Size: wr,
}
if err = newres.Save(); err != nil {
logger.ErrC(c, "server", "Couldn't save in database", err)
@@ -173,6 +173,11 @@ func ViewCode(c *gin.Context) {
c.AbortWithStatus(http.StatusNotFound)
return
}
if re.Size > conf.C.ViewLimit*utils.MegaByte {
logger.InfoC(c, "server", fmt.Sprintf("Tried to view %s but it is too large (%s > %s)", re.Key, utils.HumanBytes(uint64(re.Size)), utils.HumanBytes(uint64(conf.C.ViewLimit*utils.MegaByte))))
c.AbortWithStatus(http.StatusForbidden)
return
}
re.LogFetched(c)
f, err := os.Open(path.Join(conf.C.UploadDir, re.Key))
if err != nil {

0 comments on commit ffa8967

Please sign in to comment.
You can’t perform that action at this time.