-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add hard limits for number of TSA entries, Tlog entries, and attestat…
…ion subjects/digests (#286) * Merge commit from fork This reduces the capability of an adversary to craft a malicious bundle containing large numbers of these data, which can result in a target verifier process consuming high CPU and memory resources, resulting in an "endless data attack", a type of DoS attack. Fixes GHSA-cq38-jh5f-37mq Signed-off-by: Cody Soyland <[email protected]> * nolint in tests Signed-off-by: Cody Soyland <[email protected]> --------- Signed-off-by: Cody Soyland <[email protected]>
- Loading branch information
1 parent
e50c2d7
commit 01e70e8
Showing
6 changed files
with
156 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,9 +18,12 @@ import ( | |
"bytes" | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"encoding/json" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/in-toto/in-toto-golang/in_toto" | ||
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common" | ||
"github.com/sigstore/sigstore-go/pkg/testing/ca" | ||
"github.com/sigstore/sigstore-go/pkg/verify" | ||
"github.com/stretchr/testify/assert" | ||
|
@@ -94,7 +97,7 @@ func TestSignatureVerifierMessageSignature(t *testing.T) { | |
virtualSigstore, err := ca.NewVirtualSigstore() | ||
assert.NoError(t, err) | ||
|
||
artifact := "Hi, I am an artifact!" | ||
artifact := "Hi, I am an artifact!" //nolint:goconst | ||
entity, err := virtualSigstore.Sign("[email protected]", "issuer", []byte(artifact)) | ||
assert.NoError(t, err) | ||
|
||
|
@@ -113,3 +116,61 @@ func TestSignatureVerifierMessageSignature(t *testing.T) { | |
assert.Error(t, err) | ||
assert.Nil(t, result) | ||
} | ||
|
||
func TestTooManySubjects(t *testing.T) { | ||
virtualSigstore, err := ca.NewVirtualSigstore() | ||
assert.NoError(t, err) | ||
|
||
tooManySubjectsStatement := in_toto.Statement{} | ||
for i := 0; i < 1025; i++ { | ||
tooManySubjectsStatement.Subject = append(tooManySubjectsStatement.Subject, in_toto.Subject{ | ||
Name: fmt.Sprintf("subject-%d", i), | ||
Digest: map[string]string{ | ||
"sha256": "", // actual content of digest does not matter for this test | ||
}, | ||
}) | ||
} | ||
|
||
tooManySubjectsStatementBytes, err := json.Marshal(tooManySubjectsStatement) | ||
assert.NoError(t, err) | ||
|
||
tooManySubjectsEntity, err := virtualSigstore.Attest("[email protected]", "issuer", tooManySubjectsStatementBytes) | ||
assert.NoError(t, err) | ||
|
||
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1)) | ||
assert.NoError(t, err) | ||
|
||
artifact := "Hi, I am an artifact!" //nolint:goconst | ||
_, err = verifier.Verify(tooManySubjectsEntity, verify.NewPolicy(verify.WithArtifact(bytes.NewBufferString(artifact)), verify.WithoutIdentitiesUnsafe())) | ||
assert.ErrorContains(t, err, "too many subjects") | ||
} | ||
|
||
func TestTooManyDigests(t *testing.T) { | ||
virtualSigstore, err := ca.NewVirtualSigstore() | ||
assert.NoError(t, err) | ||
|
||
tooManyDigestsStatement := in_toto.Statement{} | ||
tooManyDigestsStatement.Subject = []in_toto.Subject{ | ||
{ | ||
Name: fmt.Sprintf("subject"), | ||
Digest: make(common.DigestSet), | ||
}, | ||
} | ||
tooManyDigestsStatement.Subject[0].Digest["sha512"] = "" // verifier requires that at least one known hash algorithm is present in the digest map | ||
for i := 0; i < 32; i++ { | ||
tooManyDigestsStatement.Subject[0].Digest[fmt.Sprintf("digest-%d", i)] = "" | ||
} | ||
|
||
tooManySubjectsStatementBytes, err := json.Marshal(tooManyDigestsStatement) | ||
assert.NoError(t, err) | ||
|
||
tooManySubjectsEntity, err := virtualSigstore.Attest("[email protected]", "issuer", tooManySubjectsStatementBytes) | ||
assert.NoError(t, err) | ||
|
||
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1)) | ||
assert.NoError(t, err) | ||
|
||
artifact := "Hi, I am an artifact!" //nolint:goconst | ||
_, err = verifier.Verify(tooManySubjectsEntity, verify.NewPolicy(verify.WithArtifact(bytes.NewBufferString(artifact)), verify.WithoutIdentitiesUnsafe())) | ||
assert.ErrorContains(t, err, "too many digests") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -191,5 +191,33 @@ func TestDuplicateTlogEntries(t *testing.T) { | |
assert.NoError(t, err) | ||
|
||
_, err = verify.VerifyArtifactTransparencyLog(&dupTlogEntity{entity}, virtualSigstore, 1, true, false) | ||
assert.Error(t, err) // duplicate tlog entries should fail to verify | ||
assert.ErrorContains(t, err, "duplicate tlog entries found") // duplicate tlog entries should fail to verify | ||
} | ||
|
||
type tooManyTlogEntriesEntity struct { | ||
*ca.TestEntity | ||
} | ||
|
||
func (e *tooManyTlogEntriesEntity) TlogEntries() ([]*tlog.Entry, error) { | ||
entries, err := e.TestEntity.TlogEntries() | ||
if err != nil { | ||
return nil, err | ||
} | ||
for i := 0; i < 32; i++ { | ||
entries = append(entries, entries[0]) | ||
} | ||
|
||
return entries, nil | ||
} | ||
|
||
func TestMaxAllowedTlogEntries(t *testing.T) { | ||
virtualSigstore, err := ca.NewVirtualSigstore() | ||
assert.NoError(t, err) | ||
|
||
statement := []byte(`{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"customFoo","subject":[{"name":"subject","digest":{"sha256":"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"}}],"predicate":{}}`) | ||
entity, err := virtualSigstore.Attest("[email protected]", "issuer", statement) | ||
assert.NoError(t, err) | ||
|
||
_, err = verify.VerifyArtifactTransparencyLog(&tooManyTlogEntriesEntity{entity}, virtualSigstore, 1, true, false) | ||
assert.ErrorContains(t, err, "too many tlog entries") // too many tlog entries should fail to verify | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,7 +113,7 @@ func TestDuplicateTimestamps(t *testing.T) { | |
assert.NoError(t, err) | ||
|
||
_, err = verify.VerifyTimestampAuthorityWithThreshold(&dupTimestampEntity{entity}, virtualSigstore, 1) | ||
assert.Error(t, err) // duplicate timestamps should fail to verify | ||
assert.ErrorContains(t, err, "duplicate timestamps found") | ||
} | ||
|
||
type badTSASignatureEntity struct { | ||
|
@@ -223,3 +223,31 @@ func TestBadTSACertificateChainOutsideValidityPeriod(t *testing.T) { | |
}) | ||
} | ||
} | ||
|
||
type tooManyTimestampsEntity struct { | ||
*ca.TestEntity | ||
} | ||
|
||
func (e *tooManyTimestampsEntity) Timestamps() ([][]byte, error) { | ||
timestamps, err := e.TestEntity.Timestamps() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for i := 0; i < 32; i++ { | ||
timestamps = append(timestamps, timestamps[0]) | ||
} | ||
|
||
return timestamps, nil | ||
} | ||
|
||
func TestTooManyTimestamps(t *testing.T) { | ||
virtualSigstore, err := ca.NewVirtualSigstore() | ||
assert.NoError(t, err) | ||
|
||
entity, err := virtualSigstore.Attest("[email protected]", "issuer", []byte("statement")) | ||
assert.NoError(t, err) | ||
|
||
_, err = verify.VerifyTimestampAuthorityWithThreshold(&tooManyTimestampsEntity{entity}, virtualSigstore, 1) | ||
assert.ErrorContains(t, err, "too many signed timestamps") | ||
} |