Compare commits

..

6 Commits

5 changed files with 972 additions and 958 deletions

View File

@ -55,13 +55,8 @@ snapcrafts:
license: MIT
apps:
hetty:
plugs: ["home", "network", "network-bind", "personal-files"]
plugs:
personal-files:
read:
- $HOME/.hetty
write:
- $HOME/.hetty
command: hetty
plugs: ["network", "network-bind"]
scoop:
bucket:

View File

@ -17,6 +17,7 @@ features tailored to the needs of the infosec and bug bounty community.
- Machine-in-the-middle (MITM) HTTP proxy, with logs and advanced search
- HTTP client for manually creating/editing requests, and replay proxied requests
- Intercept requests and responses for manual review (edit, send/receive, cancel)
- Scope support, to help keep work organized
- Easy-to-use web based admin interface
- Project based database storage, to help keep work organized
@ -50,11 +51,6 @@ brew install hettysoft/tap/hetty
sudo snap install hetty
```
⚠️ As of Sun 6 Mar 2022, we're awaiting Canonical to approve the necessary
Snapcraft privileges to allow Hetty to bind on a port. In the meantime, please
use one of the Linux [releases](https://github.com/dstotijn/hetty/releases) on
Github.
#### Windows
```sh

View File

@ -16,6 +16,7 @@ import {
TextFieldProps,
Typography,
} from "@mui/material";
import MaterialLink from "@mui/material/Link";
import { SwitchBaseProps } from "@mui/material/internal/SwitchBase";
import { useEffect, useState } from "react";
@ -217,7 +218,13 @@ export default function Settings(): JSX.Element {
onChange={(e) => setInterceptReqFilter(e.target.value)}
/>
<FormHelperText>
Filter expression to match incoming requests on. When set, only matching requests are intercepted.
Filter expression to match incoming requests on. When set, only matching requests are intercepted.{" "}
<MaterialLink
href="https://hetty.xyz/docs/guides/intercept?utm_source=hettyapp#request-filter"
target="_blank"
>
Read docs.
</MaterialLink>
</FormHelperText>
</FormControl>
<Button
@ -266,7 +273,13 @@ export default function Settings(): JSX.Element {
onChange={(e) => setInterceptResFilter(e.target.value)}
/>
<FormHelperText>
Filter expression to match received responses on. When set, only matching responses are intercepted.
Filter expression to match received responses on. When set, only matching responses are intercepted.{" "}
<MaterialLink
href="https://hetty.xyz/docs/guides/intercept/?utm_source=hettyapp#response-filter"
target="_blank"
>
Read docs.
</MaterialLink>
</FormHelperText>
</FormControl>
<Button

File diff suppressed because it is too large Load Diff

212
pkg/search/ast_test.go Normal file
View File

@ -0,0 +1,212 @@
package search_test
import (
"regexp"
"testing"
"github.com/dstotijn/hetty/pkg/search"
)
func TestExpressionString(t *testing.T) {
t.Parallel()
tests := []struct {
name string
expression search.Expression
expected string
}{
{
name: "string literal expression",
expression: search.StringLiteral{Value: "foobar"},
expected: `"foobar"`,
},
{
name: "boolean expression with equal operator",
expression: search.InfixExpression{
Operator: search.TokOpEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" = "bar")`,
},
{
name: "boolean expression with not equal operator",
expression: search.InfixExpression{
Operator: search.TokOpNotEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" != "bar")`,
},
{
name: "boolean expression with greater than operator",
expression: search.InfixExpression{
Operator: search.TokOpGt,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" > "bar")`,
},
{
name: "boolean expression with less than operator",
expression: search.InfixExpression{
Operator: search.TokOpLt,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" < "bar")`,
},
{
name: "boolean expression with greater than or equal operator",
expression: search.InfixExpression{
Operator: search.TokOpGtEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" >= "bar")`,
},
{
name: "boolean expression with less than or equal operator",
expression: search.InfixExpression{
Operator: search.TokOpLtEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" <= "bar")`,
},
{
name: "boolean expression with regular expression operator",
expression: search.InfixExpression{
Operator: search.TokOpRe,
Left: search.StringLiteral{Value: "foo"},
Right: search.RegexpLiteral{regexp.MustCompile("bar")},
},
expected: `("foo" =~ "bar")`,
},
{
name: "boolean expression with not regular expression operator",
expression: search.InfixExpression{
Operator: search.TokOpNotRe,
Left: search.StringLiteral{Value: "foo"},
Right: search.RegexpLiteral{regexp.MustCompile("bar")},
},
expected: `("foo" !~ "bar")`,
},
{
name: "boolean expression with AND, OR and NOT operators",
expression: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.StringLiteral{Value: "foo"},
Right: search.InfixExpression{
Operator: search.TokOpOr,
Left: search.StringLiteral{Value: "bar"},
Right: search.PrefixExpression{
Operator: search.TokOpNot,
Right: search.StringLiteral{Value: "baz"},
},
},
},
expected: `("foo" AND ("bar" OR (NOT "baz")))`,
},
{
name: "boolean expression with nested group",
expression: search.InfixExpression{
Operator: search.TokOpOr,
Left: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
Right: search.PrefixExpression{
Operator: search.TokOpNot,
Right: search.StringLiteral{Value: "baz"},
},
},
expected: `(("foo" AND "bar") OR (NOT "baz"))`,
},
{
name: "implicit boolean expression with string literal operands",
expression: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
Right: search.StringLiteral{Value: "baz"},
},
expected: `(("foo" AND "bar") AND "baz")`,
},
{
name: "implicit boolean expression nested in group",
expression: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
expected: `("foo" AND "bar")`,
},
{
name: "implicit and explicit boolean expression with string literal operands",
expression: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.StringLiteral{Value: "foo"},
Right: search.InfixExpression{
Operator: search.TokOpOr,
Left: search.StringLiteral{Value: "bar"},
Right: search.StringLiteral{Value: "baz"},
},
},
Right: search.StringLiteral{Value: "yolo"},
},
expected: `(("foo" AND ("bar" OR "baz")) AND "yolo")`,
},
{
name: "implicit boolean expression with comparison operands",
expression: search.InfixExpression{
Operator: search.TokOpAnd,
Left: search.InfixExpression{
Operator: search.TokOpEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
Right: search.InfixExpression{
Operator: search.TokOpRe,
Left: search.StringLiteral{Value: "baz"},
Right: search.RegexpLiteral{regexp.MustCompile("yolo")},
},
},
expected: `(("foo" = "bar") AND ("baz" =~ "yolo"))`,
},
{
name: "eq operator takes precedence over boolean ops",
expression: search.InfixExpression{
Operator: search.TokOpOr,
Left: search.InfixExpression{
Operator: search.TokOpEq,
Left: search.StringLiteral{Value: "foo"},
Right: search.StringLiteral{Value: "bar"},
},
Right: search.InfixExpression{
Operator: search.TokOpEq,
Left: search.StringLiteral{Value: "baz"},
Right: search.StringLiteral{Value: "yolo"},
},
},
expected: `(("foo" = "bar") OR ("baz" = "yolo"))`,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := tt.expression.String()
if tt.expected != got {
t.Errorf("expected: %v, got: %v", tt.expected, got)
}
})
}
}