Documentation ¶
Index ¶
- Variables
- func GetComparator(ts *TokenStream) (query.ComparatorType, error)
- func ParseObjectTypeStrings(typeslice []string) (map[engine.ObjectType]struct{}, error)
- func ResolveWithOptions(resolver AQLresolver, opts ResolverOptions) (*graph.Graph[*engine.Object, engine.EdgeBitmap], error)
- func TokenIDStrings() []string
- type AQLquery
- type AQLqueryUnion
- type AQLresolver
- type EdgeMatcher
- type EdgeSearcher
- type FirstLimiter
- type IndexLookup
- type NodeLimiter
- type NodeMatcher
- type NodeQuery
- type NodeSorter
- type NodeSorterImpl
- type QueryDefinition
- type QueryMode
- type ResolverOptions
- type SkipLimiter
- type Token
- type TokenID
- type TokenStream
- func (ts *TokenStream) EOF() bool
- func (ts *TokenStream) Next() bool
- func (ts *TokenStream) NextIfIs(id TokenID) bool
- func (ts *TokenStream) PeekNextRawToken() Token
- func (ts *TokenStream) PeekNextToken() Token
- func (ts *TokenStream) Prev() bool
- func (ts *TokenStream) SnarfTextUntil(id TokenID) string
- func (ts *TokenStream) Token() Token
Constants ¶
This section is empty.
Variables ¶
View Source
var (
DefaultQuerySettings = QueryDefinition{
MaxDepth: 99,
}
)
View Source
var Keywords []string // The keyword tokens
View Source
var Lexer *lexmachine.Lexer // The lexer object. Use this to construct a Scanner
View Source
var Literals []string // The tokens representing literal strings
View Source
var ( PredefinedQueries = []QueryDefinition{ { Name: "Who owns your AD? (Reach Domain Admin etc)", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(type=Group)(|(objectSid=S-1-5-32-544)(objectSid=S-1-5-21-*-512)(objectSid=S-1-5-21-*-519)))<-[]{1,10}-end:(type=Person)", Default: true, }, { Name: "Who can DCsync?", Query: "ACYCLIC start:(&(name=DCsync)(type=Callable-Service-Point))<-[]{1,10}-end:(type=Person)", }, { Name: "How to reach machines that have computer accounts with unconstrained delegation (non-DCs)", Query: "ACYCLIC start:(tag=unconstrained)<-[]{1,10}-end:(type=Person)", }, { Name: "What can accounts with no Kerberos preauth requirement reach? (ASREPROAST)", Query: "ACYCLIC start:(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=4194304)(tag=account_active))-[]{1,10}->end:()", }, { Name: "Who can pwn your AD by sideloading a custom DLL on your DC? (Old DCs only)", Query: "ACYCLIC start:(distinguishedname=CN=MicrosoftDNS,CN=System,DC=*)<-[]{1,15}-end:(type=Person)", }, { Name: "Who can dump SAM/SYSTEM or your ntds.dit remotely or via RDP? (Server and Backup Operators)", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(|(objectSid=S-1-5-32-551)(objectSid=S-1-5-32-549)))<-[]{1,10}-end:()", }, { Name: "Enroll in ESC1 vulnerable certificate templates (client auth + pose as anyone)", Query: "ACYCLIC start:(&(type=PKI-Certificate-Template)(msPKI-Certificate-Name-Flag:and:=1)(|(pKIExtendedKeyUsage=1.3.6.1.5.5.7.3.2)(pKIExtendedKeyUsage=1.3.5.1.5.2.3.4)(pKIExtendedKeyUsage=1.3.6.1.4.1.311.20.2.2)(pKIExtendedKeyUsage=2.5.29.37.0)(pKIExtendedKeyUsage:count:=0)))<-[CertificateEnroll]-()-[]{1,10}-end:(type=Person)", }, { Name: "Enroll in ESC15 vulnerable certificate templates (v1 + pose as anyone)", Query: "ACYCLIC start:(&(type=PKI-Certificate-Template)(msPKI-Certificate-Name-Flag:and:=1)(msPKI-Template-Schema-Version=1))<-[CertificateEnroll]-()-[]{1,10}-end:(type=Person)", }, { Name: "What can Domain Users, Authenticated Users and Everyone do?", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(|(objectSid=S-1-5-21-*-513)(objectSid=S-1-5-11)(objectSid=S-1-1-0)))-[]{1,10}->end:()", }, { Name: "Who can dump a virtual DC? (hypervisor/SAN sounding groups)", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(type=Group)(|(name=*vcenter*)(name=*vmware*)(name=*esxi*)(name=*vsan*)(name=*simplivity*)))<-[]{1,10}-end:()", }, { Name: "Who can wipe or access your backups? (backup sounding groups)", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(type=Group)(|(name=*backup*)(name=*veeam*)(name=*tsm*)(name=*tivoli storage*)(name=*rubrik*)(name=*commvault*)))<-[]{1,10}-end:(type=Person)", }, { Name: "Who can change GPOs?", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(type=Group-Policy-Container))<-[]{1,10}-end:(type=Person)", }, { Name: "What can users not required to have a password reach?", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(type=Person)(userAccountControl:1.2.840.113556.1.4.803:=32))-[]{1,10}->end:()", }, { Name: "What can users that can't change password reach?", Query: "ACYCLIC start:(&(type=Person)(userAccountControl:1.2.840.113556.1.4.803:=64))-[]{1,10}->end:()", }, { Name: "What can users with never expiring passwords reach?", Query: "ACYCLIC start:(&(type=Person)(userAccountControl:1.2.840.113556.1.4.803:=65536))-[]{1,10}->end:()", }, { Name: "What can accounts that have a password older than 5 years reach?", Query: "ACYCLIC start:(&(objectClass=Person)(!(pwdLastSet=0))(pwdLastSet:since:<-5Y)(!(userAccountControl:and:=2)))-[]{1,10}->end:()", }, { Name: "What can accounts that have never set a password reach?", Query: "ACYCLIC start:(&(dataLoader=Active Directory)(objectClass=Person)(pwdLastSet=0)(|(logonCount=0)(!(logonCount=*)))(!(userAccountControl:and:=2)))-[]{1,10}->end:()", }, { Name: "Who can control Protected Users?", Query: "ACYCLIC start:(&(type=Group)(distinguishedName=CN=Protected Users,*))<-[]{1,10}-end:(type=Person)", }, { Name: "What can kerberoastable user accounts reach?", Query: "ACYCLIC start:(&(type=Person)(servicePrincipalName=*)(tag=account_active))<-[]{1,10}-end:(type=Person)", }, { Name: "What can large groups (more than 100 members) reach?", Query: "ACYCLIC start:(&(type=Group)(member:count:>100))-[]{1,10}->end:()", }, { Name: "Who can reach Domain Controllers?", Query: "ACYCLIC start:(&(type=Machine)(out=MachineAccount,(&(type=Computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))))<-[]{1,10}-end:(type=Person)", }, { Name: "Who can reach Read-Only Domain Controllers? (RODC)", Query: "ACYCLIC start:(&(type=Machine)(out=MachineAccount,(&(type=Computer)(primaryGroupId=521))))<-[]{1,10}-end:(type=Person)", }, { Name: "Who can reach computers with unconstrained delegation (non DCs)?", Query: "ACYCLIC start:(&(type=Computer)(userAccountControl:1.2.840.113556.1.4.803:=524288)(!userAccountControl:1.2.840.113556.1.4.803:=8192))<-[]{1,10}-end:(type=Person)", }, { Name: "Who can reach computers with constrained delegation (non DCs)?", Query: "ACYCLIC start:(&(objectCategory=computer)(msds-allowedtodelegateto=*)(!userAccountControl:1.2.840.113556.1.4.803:=8192))<-[]{1,10}-end:(type=Person)", }, { Name: "Users that are members of more than 25 groups", Query: "ACYCLIC start:(&(type=Person)(memberOf:count:>10))", }, { Name: "Give me 100 random machines", Query: "ACYCLIC start:(&(type=Machine)(out=MachineAccount,(userAccountControl:1.2.840.113556.1.4.803:=4096))) LIMIT 100", }, } )
View Source
var StaticLexers = map[string]TokenID{ "\\(": LParan, "\\)": RParan, "\\[": LBracket, "\\]": RBracket, "\\{": LBrace, "\\}": RBrace, "\\~": Tilde, "\\=": Equals, "\\<": LessThan, "\\<\\=": LessThanEquals, "\\>": GreaterThan, "\\>\\=": GreaterThanEquals, "\\&": BinaryAnd, "\\|": BinaryOr, "\\^": BinaryNot, "AND": And, "OR": Or, "NOT": Not, "TRUE": True, "FALSE": False, "\\*": Star, "\\/": Slash, "\\!": Exclamation, "\\.": Dot, "\\.\\.": Dotdot, "\\,": Comma, "\\:": Colon, "\\-": EdgeAnyDirection, "\\-\\>": EdgeOut, "\\<\\-": EdgeIn, "MATCH": Match, "IS": Is, "WHERE": Where, "SKIP": Skip, "OFFSET": Offset, "LIMIT": Limit, "ORDER BY": OrderBy, "DESC": Desc, "UNION": Union, `//[^\n]*\n?`: Comment, `/\*([^*]|\r|\n|(\*+([^*/]|\r|\n)))*\*+/`: Comment, `([a-zA-Z]|_)([a-zA-Z0-9]|_|-)*`: Identifier, `\\#([a-zA-Z]|_)([a-zA-Z0-9]|_)+`: HashIdentifier, `\\@([a-zA-Z]|_)([a-zA-Z0-9]|_)+`: AtIdentifier, `( |\t|\n|\r)+`: Whitespace, }
View Source
var TokenIds map[string]int // A map from the token names to their int ids
View Source
var Tokens []string // All of the tokens (including literals and keywords)
Functions ¶
func GetComparator ¶
func GetComparator(ts *TokenStream) (query.ComparatorType, error)
func ParseObjectTypeStrings ¶
func ParseObjectTypeStrings(typeslice []string) (map[engine.ObjectType]struct{}, error)
func ResolveWithOptions ¶
func ResolveWithOptions(resolver AQLresolver, opts ResolverOptions) (*graph.Graph[*engine.Object, engine.EdgeBitmap], error)
func TokenIDStrings ¶
func TokenIDStrings() []string
TokenIDStrings returns a slice of all String values of the enum
Types ¶
type AQLquery ¶
type AQLquery struct { Sources []NodeQuery // count is n Next []EdgeSearcher // count is n-1 Mode QueryMode Shortest bool OverAllProbability engine.Probability // contains filtered or unexported fields }
type AQLqueryUnion ¶
type AQLqueryUnion struct {
// contains filtered or unexported fields
}
Union of multiple queries
func (AQLqueryUnion) Resolve ¶
func (aqlqu AQLqueryUnion) Resolve(opts ResolverOptions) (*graph.Graph[*engine.Object, engine.EdgeBitmap], error)
type AQLresolver ¶
type AQLresolver interface {
Resolve(ResolverOptions) (*graph.Graph[*engine.Object, engine.EdgeBitmap], error)
}
func ParseAQLQuery ¶
func ParseAQLQuery(s string, ao *engine.Objects) (AQLresolver, error)
type EdgeMatcher ¶
type EdgeMatcher struct { Bitmap engine.EdgeBitmap Count int64 // minimum number of edges to match Comparator query.ComparatorType NoTrimEdges bool // don't trim edges to just the filter }
type EdgeSearcher ¶
type EdgeSearcher struct { PathNodeRequirement *NodeQuery // Nodes passed along the way must fulfill this filter FilterEdges EdgeMatcher // match any of these Direction engine.EdgeDirection MinIterations, MaxIterations int // there should be between min and max iterations in the chain ProbabilityValue engine.Probability ProbabilityComparator query.ComparatorType // contains filtered or unexported fields }
type FirstLimiter ¶
type FirstLimiter int
func (FirstLimiter) Limit ¶
func (fl FirstLimiter) Limit(o engine.ObjectSlice) engine.ObjectSlice
type IndexLookup ¶
type IndexLookup struct {
// contains filtered or unexported fields
}
type NodeLimiter ¶
type NodeLimiter interface {
Limit(engine.ObjectSlice) engine.ObjectSlice
}
type NodeMatcher ¶
type NodeQuery ¶
type NodeQuery struct { IndexLookup IndexLookup // Possible start of search, quickly narrows it down Selector query.NodeFilter // Where style boolean approval filter for objects OrderBy NodeSorter // Sorting ReferenceName string // For cross result reference Skip int // Skipping Limit int // Limiting }
type NodeSorter ¶
type NodeSorter interface {
Sort(engine.ObjectSlice) engine.ObjectSlice
}
type NodeSorterImpl ¶
func (NodeSorterImpl) Sort ¶
func (nsi NodeSorterImpl) Sort(o engine.ObjectSlice) engine.ObjectSlice
type QueryDefinition ¶
type QueryDefinition struct { Name string `json:"name"` Query string `json:"query,omitempty"` MaxDepth int `json:"max_depth,omitempty"` MaxOutgoingConnections int `json:"max_outgoing_connections,omitempty"` Default bool `json:"default,omitempty"` MinAccumulatedProbability engine.Probability `json:"min_accumulated_probability,omitempty"` UserDefined bool `json:"user_defined,omitempty"` }
Can return built in queries and user defined persisted queries
func DefaultQueryDefinition ¶
func DefaultQueryDefinition() QueryDefinition
func ParseQueryDefinitionFromPOST ¶
func ParseQueryDefinitionFromPOST(ctx *gin.Context) (QueryDefinition, error)
func (QueryDefinition) ID ¶
func (q QueryDefinition) ID() string
func (QueryDefinition) Resolver ¶
func (qd QueryDefinition) Resolver(ao *engine.Objects) (AQLresolver, error)
Compiles the query and makes it a resolver
type ResolverOptions ¶
type ResolverOptions struct { MaxDepth int `json:"max_depth,omitempty"` MaxOutgoingConnections int `json:"max_outgoing_connections,omitempty"` MinEdgeProbability engine.Probability `json:"min_edge_probability,omitempty"` MinAccumulatedProbability engine.Probability `json:"min_accumulated_probability,omitempty"` PruneIslands bool `json:"prune_islands,omitempty"` NodeLimit int `json:"nodelimit,omitempty"` }
func NewResolverOptions ¶
func NewResolverOptions() ResolverOptions
type SkipLimiter ¶
type SkipLimiter int
func (SkipLimiter) Limit ¶
func (sl SkipLimiter) Limit(o engine.ObjectSlice) engine.ObjectSlice
type TokenID ¶
type TokenID int
const ( Invalid TokenID = iota Star Slash Exclamation Dot Dotdot Comma Colon Equals Tilde LessThan LessThanEquals GreaterThan GreaterThanEquals And Or Xor Not BinaryAnd BinaryOr BinaryNot LParan // ( RParan // ) LBracket // [ RBracket // ] LBrace // { RBrace // } EdgeAnyDirection // - EdgeIn // <- EdgeOut // -> Is Match Where Skip Offset Limit OrderBy Desc Union True False Literal Keyword Whitespace Integer Float UnquotedLDAPString QuotedString // Quoted string Identifier HashIdentifier AtIdentifier Comment MAXTOKEN = Comment )
func TokenIDString ¶
TokenIDString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.
func (TokenID) IsATokenID ¶
IsATokenID returns "true" if the value is listed in the enum definition. "false" otherwise
type TokenStream ¶
type TokenStream struct {
// contains filtered or unexported fields
}
func Parse ¶
func Parse(input string) (*TokenStream, error)
func (*TokenStream) EOF ¶
func (ts *TokenStream) EOF() bool
func (*TokenStream) Next ¶
func (ts *TokenStream) Next() bool
func (*TokenStream) NextIfIs ¶
func (ts *TokenStream) NextIfIs(id TokenID) bool
func (*TokenStream) PeekNextRawToken ¶
func (ts *TokenStream) PeekNextRawToken() Token
func (*TokenStream) PeekNextToken ¶
func (ts *TokenStream) PeekNextToken() Token
func (*TokenStream) Prev ¶
func (ts *TokenStream) Prev() bool
func (*TokenStream) SnarfTextUntil ¶
func (ts *TokenStream) SnarfTextUntil(id TokenID) string
func (*TokenStream) Token ¶
func (ts *TokenStream) Token() Token
Click to show internal directories.
Click to hide internal directories.