mirror of
https://github.com/dstotijn/hetty.git
synced 2025-07-01 18:47:29 -04:00
Compare commits
6 Commits
add-interc
...
v0.7.0
Author | SHA1 | Date | |
---|---|---|---|
d3246b0918 | |||
61fd3fcc45 | |||
d34258dfd1 | |||
0e9fb0ac91 | |||
02408b5196 | |||
6ffc55cde3 |
@ -55,13 +55,8 @@ snapcrafts:
|
|||||||
license: MIT
|
license: MIT
|
||||||
apps:
|
apps:
|
||||||
hetty:
|
hetty:
|
||||||
plugs: ["home", "network", "network-bind", "personal-files"]
|
command: hetty
|
||||||
plugs:
|
plugs: ["network", "network-bind"]
|
||||||
personal-files:
|
|
||||||
read:
|
|
||||||
- $HOME/.hetty
|
|
||||||
write:
|
|
||||||
- $HOME/.hetty
|
|
||||||
|
|
||||||
scoop:
|
scoop:
|
||||||
bucket:
|
bucket:
|
||||||
|
@ -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
|
- Machine-in-the-middle (MITM) HTTP proxy, with logs and advanced search
|
||||||
- HTTP client for manually creating/editing requests, and replay proxied requests
|
- 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
|
- Scope support, to help keep work organized
|
||||||
- Easy-to-use web based admin interface
|
- Easy-to-use web based admin interface
|
||||||
- Project based database storage, to help keep work organized
|
- Project based database storage, to help keep work organized
|
||||||
@ -50,11 +51,6 @@ brew install hettysoft/tap/hetty
|
|||||||
sudo snap install 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
|
#### Windows
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
TextFieldProps,
|
TextFieldProps,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import MaterialLink from "@mui/material/Link";
|
||||||
import { SwitchBaseProps } from "@mui/material/internal/SwitchBase";
|
import { SwitchBaseProps } from "@mui/material/internal/SwitchBase";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
@ -217,7 +218,13 @@ export default function Settings(): JSX.Element {
|
|||||||
onChange={(e) => setInterceptReqFilter(e.target.value)}
|
onChange={(e) => setInterceptReqFilter(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<FormHelperText>
|
<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>
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
@ -266,7 +273,13 @@ export default function Settings(): JSX.Element {
|
|||||||
onChange={(e) => setInterceptResFilter(e.target.value)}
|
onChange={(e) => setInterceptResFilter(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<FormHelperText>
|
<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>
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<Button
|
<Button
|
||||||
|
1686
admin/yarn.lock
1686
admin/yarn.lock
File diff suppressed because it is too large
Load Diff
212
pkg/search/ast_test.go
Normal file
212
pkg/search/ast_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user