Skip to content

BChecks V1‐Beta grammar definition

Albert-PortSwigger edited this page Oct 10, 2023 · 5 revisions
//'=> <STATE>' denotes a transition to a lexical state
//'<=' denotes a transition to a previous lexical state
//Strings are matched using Java regex
//Token and grammar rules are matched with their order in this file as precedence 
//"IGNORED" tokens are matched by the lexer but are ignored in the grammar rules


//Lexer rules

//<Default, ActiveCheck, InsertionPointCheck, PassiveCheck, RequestNaming, WithinVariableRef>:
IGNORED ::= " " | "\n" | "\t" | "\r" | "\f" | "#[^\r|\n]*[\n|\r|\r\n]"


//<Default> 
METADATA_HEADER ::= "metadata"
NAME_HEADER ::= "name"
DESCRIPTION_HEADER ::= "description"
LANGUAGE_HEADER ::= "language"
LANGUAGE_LEVEL_1 ::= "v1-beta"
AUTHOR_HEADER ::= "author"
TAGS_HEADER ::= "tags"
GIVEN_HEADER ::= "given"
HOST_FREQ ::= "host" // => <ActiveCheck>
REQUEST_FREQ ::= "request" // => <ActiveCheck>
RESPONSE_FREQ ::= "response" // => <PassiveCheck>
INSERTION_POINT_FREQ ::= "insertion point" // => <InsertionPointCheck>
ANY ::= "any"
HEADER ::= "header"
QUERY ::= "query"
COOKIE ::= "cookie"
DEFINE_HEADER ::= "define"
RUN_FOR_EACH_HEADER ::= "run for each"
EQUALS ::= "="


//<Default, ActiveCheck, InsertionPointCheck, PassiveCheck, WithinVariableRef> 
INTERPOLATABLE_STRING_OPENING_QUOTE ::= "`" // => <WithinInterpolatableString>
LITERAL_STRING_OPENING_QUOTE ::= "\"" // => <WithinLiteralString>
OPEN_BRACKET ::= "\("
CLOSE_BRACKET ::= "\)"
NATURAL_NUMBER ::= (DIGIT)?(DIGIT)?(DIGIT)?(DIGIT)?(DIGIT)?(DIGIT)?DIGIT
LETTER_OR_UNDERSCORE ::= "[_|a-z|A-Z]"
DIGIT ::= "[0-9]"
COMMA ::= ","


//<WithinInterpolatableString> 
INTERPOLATABLE_STRING_CLOSING_QUOTE ::= "`" // <=
INTERPOLATABLE_STRING_LITERAL ::= "\\.|[^`|{|\\]"


//<WithinLiteralString> 
LITERAL_STRING_CLOSING_QUOTE ::= "\"" // <=
LITERAL_STRING ::= "\\\"|[^\"]"


//<Default, ActiveCheck, InsertionPointCheck, PassiveCheck, WithinInterpolatableString, WithinVariableRef> 
VARIABLE_START ::= "\{" // => <WithinVariableRef>


//<WithinVariableRef> 
VARIABLE_END ::= "}" // <=
GENERATE_COLLABORATOR_ADDRESS_FUNCTION ::= "generate_collaborator_address"
RANDOM_STR_FUNCTION ::= "random_str"
TO_LOWER_FUNCTION ::= "to_lower"
TO_UPPER_FUNCTION ::= "to_upper"
REGEX_REPLACE_FUNCTION ::= "regex_replace"
BASE64_ENCODE_FUNCTION ::= "base64_encode"
BASE64_DECODE_FUNCTION ::= "base64_decode"
SHA1_FUNCTION ::= "sha1"
SHA256_FUNCTION ::= "sha256"
MD5_FUNCTION ::= "md5"
REQUEST_OBJECT ::= "request"
RESPONSE_OBJECT ::= "response"
REQUEST_RESPONSE_COMMON_PROPERTY ::= "http_version" | "headers" | "body"
REQUEST_SPECIFIC_PROPERTY ::= "method"
RESPONSE_SPECIFIC_PROPERTY ::= "status_code"
URL ::= "url"
URL_PROPERTY ::= "protocol" | "host" | "port" | "path" | "file" | "query"


//<ActiveCheck, InsertionPointCheck, PassiveCheck> 
REPORT_ISSUE_HEADER ::= "report issue"
SEVERITY_HEADER ::= "severity"
HIGH_SEVERITY ::= "high"
MEDIUM_SEVERITY ::= "medium"
LOW_SEVERITY ::= "low"
INFO_SEVERITY ::= "info"
CONFIDENCE_HEADER ::= "confidence"
CERTAIN_CONFIDENCE ::= "certain"
FIRM_CONFIDENCE ::= "firm"
TENTATIVE_CONFIDENCE ::= "tentative"
REMEDIATION_HEADER ::= "remediation"
DETAIL_HEADER ::= "detail"
IF_HEADER ::= "if"
ELSE_HEADER ::= "else"
IF_FOOTER ::= "end if"
IN_KEY ::= "in"
IS_KEY ::= "is"
MATCHES_KEY ::= "matches"
DIFFERS_FROM_KEY ::= "differs from"


//<Default, ActiveCheck, InsertionPointCheck> 
BODY ::= "body"


//<ActiveCheck, InsertionPointCheck> 
SEND ::= "send"
REQUEST_HEADER ::= "request"
CALLED ::= "called" // => <RequestNaming>
METHOD ::= "method"
PATH ::= "path"
QUERIES ::= "queries"
APPENDING ::= "appending"
REMOVING ::= "removing"
REPLACING ::= "replacing"
HEADERS ::= "headers"
ANY_KEY ::= "any"
DNS_KEY ::= "dns"
HTTP_KEY ::= "http"
SMTP_KEY ::= "smtp"
INTERACTIONS_KEY ::= "interactions"


//<InsertionPointCheck> 
PAYLOAD_HEADER ::= "payload"


//<Default, ActiveCheck, PassiveCheck, InsertionPointCheck> 
BOOL_AND ::= "and"
BOOL_OR ::= "or"
BOOL_NOT ::= "not"
COLON ::= ":"
THEN ::= "then"


//<Default, WithinVariableRef> 
VARIABLE_NAME ::= LETTER_OR_UNDERSCORE (LETTER_OR_UNDERSCORE|DIGIT)*


//<RequestNaming> 
REQUEST_NAME ::= LETTER_OR_UNDERSCORE (LETTER_OR_UNDERSCORE|DIGIT)* // <=


//<Default, ActiveCheck, InsertionPointCheck, PassiveCheck, WithinVariableRef> 
DOT ::= "\."


//<Default, ActiveCheck, InsertionPointCheck, PassiveCheck, RequestNaming, WithinInterpolatableString, WithinLiteralString, WithinVariableRef> 
UNKNOWN ::= "."
UNKNOWN_STRING ::= LETTER_OR_UNDERSCORE (LETTER_OR_UNDERSCORE|DIGIT)*


//Parser rules

Start ::= Metadata ScanCheck EOF

Metadata ::= METADATA_HEADER COLON MetadataBlock

MetadataBlock ::= LanguageLevelField NameField (MetadataField)*

LanguageLevelField ::= LANGUAGE_HEADER COLON LANGUAGE_LEVEL_1

NameField ::= NAME_HEADER COLON RawStringLit

MetadataField ::= (AuthorField | TagsField | DescriptionField)
 
AuthorField ::= AUTHOR_HEADER COLON RawStringArray

TagsField ::= TAGS_HEADER COLON RawStringArray

DescriptionField ::= DESCRIPTION_HEADER COLON RawStringLit

ScanCheck ::= ((DefineBlock (RunForEachBlock)?) | (RunForEachBlock (DefineBlock)?))? GivenBlock

GivenBlock ::= GIVEN_HEADER Frequency THEN (Exp)+

Frequency ::= (HOST_FREQ | REQUEST_FREQ | RESPONSE_FREQ | ((InsertionPointModes(BOOL_OR InsertionPointModes)*)? INSERTION_POINT_FREQ))

InsertionPointModes ::= (ANY | QUERY | HEADER | BODY | COOKIE)

Exp ::= (ControlFlow | BCheckAction)+

DefineBlock ::= DEFINE_HEADER COLON (NonIterableVariableDeclaration)+

RunForEachBlock ::= RUN_FOR_EACH_HEADER COLON (IterableVariableDeclaration)+

NonIterableVariableDeclaration ::= VARIABLE_NAME EQUALS (NonIterableVariableValue | VariableReference)

IterableVariableDeclaration ::= VARIABLE_NAME EQUALS IterableVariableValue

ReportIssue ::= REPORT_ISSUE_HEADER COLON ((IssueSeverityField IssueConfidenceField) | (IssueConfidenceField IssueSeverityField)) ((IssueRemediationField (IssueDetailField)?) | (IssueDetailField (IssueRemediationField)?))?

IssueSeverityField ::= SEVERITY_HEADER COLON SeverityEnum

IssueConfidenceField ::= CONFIDENCE_HEADER COLON ConfidenceEnum

IssueRemediationField ::= REMEDIATION_HEADER COLON (StringLit | VariableReference)

IssueDetailField ::= DETAIL_HEADER COLON (StringLit | VariableReference)

SeverityEnum ::= (INFO_SEVERITY | LOW_SEVERITY | MEDIUM_SEVERITY | HIGH_SEVERITY)

ConfidenceEnum ::= (CERTAIN_CONFIDENCE | FIRM_CONFIDENCE | TENTATIVE_CONFIDENCE)

ControlFlow ::= IfBlock IF_FOOTER

IfBlock ::= IF_HEADER BooleanCondition THEN Exp (ElseBlock)?

ElseBlock ::= ELSE_HEADER (IfBlock | THEN Exp)

BooleanCondition ::= BooleanExpression (BooleanOperand BooleanCondition)?

BooleanExpression ::= (((BooleanFunction)? OPEN_BRACKET BooleanCondition CLOSE_BRACKET) | BooleanAtom)

BooleanAtom ::= ((Value (Comparison Value) | (RegexComparison RegexStringLit)) | Boolean)

Boolean ::= HasInteractions

HasInteractions ::= InteractionsEnum

InteractionsEnum ::= (((ANY_KEY)? INTERACTIONS_KEY) | (DNS_KEY INTERACTIONS_KEY) | (HTTP_KEY INTERACTIONS_KEY) | (SMTP_KEY INTERACTIONS_KEY))

Value ::= (VariableReference | StringLit)

Comparison ::= (IS_KEY | IN_KEY | DIFFERS_FROM_KEY)

RegexComparison ::= MATCHES_KEY

Function ::= (GenerateCollaboratorAddress | RandomStr | ToLower | ToUpper | Base64Encode | Base64Decode | RegexReplace | SHA1 | SHA256 | MD5)

GenerateCollaboratorAddress ::= GENERATE_COLLABORATOR_ADDRESS_FUNCTION OPEN_BRACKET CLOSE_BRACKET

RandomStr ::= RANDOM_STR_FUNCTION OPEN_BRACKET NATURAL_NUMBER CLOSE_BRACKET

ToLower ::= TO_LOWER_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

ToUpper ::= TO_UPPER_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

RegexReplace ::= REGEX_REPLACE_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) COMMA RegexStringLit COMMA (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

Base64Encode ::= BASE64_ENCODE_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

Base64Decode ::= BASE64_DECODE_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

SHA1 ::= SHA1_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

SHA256 ::= SHA256_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

MD5 ::= MD5_FUNCTION OPEN_BRACKET (VariableComponent | VariableReference | StringLit) CLOSE_BRACKET

BCheckAction ::= (ReportIssue | (SEND NamedOperation))

NamedOperation ::= (SendRequest | SendPayload)

SendRequest ::= REQUEST_HEADER (CALLED REQUEST_NAME)? COLON (StringLit | (RequestModifier)*)

SendPayload ::= PAYLOAD_HEADER (CALLED REQUEST_NAME)? COLON PayloadModifier

PayloadModifier ::= (AppendingPayloadModifier | ReplacingPayloadModifier)

AppendingPayloadModifier ::= APPENDING COLON (StringLit | VariableReference)

ReplacingPayloadModifier ::= REPLACING COLON (StringLit | VariableReference)

RequestModifier ::= (RemoveModifier | AppendModifier | ReplaceModifier)

RemoveModifier ::= REMOVING (BODY | METHOD | PATH | ((HEADERS | QUERIES) KeyModificationValues))

AppendModifier ::= APPENDING (((BODY | METHOD | PATH) ModificationValue) | (QUERIES KeyModificationValues) | (HEADERS KeyValuePairModificationValues))

ReplaceModifier ::= (REPLACING)? (((BODY | METHOD | PATH) ModificationValue) | (QUERIES KeyModificationValues) | (HEADERS KeyValuePairModificationValues))

ModificationValue ::= COLON (StringLit | VariableReference)

KeyModificationValues ::= COLON (StringLit | VariableReference) (COMMA (StringLit | VariableReference))*

KeyValuePairModificationValues ::= COLON KeyValuePair (COMMA KeyValuePair)*

KeyValuePair ::= (StringLit | VariableReference) COLON (StringLit | VariableReference)

IterableVariableValue ::= Array

NonIterableVariableValue ::= StringLit

RawStringArray ::= RawStringLit (((INTERPOLATABLE_STRING_OPENING_QUOTE | LITERAL_STRING_OPENING_QUOTE) | (COMMA RawStringLit ((INTERPOLATABLE_STRING_OPENING_QUOTE | LITERAL_STRING_OPENING_QUOTE))*)*)

Array ::= (StringLit | VariableReference) (((StringLit | VariableReference)) | ((COMMA (StringLit | VariableReference) ((StringLit | VariableReference))*)*))

StringLit ::= (InterpolatableString | RawStr)

RawStringLit ::= RawStr

RegexStringLit ::= RawStr

InterpolatableString ::= INTERPOLATABLE_STRING_OPENING_QUOTE (((INTERPOLATABLE_STRING_LITERAL | VariableReference | UNKNOWN)+ INTERPOLATABLE_STRING_CLOSING_QUOTE) | INTERPOLATABLE_STRING_CLOSING_QUOTE)

RawStr ::= LITERAL_STRING_OPENING_QUOTE (((LITERAL_STRING)+ LITERAL_STRING_CLOSING_QUOTE) | LITERAL_STRING_CLOSING_QUOTE)

VariableReference ::= VARIABLE_START VariableComponent VARIABLE_END

VariableComponent ::= (Function | VariableObject)

VariableObject ::= VARIABLE_NAME (DOT ((REQUEST_OBJECT (DOT VariableRequestProperty)?) | (RESPONSE_OBJECT (DOT VariableResponseProperty)?)))?

VariableRequestProperty ::= (REQUEST_SPECIFIC_PROPERTY | REQUEST_RESPONSE_COMMON_PROPERTY | VariableUrlProperty)

VariableResponseProperty ::= (RESPONSE_SPECIFIC_PROPERTY | REQUEST_RESPONSE_COMMON_PROPERTY | VariableUrlProperty)

VariableUrlProperty ::= URL (DOT URL_PROPERTY)?

BooleanFunction ::= BOOL_NOT

BooleanOperand ::= (BOOL_AND | BOOL_OR)
Clone this wiki locally