mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-11-24 09:02:26 +02:00
added randomized trottle for failed list filter requests
This commit is contained in:
parent
8144ad1dda
commit
0d34c00d2e
@ -1,9 +1,12 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
cryptoRand "crypto/rand"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/dbx"
|
||||
@ -71,7 +74,13 @@ func (api *recordApi) list(c echo.Context) error {
|
||||
|
||||
records := []*models.Record{}
|
||||
|
||||
result, err := searchProvider.ParseAndExec(c.QueryParams().Encode(), &records)
|
||||
// note: in v0.23.0 this has been migrated as option check in the search.Provider
|
||||
queryStr := c.QueryParams().Encode()
|
||||
if len(queryStr) > 2048 {
|
||||
return NewBadRequestError("query string is too large", nil)
|
||||
}
|
||||
|
||||
result, err := searchProvider.ParseAndExec(queryStr, &records)
|
||||
if err != nil {
|
||||
return NewBadRequestError("", err)
|
||||
}
|
||||
@ -91,10 +100,43 @@ func (api *recordApi) list(c echo.Context) error {
|
||||
api.app.Logger().Debug("Failed to enrich list records", slog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
// note: in v0.23.0 this is combined with extra check for repeated attempts
|
||||
//
|
||||
// Add a randomized throttle in case of empty search filter attempts.
|
||||
//
|
||||
// This is just for extra precaution since security researches raised concern regarding the possibity of eventual
|
||||
// timing attacks because the List API rule acts also as filter and executes in a single run with the client-side filters.
|
||||
// This is by design and it is an accepted tradeoff between performance, usability and correctness.
|
||||
//
|
||||
// While technically the below doesn't fully guarantee protection against filter timing attacks, in practice combined with the network latency it makes them even less feasible.
|
||||
// A properly configured rate limiter or individual fields Hidden checks are better suited if you are really concerned about eventual information disclosure by side-channel attacks.
|
||||
//
|
||||
// In all cases it doesn't really matter that much because it doesn't affect the builtin PocketBase security sensitive fields (e.g. password and tokenKey) since they
|
||||
// are not client-side filterable and in the few places where they need to be compared against an external value, a constant time check is used.
|
||||
if requestInfo.Admin == nil &&
|
||||
(collection.ListRule != nil && *collection.ListRule != "") &&
|
||||
(requestInfo.Query["filter"] != "") &&
|
||||
len(e.Records) == 0 {
|
||||
api.app.Logger().Debug("Randomized throttle because of failed filter search", "collectionId", collection.Id)
|
||||
randomizedThrottle(100)
|
||||
}
|
||||
|
||||
return e.HttpContext.JSON(http.StatusOK, e.Result)
|
||||
})
|
||||
}
|
||||
|
||||
func randomizedThrottle(softMax int64) {
|
||||
var timeout int64
|
||||
randRange, err := cryptoRand.Int(cryptoRand.Reader, big.NewInt(softMax))
|
||||
if err == nil {
|
||||
timeout = randRange.Int64()
|
||||
} else {
|
||||
timeout = softMax
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(timeout) * time.Millisecond)
|
||||
}
|
||||
|
||||
func (api *recordApi) view(c echo.Context) error {
|
||||
collection, _ := c.Get(ContextCollectionKey).(*models.Collection)
|
||||
if collection == nil {
|
||||
|
Loading…
Reference in New Issue
Block a user