mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 08:25:24 +00:00
* fix template signature verification * fix signature pattern check * add tests * remove signature count constraint, check for lines len * Add more tests * Centralize signature extraction logic in signer package * Move signature handling in Sign function to beginning * Remove comment * Revert `NewTemplateSigVerifier` * update tests * use ExtractSignatureAndContent func * Allow signing code templates * Remove unused const --------- Co-authored-by: Doğan Can Bakır <dogancanbakir@protonmail.com> Co-authored-by: Guy Goldenberg <guy.goldenberg@wiz.io>
127 lines
3.5 KiB
Go
127 lines
3.5 KiB
Go
package signer
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
testCertFile = "../../../integration_tests/protocols/keys/ci.crt"
|
|
testKeyFile = "../../../integration_tests/protocols/keys/ci-private-key.pem"
|
|
)
|
|
|
|
type mockSignableTemplate struct {
|
|
imports []string
|
|
hasCode bool
|
|
}
|
|
|
|
func (m *mockSignableTemplate) GetFileImports() []string {
|
|
return m.imports
|
|
}
|
|
|
|
func (m *mockSignableTemplate) HasCodeProtocol() bool {
|
|
return m.hasCode
|
|
}
|
|
|
|
var signer, _ = NewTemplateSignerFromFiles(testCertFile, testKeyFile)
|
|
|
|
func TestTemplateSignerSignAndVerify(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
|
|
tests := []struct {
|
|
name string
|
|
data []byte
|
|
tmpl SignableTemplate
|
|
wantSignErr bool
|
|
wantVerifyErr bool
|
|
wantVerified bool
|
|
modifyAfterSign func([]byte) []byte
|
|
}{
|
|
{
|
|
name: "Simple template",
|
|
data: []byte("id: test-template\ninfo:\n name: Test Template"),
|
|
tmpl: &mockSignableTemplate{},
|
|
wantVerified: true,
|
|
},
|
|
{
|
|
name: "Template with imports",
|
|
data: []byte("id: test-template\ninfo:\n name: Test Template"),
|
|
tmpl: &mockSignableTemplate{imports: []string{
|
|
filepath.Join(tempDir, "import1.yaml"),
|
|
filepath.Join(tempDir, "import2.yaml"),
|
|
}},
|
|
wantVerified: true,
|
|
},
|
|
{
|
|
name: "Template with code protocol",
|
|
data: []byte("id: test-template\ninfo:\n name: Test Template\n\ncode:\n - engine: bash\n source: echo 'Hello, World!'"),
|
|
tmpl: &mockSignableTemplate{hasCode: true},
|
|
wantSignErr: false,
|
|
wantVerified: true,
|
|
},
|
|
{
|
|
name: "Tampered template",
|
|
data: []byte("id: test-template\ninfo:\n name: Test Template"),
|
|
tmpl: &mockSignableTemplate{},
|
|
modifyAfterSign: func(data []byte) []byte {
|
|
signatureIndex := bytes.LastIndex(data, []byte(SignaturePattern))
|
|
if signatureIndex == -1 {
|
|
return data
|
|
}
|
|
return append(data[:signatureIndex], append([]byte("# Tampered content\n"), data[signatureIndex:]...)...)
|
|
},
|
|
wantVerified: false,
|
|
},
|
|
{
|
|
name: "Invalid signature",
|
|
data: []byte("id: test-template\ninfo:\n name: Test Template"),
|
|
tmpl: &mockSignableTemplate{},
|
|
modifyAfterSign: func(data []byte) []byte {
|
|
return append(bytes.TrimSuffix(data, []byte("\n")), []byte("\n# digest: invalid_signature:fragment")...)
|
|
},
|
|
wantVerifyErr: true,
|
|
wantVerified: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Create import files if needed
|
|
for _, imp := range tt.tmpl.GetFileImports() {
|
|
err := os.WriteFile(imp, []byte("imported content"), 0644)
|
|
require.NoError(t, err, "Failed to create import file")
|
|
}
|
|
|
|
// Sign the template
|
|
signature, err := signer.Sign(tt.data, tt.tmpl)
|
|
if tt.wantSignErr {
|
|
assert.Error(t, err, "Expected an error during signing")
|
|
return
|
|
}
|
|
require.NoError(t, err, "Failed to sign template")
|
|
|
|
// Append signature to the template data
|
|
signedData := append(tt.data, []byte("\n"+signature)...)
|
|
|
|
// Apply any modifications after signing if specified
|
|
if tt.modifyAfterSign != nil {
|
|
signedData = tt.modifyAfterSign(signedData)
|
|
}
|
|
|
|
// Verify the signature
|
|
verified, err := signer.Verify(signedData, tt.tmpl)
|
|
if tt.wantVerifyErr {
|
|
assert.Error(t, err, "Expected an error during verification")
|
|
} else {
|
|
assert.NoError(t, err, "Unexpected error during verification")
|
|
}
|
|
assert.Equal(t, tt.wantVerified, verified, "Unexpected verification result")
|
|
})
|
|
}
|
|
}
|