Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
766cfceac4 |
No files matched your search
@@ -681,12 +681,8 @@ through. An app's fixes hold for the hostnames `SWW_APPS` lists the app for:
|
||||
Set empty, `SWW_APPS` lists no hostname.
|
||||
- Unset, every app's fixes hold for every hostname. An app's fixes then weaken
|
||||
the check of any other app that serves the same paths or fields.
|
||||
- Any of these mistakes stops the start:
|
||||
- an unknown app;
|
||||
- a hostname that is not a DNS name, such as `*.example.com`;
|
||||
- a hostname listed twice;
|
||||
- an app listed twice for one hostname;
|
||||
- an entry without a colon.
|
||||
- The start stops on an unknown app, a hostname listed twice, an app listed
|
||||
twice for one hostname, or an entry without a colon.
|
||||
|
||||
`gitea` is the only app supported. Each app's fixes are in one file, such as
|
||||
`internal/waf/gitea.conf`, and one entry of `apps` in `internal/waf/waf.go`.
|
||||
|
||||
+2
-6
@@ -210,12 +210,8 @@ between the two (see "The image's command" below).
|
||||
- A hostname not listed gets no app's fixes, so every rule checks it in
|
||||
full. Set empty, it lists no hostname.
|
||||
- Unset, every app's fixes apply to every hostname.
|
||||
- Any of these mistakes stops the start:
|
||||
- an unknown app;
|
||||
- a hostname that is not a DNS name, such as `*.example.com`;
|
||||
- a hostname listed twice;
|
||||
- an app listed twice for one hostname;
|
||||
- an entry without a colon.
|
||||
- An unknown app, a hostname listed twice, an app listed twice for one
|
||||
hostname, or an entry without a colon stops the start.
|
||||
- `SWW_ERROR_BURST_THRESHOLD` (default `30`): the most refusals of one client in
|
||||
a minute (see "Attack detection" in `SPEC.md`). A count or `off`.
|
||||
|
||||
|
||||
@@ -406,7 +406,6 @@ var (
|
||||
"is not a path starting with / and without a ?, such as /wp-login.php")
|
||||
errNotAppsEntry = errors.New(
|
||||
"is not a hostname, : and a list of apps, such as git.example.com:gitea")
|
||||
errNotHostname = errors.New("is not a DNS name such as git.example.com")
|
||||
errNotApp = errors.New("is not an app sww has fixes for; the apps are")
|
||||
errNotWAFMode = errors.New("is not off, detect or block")
|
||||
errNotParanoiaLevel = errors.New("is not a paranoia level, from 1 to 4")
|
||||
@@ -1676,10 +1675,9 @@ func parseTrapPaths(value string) ([]string, error) {
|
||||
// parseApps reads the apps each hostname serves: entries separated by
|
||||
// semicolons, each a hostname, a colon, and a comma-separated list of the
|
||||
// names waf.AppNames returns, such as
|
||||
// git.example.com:gitea;cloud.example.com:nextcloud,wordpress. Each
|
||||
// hostname is a DNS name, without a wildcard. It returns them by hostname
|
||||
// in lowercase, since a hostname is matched without regard to case. An
|
||||
// empty value lists no hostname.
|
||||
// git.example.com:gitea;cloud.example.com:nextcloud,wordpress. It returns
|
||||
// them by hostname in lowercase, since a hostname is matched without
|
||||
// regard to case. An empty value lists no hostname.
|
||||
func parseApps(value string) (map[string][]string, error) {
|
||||
apps := map[string][]string{}
|
||||
|
||||
@@ -1698,10 +1696,6 @@ func parseApps(value string) (map[string][]string, error) {
|
||||
return nil, fmt.Errorf("%q %w", entry, errNotAppsEntry)
|
||||
}
|
||||
|
||||
if !isZone(hostname) {
|
||||
return nil, fmt.Errorf("%q %w", hostname, errNotHostname)
|
||||
}
|
||||
|
||||
if _, listed := apps[hostname]; listed {
|
||||
return nil, fmt.Errorf("%q %w", hostname, errListedTwice)
|
||||
}
|
||||
@@ -2158,8 +2152,7 @@ func MaskZoneKey(zone string) string {
|
||||
return masked + "." + rest
|
||||
}
|
||||
|
||||
// isZone reports whether each label of zone is as parseZones takes it. It
|
||||
// also checks the hostnames of SWW_APPS, which are DNS names too.
|
||||
// isZone reports whether each label of zone is as parseZones takes it.
|
||||
func isZone(zone string) bool {
|
||||
for label := range strings.SplitSeq(zone, ".") {
|
||||
badChar := strings.ContainsFunc(label, func(char rune) bool {
|
||||
|
||||
@@ -603,20 +603,14 @@ func TestApps(t *testing.T) {
|
||||
func TestInvalidAppsStopsTheStart(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
notEntry = " is not a hostname, : and a list of apps, " +
|
||||
"such as git.example.com:gitea"
|
||||
notHostname = " is not a DNS name such as git.example.com"
|
||||
)
|
||||
const notEntry = " is not a hostname, : and a list of apps, " +
|
||||
"such as git.example.com:gitea"
|
||||
|
||||
for _, tc := range []struct{ value, want string }{
|
||||
{"git.example.com:gitea;blog.example.com", `"blog.example.com"` + notEntry},
|
||||
{"git.example.com:gitea;", `""` + notEntry},
|
||||
{":gitea", `":gitea"` + notEntry},
|
||||
{"git.example.com:", `"git.example.com:"` + notEntry},
|
||||
{"*.example.com:gitea", `"*.example.com"` + notHostname},
|
||||
{"git.example.com/:gitea", `"git.example.com/"` + notHostname},
|
||||
{"git example.com:gitea", `"git example.com"` + notHostname},
|
||||
{
|
||||
"git.example.com:gitea,nextcloud",
|
||||
`"nextcloud" is not an app sww has fixes for; the apps are gitea`,
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
||||
"sneak.berlin/go/smallwebwaf/internal/discriminator"
|
||||
"sneak.berlin/go/smallwebwaf/internal/ratelimit"
|
||||
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
||||
)
|
||||
@@ -22,7 +21,6 @@ const (
|
||||
wafDisabledRules = "SWW_WAF_DISABLED_RULES"
|
||||
wafExemptPaths = "SWW_WAF_EXEMPT_PATHS"
|
||||
wafBodyLimit = "SWW_WAF_BODY_LIMIT"
|
||||
apps = "SWW_APPS"
|
||||
block = "block"
|
||||
detect = "detect"
|
||||
)
|
||||
@@ -239,27 +237,6 @@ func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGiteasFixesApplyOnlyToAHostnameThatServesGitea(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Only gitea's fixes let a file name through in path, a parameter
|
||||
// gitea sends file names in.
|
||||
const fileName = "/?path=.gitignore"
|
||||
|
||||
s := startDiscriminator(t, "", map[string]string{
|
||||
wafMode: block, apps: siteA + ":gitea",
|
||||
})
|
||||
|
||||
wantDisposition(t, do(t, s.question(siteA, client, fileName)),
|
||||
http.StatusOK, discriminator.DispositionAllow)
|
||||
wantDisposition(t, do(t, s.question(siteB, client, fileName)),
|
||||
http.StatusForbidden, discriminator.DispositionDeny)
|
||||
|
||||
lines := s.out.requestLines(t, 2)
|
||||
wantLine(t, lines[0], http.StatusOK, requestlog.ActionForward)
|
||||
wantLine(t, lines[1], http.StatusForbidden, requestlog.ActionWAFBlocked)
|
||||
}
|
||||
|
||||
func TestAttackInAFormBodyIsRefusedOnlyWhileBodiesAreRead(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in new issue
Block a user