Browse Source

Fix default configurations (#597)

* fix default perms on SQLite file

* seed the prng securely

* fix defaults to enforce certificates verification

* ensure file is within path

* ensure the directory doesn't exist beforehand

* verify certificate by default

* disable http ip forward headers
Thibault "bui" Koechlin 4 years ago
parent
commit
e74f221044

+ 9 - 4
cmd/crowdsec-cli/config.go

@@ -5,6 +5,9 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
+	"path/filepath"
+
+	"github.com/pkg/errors"
 
 	"github.com/crowdsecurity/crowdsec/pkg/csconfig"
 	"github.com/crowdsecurity/crowdsec/pkg/cwhub"
@@ -35,11 +38,13 @@ func backupConfigToDirectory(dirPath string) error {
 		return fmt.Errorf("directory path can't be empty")
 	}
 	log.Infof("Starting configuration backup")
-	_, err = os.Stat(dirPath)
-	if err == nil {
-		return fmt.Errorf("%s already exists", dirPath)
+	/*if parent directory doesn't exist, bail out. create final dir with Mkdir*/
+	parentDir := filepath.Dir(dirPath)
+	if _, err := os.Stat(parentDir); err != nil {
+		return errors.Wrapf(err, "while checking parent directory %s existence", parentDir)
 	}
-	if err = os.MkdirAll(dirPath, os.ModePerm); err != nil {
+
+	if err = os.Mkdir(dirPath, 0600); err != nil {
 		return fmt.Errorf("error while creating %s : %s", dirPath, err)
 	}
 

+ 10 - 11
cmd/crowdsec-cli/machines.go

@@ -1,10 +1,11 @@
 package main
 
 import (
+	saferand "crypto/rand"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
+	"math/big"
 	"os"
 	"strings"
 	"time"
@@ -42,20 +43,18 @@ const (
 )
 
 func generatePassword(length int) string {
-	rand.Seed(time.Now().UnixNano())
+
 	charset := upper + lower + digits
+	charsetLength := len(charset)
 
 	buf := make([]byte, length)
-	buf[0] = digits[rand.Intn(len(digits))]
-	buf[1] = upper[rand.Intn(len(upper))]
-	buf[2] = lower[rand.Intn(len(lower))]
-
-	for i := 3; i < length; i++ {
-		buf[i] = charset[rand.Intn(len(charset))]
+	for i := 0; i < length; i++ {
+		rInt, err := saferand.Int(saferand.Reader, big.NewInt(int64(charsetLength)))
+		if err != nil {
+			log.Fatalf("failed getting data from prng for password generation : %s", err)
+		}
+		buf[i] = charset[rInt.Int64()]
 	}
-	rand.Shuffle(len(buf), func(i, j int) {
-		buf[i], buf[j] = buf[j], buf[i]
-	})
 
 	return string(buf)
 }

+ 1 - 1
config/config.yaml

@@ -31,7 +31,7 @@ db_config:
     max_age: 7d
 api:
   client:
-    insecure_skip_verify: true
+    insecure_skip_verify: false
     credentials_path: /etc/crowdsec/local_api_credentials.yaml
   server:
     log_level: info

+ 1 - 1
config/user.yaml

@@ -27,7 +27,7 @@ db_config:
   port: 3306
 api:
   client:
-    insecure_skip_verify: true # default true
+    insecure_skip_verify: false # default true
     credentials_path: /etc/crowdsec/local_api_credentials.yaml
   server:
     #log_level: info

+ 1 - 1
docker/config.yaml

@@ -31,7 +31,7 @@ db_config:
     max_age: 7d
 api:
   client:
-    insecure_skip_verify: true
+    insecure_skip_verify: false
     credentials_path: /etc/crowdsec/local_api_credentials.yaml
   server:
     log_level: info

+ 1 - 1
docs/v1.X/docs/references/crowdsec-config.md

@@ -43,7 +43,7 @@ db_config:
     max_age: 7d
 api:
   client:
-    insecure_skip_verify: true
+    insecure_skip_verify: false
     credentials_path: /etc/crowdsec/local_api_credentials.yaml
   server:
     log_level: info

+ 1 - 1
pkg/apiclient/client.go

@@ -14,7 +14,7 @@ import (
 )
 
 var (
-	InsecureSkipVerify = true
+	InsecureSkipVerify = false
 )
 
 type ApiClient struct {

+ 4 - 0
pkg/apiserver/apiserver.go

@@ -61,6 +61,10 @@ func NewServer(config *csconfig.LocalApiServerCfg) (*APIServer, error) {
 	}
 	log.Debugf("starting router, logging to %s", logFile)
 	router := gin.New()
+	/*related to https://github.com/gin-gonic/gin/pull/2474
+	Gin team doesn't seem to be willing to have a opt-in/opt-out on the trusted proxies.
+	For now, let's not trust that. 	*/
+	router.ForwardedByClientIP = false
 
 	/*The logger that will be used by handlers*/
 	clog := log.New()

+ 1 - 1
pkg/csconfig/config.go

@@ -125,7 +125,7 @@ func (c *GlobalConfig) LoadConfiguration() error {
 			}
 		}
 		if c.API.Client.InsecureSkipVerify == nil {
-			apiclient.InsecureSkipVerify = true
+			apiclient.InsecureSkipVerify = false
 		} else {
 			apiclient.InsecureSkipVerify = *c.API.Client.InsecureSkipVerify
 		}

+ 10 - 2
pkg/cwhub/download.go

@@ -3,6 +3,7 @@ package cwhub
 import (
 	"bytes"
 	"crypto/sha256"
+	"path/filepath"
 
 	//"errors"
 	"github.com/pkg/errors"
@@ -127,7 +128,6 @@ func DownloadItem(cscli *csconfig.CscliCfg, target Item, overwrite bool) (Item,
 			return target, nil
 		}
 	}
-
 	req, err := http.NewRequest("GET", fmt.Sprintf(RawFileURLTemplate, HubBranch, target.RemotePath), nil)
 	if err != nil {
 		return target, errors.Wrap(err, fmt.Sprintf("while downloading %s", req.URL.String()))
@@ -159,6 +159,14 @@ func DownloadItem(cscli *csconfig.CscliCfg, target Item, overwrite bool) (Item,
 	tmpdirs := strings.Split(tdir+"/"+target.RemotePath, "/")
 	parent_dir := strings.Join(tmpdirs[:len(tmpdirs)-1], "/")
 
+	/*ensure that target file is within target dir*/
+	finalPath, err := filepath.Abs(tdir + "/" + target.RemotePath)
+	if err != nil {
+		return target, errors.Wrapf(err, "Abs error on %s", tdir+"/"+target.RemotePath)
+	}
+	if !strings.HasPrefix(finalPath, tdir) {
+		return target, fmt.Errorf("path %s escapes %s, abort", target.RemotePath, tdir)
+	}
 	/*check dir*/
 	if _, err = os.Stat(parent_dir); os.IsNotExist(err) {
 		log.Debugf("%s doesn't exist, create", parent_dir)
@@ -167,7 +175,7 @@ func DownloadItem(cscli *csconfig.CscliCfg, target Item, overwrite bool) (Item,
 		}
 	}
 	/*check actual file*/
-	if _, err = os.Stat(tdir + "/" + target.RemotePath); !os.IsNotExist(err) {
+	if _, err = os.Stat(finalPath); !os.IsNotExist(err) {
 		log.Warningf("%s : overwrite", target.Name)
 		log.Debugf("target: %s/%s", tdir, target.RemotePath)
 	} else {

+ 16 - 0
pkg/database/database.go

@@ -3,6 +3,7 @@ package database
 import (
 	"context"
 	"fmt"
+	"os"
 	"time"
 
 	"github.com/crowdsecurity/crowdsec/pkg/csconfig"
@@ -30,6 +31,21 @@ func NewClient(config *csconfig.DatabaseCfg) (*Client, error) {
 	}
 	switch config.Type {
 	case "sqlite":
+
+		/*if it's the first startup, we want to touch and chmod file*/
+		if _, err := os.Stat(config.DbPath); os.IsNotExist(err) {
+			f, err := os.OpenFile(config.DbPath, os.O_CREATE|os.O_RDWR, 0600)
+			if err != nil {
+				return &Client{}, errors.Wrapf(err, "failed to create SQLite database file %q", config.DbPath)
+			}
+			if err := f.Close(); err != nil {
+				return &Client{}, errors.Wrapf(err, "failed to create SQLite database file %q", config.DbPath)
+			}
+		} else { /*ensure file perms*/
+			if err := os.Chmod(config.DbPath, 0600); err != nil {
+				return &Client{}, fmt.Errorf("unable to set perms on %s: %v", config.DbPath, err)
+			}
+		}
 		client, err = ent.Open("sqlite3", fmt.Sprintf("file:%s?_busy_timeout=100000&_fk=1", config.DbPath))
 		if err != nil {
 			return &Client{}, fmt.Errorf("failed opening connection to sqlite: %v", err)