Path: blob/dev/pkg/operators/matchers/match_test.go
2070 views
package matchers12import (3"testing"45"github.com/Knetic/govaluate"6"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"7"github.com/stretchr/testify/require"8)910func TestWordANDCondition(t *testing.T) {11m := &Matcher{condition: ANDCondition, Words: []string{"a", "b"}}1213isMatched, matched := m.MatchWords("a b", nil)14require.True(t, isMatched, "Could not match words with valid AND condition")15require.Equal(t, m.Words, matched)1617isMatched, matched = m.MatchWords("b", nil)18require.False(t, isMatched, "Could match words with invalid AND condition")19require.Equal(t, []string{}, matched)20}2122func TestRegexANDCondition(t *testing.T) {23m := &Matcher{Type: MatcherTypeHolder{MatcherType: RegexMatcher}, Condition: "and", Regex: []string{"[a-z]{3}", "\\d{2}"}}24err := m.CompileMatchers()25require.Nil(t, err)2627isMatched, matched := m.MatchRegex("abc abcd 123")28require.True(t, isMatched, "Could not match regex with valid AND condition")29require.Equal(t, []string{"abc", "abc", "12"}, matched)3031isMatched, matched = m.MatchRegex("bc 1")32require.False(t, isMatched, "Could match regex with invalid AND condition")33require.Equal(t, []string{}, matched)34}3536func TestORCondition(t *testing.T) {37m := &Matcher{condition: ORCondition, Words: []string{"a", "b"}}3839isMatched, matched := m.MatchWords("a b", nil)40require.True(t, isMatched, "Could not match valid word OR condition")41require.Equal(t, []string{"a"}, matched)4243isMatched, matched = m.MatchWords("b", nil)44require.True(t, isMatched, "Could not match valid word OR condition")45require.Equal(t, []string{"b"}, matched)4647isMatched, matched = m.MatchWords("c", nil)48require.False(t, isMatched, "Could match invalid word OR condition")49require.Equal(t, []string{}, matched)50}5152func TestRegexOrCondition(t *testing.T) {53m := &Matcher{Type: MatcherTypeHolder{MatcherType: RegexMatcher}, Condition: "or", Regex: []string{"[a-z]{3}", "\\d{2}"}}54err := m.CompileMatchers()55require.Nil(t, err)5657isMatched, matched := m.MatchRegex("ab 123")58require.True(t, isMatched, "Could not match valid regex OR condition")59require.Equal(t, []string{"12"}, matched)6061isMatched, matched = m.MatchRegex("bc 1")62require.False(t, isMatched, "Could match invalid regex OR condition")63require.Equal(t, []string{}, matched)64}6566func TestHexEncoding(t *testing.T) {67m := &Matcher{Encoding: "hex", Type: MatcherTypeHolder{MatcherType: WordsMatcher}, Part: "body", Words: []string{"50494e47"}}68err := m.CompileMatchers()69require.Nil(t, err, "could not compile matcher")7071isMatched, matched := m.MatchWords("PING", nil)72require.True(t, isMatched, "Could not match valid Hex condition")73require.Equal(t, m.Words, matched)74}7576func TestMatcher_MatchDSL(t *testing.T) {77compiled, err := govaluate.NewEvaluableExpressionWithFunctions("contains(body, \"{{VARIABLE}}\")", dsl.HelperFunctions)78require.Nil(t, err, "couldn't compile expression")7980m := &Matcher{Type: MatcherTypeHolder{MatcherType: DSLMatcher}, dslCompiled: []*govaluate.EvaluableExpression{compiled}}81err = m.CompileMatchers()82require.Nil(t, err, "could not compile matcher")8384values := []string{"PING", "pong"}8586for value := range values {87isMatched := m.MatchDSL(map[string]interface{}{"body": value, "VARIABLE": value})88require.True(t, isMatched)89}90}9192func TestMatcher_MatchXPath_HTML(t *testing.T) {93body := `<!doctype html>94<html>95<head>96<title>Example Domain</title>9798<meta charset="utf-8" />99<meta http-equiv="Content-type" content="text/html; charset=utf-8" />100<meta name="viewport" content="width=device-width, initial-scale=1" />101</head>102103<body>104<div>105<h1>Example Domain</h1>106<p>This domain is for use in illustrative examples in documents. You may use this107domain in literature without prior coordination or asking for permission.</p>108<p><a href="https://www.iana.org/domains/example">More information...</a></p>109</div>110</body>111</html>112`113body2 := `<!doctype html>114<html>115<head>116<title>Example Domain</title>117</head>118<body>119<h1> It's test time! </h1>120</body>121</html>122`123124// single match125m := &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"/html/body/div/p[2]/a"}}126err := m.CompileMatchers()127require.Nil(t, err)128129isMatched := m.MatchXPath(body)130require.True(t, isMatched, "Could not match valid XPath")131132isMatched = m.MatchXPath("<h1>aaaaaaaaa")133require.False(t, isMatched, "Could match invalid XPath")134135// OR match136m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "or", XPath: []string{"/html/head/title[contains(text(), 'PATRICAAA')]", "/html/body/div/p[2]/a"}}137err = m.CompileMatchers()138require.Nil(t, err)139140isMatched = m.MatchXPath(body)141require.True(t, isMatched, "Could not match valid multi-XPath with OR condition")142143isMatched = m.MatchXPath(body2)144require.False(t, isMatched, "Could match invalid multi-XPath with OR condition")145146// AND match147m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "and", XPath: []string{"/html/head/title[contains(text(), 'Example Domain')]", "/html/body/div/p[2]/a"}}148err = m.CompileMatchers()149require.Nil(t, err)150151isMatched = m.MatchXPath(body)152require.True(t, isMatched, "Could not match valid multi-XPath with AND condition")153154isMatched = m.MatchXPath(body2)155require.False(t, isMatched, "Could match invalid multi-XPath with AND condition")156157// invalid xpath158m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//a[@a==1]"}}159_ = m.CompileMatchers()160isMatched = m.MatchXPath(body)161require.False(t, isMatched, "Invalid xpath did not return false")162}163164func TestMatcher_MatchXPath_XML(t *testing.T) {165body := `<?xml version="1.0" encoding="utf-8"?><foo>bar</foo><wibble id="1" /><parent><child>baz</child></parent>`166body2 := `<?xml version="1.0" encoding="utf-8"?><test>bar</test><wibble2 id="1" /><roditelj><dijete>alo</dijete></roditelj>`167168// single match169m := &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//foo[contains(text(), 'bar')]"}}170err := m.CompileMatchers()171require.Nil(t, err)172173isMatched := m.MatchXPath(body)174require.True(t, isMatched, "Could not match valid XPath")175176isMatched = m.MatchXPath("<h1>aaaaaaaaa</h1>")177require.False(t, isMatched, "Could match invalid XPath")178179// OR match180m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "or", XPath: []string{"/foo[contains(text(), 'PATRICAAA')]", "/parent/child"}}181err = m.CompileMatchers()182require.Nil(t, err)183184isMatched = m.MatchXPath(body)185require.True(t, isMatched, "Could not match valid multi-XPath with OR condition")186187isMatched = m.MatchXPath(body2)188require.False(t, isMatched, "Could match invalid multi-XPath with OR condition")189190// AND match191m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, Condition: "and", XPath: []string{"/foo[contains(text(), 'bar')]", "/parent/child"}}192err = m.CompileMatchers()193require.Nil(t, err)194195isMatched = m.MatchXPath(body)196require.True(t, isMatched, "Could not match valid multi-XPath with AND condition")197198isMatched = m.MatchXPath(body2)199require.False(t, isMatched, "Could match invalid multi-XPath with AND condition")200201// invalid xpath202m = &Matcher{Type: MatcherTypeHolder{MatcherType: XPathMatcher}, XPath: []string{"//a[@a==1]"}}203_ = m.CompileMatchers()204isMatched = m.MatchXPath(body)205require.False(t, isMatched, "Invalid xpath did not return false")206207// invalid xml208isMatched = m.MatchXPath("<h1> not right <q id=2/>notvalid")209require.False(t, isMatched, "Invalid xpath did not return false")210}211212213