Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: documentation sync #824

Merged
merged 9 commits into from
Jun 22, 2023
37 changes: 25 additions & 12 deletions internal/actions/allow.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,31 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// 0 nothing, 1 phase, 2 request
// Action Group: Disruptive
//
// Description:
// Stops rule processing on a successful match and allows a transaction to be proceed.
//
// - Using solely: allow will affect the entire transaction.
// stopping processing of the current phase but also skipping over all other phases apart from the logging phase.
// (The logging phase is special; it is designed to be always execute.)
// - Using with parameter `phase`: the engine will stop processing the current phase, and the other phases will continue.
// - Using with parameter `request`: engine will stop processing the current phase, and the next phase to be processed will be phase `types.PhaseResponseHeaders`.
//
// Example:
// ```
// # Allow unrestricted access from 192.168.1.100
// SecRule REMOTE_ADDR "^192\.168\.1\.100$" phase:1,id:95,nolog,allow
//
// # Do not process request but process response
// SecAction phase:1,allow:request,id:96
//
// # Do not process transaction (request and response).
// SecAction phase:1,allow,id:97
//
// # If you want to allow a response through, put a rule in phase RESPONSE_HEADERS and use allow
// SecAction phase:3,allow,id:98
// ```
type allowFn struct {
allow corazatypes.AllowType
}
Expand All @@ -30,17 +54,6 @@ func (a *allowFn) Init(_ plugintypes.RuleMetadata, data string) error {
return nil
}

// Evaluate Allow has the following rules:
//
// Example: `SecRule REMOTE_ADDR "^192\.168\.1\.100$" "phase:1,id:95,nolog,allow"`
//
// - If used one its own, like in the example above, allow will affect the entire transaction,
// stopping processing of the current phase but also skipping over all other phases apart from the logging phase.
// (The logging phase is special; it is designed to always execute.)
// - If used with parameter "phase", allow will cause the engine to stop processing the current phase.
// Other phases will continue as normal.
// - If used with parameter "request", allow will cause the engine to stop processing the current phase.
// The next phase to be processed will be phase types.PhaseResponseHeaders.
func (a *allowFn) Evaluate(r plugintypes.RuleMetadata, txS plugintypes.TransactionState) {
tx := txS.(*corazawaf.Transaction)
tx.AllowType = a.allow
Expand Down
10 changes: 10 additions & 0 deletions internal/actions/auditlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// Action Group: Non-disruptive
//
// Description:
// Marks the transaction for logging in the audit log.
//
// Example:
// ```
// # The action is explicit if the log is specified.
// SecRule REMOTE_ADDR "^192\.168\.1\.100$" "auditlog,phase:1,id:100,allow"
// ```
type auditlogFn struct{}

func (a *auditlogFn) Init(r plugintypes.RuleMetadata, data string) error {
Expand Down
39 changes: 39 additions & 0 deletions internal/actions/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,45 @@ import (
"github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes"
)

// Action Group: Disruptive
//
// Description:
// Performs the disruptive action defined by the previous `SecDefaultAction`.
// This action is a placeholder to be used by rule writers to request a blocking action,
// but without specifying how the blocking is to be done.
// The idea is that such decisions are best left to rule users, as well as to allow users, to override blocking for their demands.
// In future versions of Coraza, more control and functionality will be added to define "how" to block.
//
// Example:
// ```
// # Specify how blocking is to be done
// SecDefaultAction "phase:2,deny,id:101,status:403,log,auditlog"
//
// # Detect attacks where we want to block
// SecRule ARGS "@rx attack1" "phase:2,block,id:102"
//
// # Detect attacks where we want only to warn
// SecRule ARGS "@rx attack2" "phase:2,pass,id:103"
//
// # It is possible to use the `SecRuleUpdateActionById` directive to override how a rule handles blocking.
// # This is useful in three cases:
//
// # 1. If a rule has blocking hard-coded, and you want it to use the policy you determine.
// # 2. If a rule was written to `block`, but you want it to warn only.
// # 3. If a rule was written to only `warn`, but you want it to block.
//
// # The following example demonstrates the first case,
// # in which the hard-coded block is removed in favor of the user-controllable block:
//
// # Specify how blocking is to be done
// SecDefaultAction "phase:2,deny,status:403,log,auditlog,id:104"
//
// # Detect attacks and block
// SecRule ARGS "@rx attack1" "phase:2,id:1,deny"
//
// # Change how rule ID 1 blocks
// SecRuleUpdateActionById 1 "block"
// ```
type blockFn struct{}

func (a *blockFn) Init(_ plugintypes.RuleMetadata, data string) error {
Expand Down
16 changes: 16 additions & 0 deletions internal/actions/capture.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// Action Group: Non-disruptive
//
// Description:
// > This action is being forced by now, it might be reused in the future.
//
// When used together with the regular expression operator `@rx`,
// `capture` creates a copy of the regular expression and places them into the transaction variable collection.
// Up to 10 captures will be copied on a successful pattern match, each with a name consisting of a digit from 0 to 9.
// The `TX.0` variable always contains the entire area that the regular expression matched.
// All the other variables contain the captured values, in the order in which the capturing parentheses appear in the regular expression.
//
// Example:
// ```
// SecRule REQUEST_BODY "^username=(\w{25,})" phase:2,capture,t:none,chain,id:105
// SecRule TX:1 "(?:(?:a(dmin|nonymous)))"
// ```
type captureFn struct{}

func (a *captureFn) Init(r plugintypes.RuleMetadata, data string) error {
Expand Down
35 changes: 35 additions & 0 deletions internal/actions/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,41 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// Action Group: Flow
//
// Description:
// Creating a rule chain - chains the current rule with the rule that immediately follows it.
//
// Noted that rule chains simulate **AND condition**.
// The disruptive actions specified in the first portion of the chained rule will be triggered only if all of the variable checks return positive hits.
// If one of the chained rule is negative, the entire rule chain will fail to match.
//
// These action can be specified only by the chain starter rule:
// - disruptive actions
// - execution phases
// - metadata actions (id, rev, msg, tag, severity, logdata)
// - skip
// - skipAfter
//
// The following directives can be used in rule chains:
// - `SecAction`
// - `SecRule`
// - `SecRuleScript`
//
// Special rules control the usage of actions in a chained rule:
// - An action which affects the rule flow (i.e., the disruptive actions, `skip` and `skipAfter`) can be used only in the chain starter. They will be executed only if the entire chain matches.
// - Non-disruptive rules can be used in any rule; they will be executed if the rule that contains them matches and not only when the entire chain matches.
// - The metadata actions (e.g., `id`, `rev`, `msg`) can be used only in the chain starter.
//
// Example:
// ```
// # Refuse to accept POST requests that do not contain a Content-Length header.
// # Noted that the rule should be preceded by a rule that verifies only valid request methods are used.
//
// SecRule REQUEST_METHOD "^POST$" "phase:1,chain,t:none,id:105"
// SecRule &REQUEST_HEADERS:Content-Length "@eq 0" "t:none"
//
// ```
type chainFn struct{}

func (a *chainFn) Init(r plugintypes.RuleMetadata, data string) error {
Expand Down
56 changes: 56 additions & 0 deletions internal/actions/ctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,62 @@ const (
ctlDebugLogLevel ctlFunctionType = iota
)

// Action Group: Non-disruptive
//
// Description:
// Change Coraza configuration on transient, per-transaction basis.
// Any changes made using this action will affect only the transaction in which the action is executed.
// The default configuration, as well as the other transactions running in parallel, will be unaffected.
//
// The following configuration options are supported:
// - `auditEngine`
// - `auditLogParts`
// - `debugLogLevel`
// - `forceRequestBodyVariable`
// - `requestBodyAccess`
// - `requestBodyLimit`
// - `requestBodyProcessor`
// - `responseBodyAccess`
// - `responseBodyLimit`
// - `ruleEngine`
// - `ruleRemoveById`
// - `ruleRemoveByMsg`
// - `ruleRemoveByTag`
// - `ruleRemoveTargetById`
// - `ruleRemoveTargetByMsg`
// - `ruleRemoveTargetByTag`
// - `hashEngine` (**Not Supported in Coraza (TBI)**)
// - `hashEnforcement` (**Not supported in Coraza (TBI)**)
//
// Here are some notes about the options:
//
// 1. Option `ruleRemoveTargetById`, `ruleRemoveTargetByMsg`, and `ruleRemoveTargetByTag`, users don't need to use the char ! before the target list.
//
// 2. Option `ruleRemoveById` is triggered at run time and should be specified before the rule in which it is disabling.
//
// 3. Option `requestBodyProcessor` allows you to configure the request body processor.
// By default, Coraza will use the `URLENCODED` and `MULTIPART` processors to process an `application/x-www-form-urlencoded` and a `multipart/form-data` body respectively.
// Other processors also supported: `JSON` and `XML`, but they are never used implicitly.
// Instead, you must tell Coraza to use it by placing a few rules in the `REQUEST_HEADERS` processing phase.
// After the request body is processed as XML, you will be able to use the XML-related features to inspect it.
// Request body processors will not interrupt a transaction if an error occurs during parsing.
// Instead, they will set the variables `REQBODY_PROCESSOR_ERROR` and `REQBODY_PROCESSOR_ERROR_MSG`.
// These variables should be inspected in the `REQUEST_BODY` phase and an appropriate action taken.
//
// 4. Option `forceRequestBodyVariable“ allows you to configure the `REQUEST_BODY` variable to be set when there is no request body processor configured.
// This allows for inspection of request bodies of unknown types.
//
// Example:
// ```
// # Parse requests with Content-Type "text/xml" as XML
// SecRule REQUEST_CONTENT_TYPE ^text/xml "nolog,pass,id:106,ctl:requestBodyProcessor=XML"
//
// # white-list the user parameter for rule #981260 when the REQUEST_URI is /index.php
//
// SecRule REQUEST_URI "@beginsWith /index.php" "phase:1,t:none,pass,\
// nolog,ctl:ruleRemoveTargetById=981260;ARGS:user"
//
// ```
type ctlFn struct {
action ctlFunctionType
value string
Expand Down
9 changes: 9 additions & 0 deletions internal/actions/deny.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ import (
"github.com/corazawaf/coraza/v3/types"
)

// Action Group: Disruptive
//
// Description:
// Stops rule processing and intercepts transaction.
//
// Example:
// ```
// SecRule REQUEST_HEADERS:User-Agent "nikto" "log,deny,id:107,msg:'Nikto Scanners Identified'"
// ```
type denyFn struct{}

func (a *denyFn) Init(_ plugintypes.RuleMetadata, data string) error {
Expand Down
18 changes: 18 additions & 0 deletions internal/actions/drop.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ import (
"github.com/corazawaf/coraza/v3/types"
)

// Action Group: Disruptive
//
// Description:
// > This action depends on each implementation, the server is instructed to drop the connection.
//
// Initiates an immediate close of the TCP connection by sending a FIN packet.
// This action is extremely useful when responding to both Brute Force and Denial of Service attacks,
// which you may want to minimize the network bandwidth and the data returned to the client.
// This action causes error message to appear in the log `(9)Bad file descriptor: core_output_filter: writing data to the network`
//
// Example:
// ```
// # The following example initiates an IP collection for tracking Basic Authentication attempts.
// # If the client exceed the threshold of more than 25 attempts in 2 minutes, it will `DROP` the subsequent connections.
// SecAction phase:1,id:109,initcol:ip=%{REMOTE_ADDR},nolog
// SecRule ARGS:login "!^$" "nolog,phase:1,id:110,setvar:ip.auth_attempt=+1,deprecatevar:ip.auth_attempt=25/120"
// SecRule IP:AUTH_ATTEMPT "@gt 25" "log,drop,phase:1,id:111,msg:'Possible Brute Force Attack'"
// ```
type dropFn struct{}

func (a *dropFn) Init(_ plugintypes.RuleMetadata, data string) error {
Expand Down
22 changes: 22 additions & 0 deletions internal/actions/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ import (
"github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes"
)

// Action Group: Non-disruptive
//
// Description:
// Executes an external script/binary supplied as parameter.
// The `exec` action is executed independently from any disruptive actions specified.
// External scripts will always be called with no parameters.
// Some transaction information will be placed in environment variables.
// All the usual CGI environment variables will be there.
// You should be aware that forking a threaded process results in all threads being replicated in the new process.
// Forking can therefore incur larger overhead in a multithreaded deployment.
//
// > The script you execute must write something (anything) to stdout,
// > if it doesn’t, Coraza will assume that the script failed, and will record the failure.
//
// Example:
// ```
// # Run external program on rule match
// SecRule REQUEST_URI "^/cgi-bin/script\.pl" "phase:2,id:112,t:none,t:lowercase,t:normalizePath,block,\ exec:/usr/local/apache/bin/test.sh"

// # Run Lua script on rule match
// SecRule ARGS:p attack "phase:2,id:113,block,exec:/usr/local/apache/conf/exec.lua"
// ```
type execFn struct{}

func (a *execFn) Init(_ plugintypes.RuleMetadata, data string) error {
Expand Down
16 changes: 16 additions & 0 deletions internal/actions/expirevar.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import (
"github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes"
)

// Action Group: Non-disruptive
//
// Description:
// Configures a collection variable to expire after the given time period (in seconds).
// You should use the `expirevar` with `setvar` action to keep the intended expiration time.
// The expire time will be reset if they are used on their own (perhaps in a SecAction directive).
//
// Example:
// ```
//
// SecRule REQUEST_COOKIES:JSESSIONID "!^$" "nolog,phase:1,id:114,pass,setsid:%{REQUEST_COOKIES:JSESSIONID}"
//
// SecRule REQUEST_URI "^/cgi-bin/script\.pl" "phase:2,id:115,t:none,t:lowercase,t:normalizePath,log,allow,\
// setvar:session.suspicious=1,expirevar:session.suspicious=3600,phase:1"
//
// ```
type expirevarFn struct{}

func (a *expirevarFn) Init(_ plugintypes.RuleMetadata, data string) error {
Expand Down
10 changes: 10 additions & 0 deletions internal/actions/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// Action Group: Metadata
//
// Description:
// > This action is mandatory for all `SecRule` and `SecAction`, and it must be numeric.
// Assigns a unique ID to the rule or chain in which it appears.
//
// Example:
// ```
// SecRule &REQUEST_HEADERS:Host "@eq 0" "log,id:60008,severity:2,msg:'Request Missing a Host Header'"
// ```
type idFn struct{}

func (a *idFn) Init(r plugintypes.RuleMetadata, data string) error {
Expand Down
14 changes: 13 additions & 1 deletion internal/actions/initcol.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ import (
"github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes"
)

// Initializes a persistent collection and add the data to the standard collections coraza.
// Action Group: Non-disruptive
//
// Description:
// Initializes a named persistent collection, either by loading data from storage or by creating a new collection in memory.
// Collections are loaded into memory on-demand, when the initcol action is executed.
// A collection will be persisted only if a change was made to it in the course of transaction processing.
// See the `Persistent Storage` section for further details.
//
// Example:
// ```
// # Initiates IP address tracking, which is best done in phase 1
// SecAction "phase:1,id:116,nolog,pass,initcol:ip=%{REMOTE_ADDR}"
// ```
type initcolFn struct {
collection string
variable byte
Expand Down
10 changes: 10 additions & 0 deletions internal/actions/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import (
"github.com/corazawaf/coraza/v3/internal/corazawaf"
)

// Action Group: Non-disruptive
//
// Description:
// Indicates that a successful match of the rule needs to be logged.
//
// Example:
// ```
// # log matches from the error log file to the Coraza audit log.
// SecAction "phase:1,id:117,pass,initcol:ip=%{REMOTE_ADDR},log"
// ```
type logFn struct{}

func (a *logFn) Init(r plugintypes.RuleMetadata, data string) error {
Expand Down
Loading