-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fix] Upgraded AWS go-sdk to V2 (only for AWS Canary Token Verification) #3907
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
What part of the change fixes this issue? |
Just migration of aws sdk to v2 and some code in canary.go file |
That was never an issue with the canary flow AFAIk. It was in the normal Access Key / Session Key detector flows. trufflehog/pkg/detectors/aws/access_keys/accesskey.go Lines 280 to 284 in f2dc96e
|
Sorry I misread your comment. Verification of Canary id/secret is the part of access key / session key detector. Few of the customer reported that Live AWS Canary tokens are not being verified which got fixed once I migrated to V2. |
thank you @rgmz for pointing out the usage in access_key.go I should also migrate the code to V2. |
HI @rgmz , Thank you for pointing out that comment. I have replaced that custom API Request code using SDK methods. After that I am not able to reproduce signature related error even using the same Id and multiple secrets with it. Can you do me a favor to review the code and if I have missed any case. TIA 🙇
Note: AWS SessionKey detector is still using the custom API request method. If these changes are good enough, I can work on that part too. |
@zricethezav I also request you to re-review the updated changes. TIA. |
return false, nil, fmt.Errorf("request returned status %d with an unexpected reason (%s: %s)", res.StatusCode, body.Error.Code, body.Error.Message) | ||
} else { | ||
return false, nil, fmt.Errorf("request to %v returned unexpected status %d", res.Request.URL, res.StatusCode) | ||
return false, nil, fmt.Errorf("request returned unexpected error: %s", err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return false, nil, fmt.Errorf("request returned unexpected error: %s", err.Error()) | |
return false, nil, fmt.Errorf("request returned unexpected error: %w", err) |
cfg, err := config.LoadDefaultConfig(ctx, | ||
config.WithRegion(region), | ||
config.WithHTTPClient(s.getClient()), | ||
config.WithCredentialsProvider( | ||
credentials.NewStaticCredentialsProvider(resIDMatch, resSecretMatch, ""), | ||
), | ||
) | ||
if err != nil { | ||
return false, nil, err | ||
} | ||
req.Header.Set("Accept", "application/json") | ||
|
||
// TASK 1: CREATE A CANONICAL REQUEST. | ||
// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html | ||
canonicalURI := "/" | ||
canonicalHeaders := "host:" + host + "\n" | ||
signedHeaders := "host" | ||
algorithm := "AWS4-HMAC-SHA256" | ||
credentialScope := fmt.Sprintf("%s/%s/%s/aws4_request", datestamp, region, service) | ||
|
||
params := req.URL.Query() | ||
params.Add("Action", "GetCallerIdentity") | ||
params.Add("Version", "2011-06-15") | ||
params.Add("X-Amz-Algorithm", algorithm) | ||
params.Add("X-Amz-Credential", resIDMatch+"/"+credentialScope) | ||
params.Add("X-Amz-Date", amzDate) | ||
params.Add("X-Amz-Expires", "30") | ||
params.Add("X-Amz-SignedHeaders", signedHeaders) | ||
|
||
canonicalQuerystring := params.Encode() | ||
payloadHash := aws.GetHash("") // empty payload | ||
canonicalRequest := method + "\n" + canonicalURI + "\n" + canonicalQuerystring + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + payloadHash | ||
|
||
// TASK 2: CREATE THE STRING TO SIGN. | ||
stringToSign := algorithm + "\n" + amzDate + "\n" + credentialScope + "\n" + aws.GetHash(canonicalRequest) | ||
|
||
// TASK 3: CALCULATE THE SIGNATURE. | ||
// https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html | ||
hash := aws.GetHMAC([]byte(fmt.Sprintf("AWS4%s", resSecretMatch)), []byte(datestamp)) | ||
hash = aws.GetHMAC(hash, []byte(region)) | ||
hash = aws.GetHMAC(hash, []byte(service)) | ||
hash = aws.GetHMAC(hash, []byte("aws4_request")) | ||
|
||
signature2 := aws.GetHMAC(hash, []byte(stringToSign)) // Get Signature HMAC SHA256 | ||
signature := hex.EncodeToString(signature2) | ||
|
||
// TASK 4: ADD SIGNING INFORMATION TO THE REQUEST. | ||
params.Add("X-Amz-Signature", signature) | ||
req.Header.Add("Content-type", "application/x-www-form-urlencoded; charset=utf-8") | ||
req.URL.RawQuery = params.Encode() | ||
|
||
client := s.verificationClient | ||
if client == nil { | ||
client = defaultVerificationClient | ||
} | ||
// Create STS client | ||
stsClient := sts.NewFromConfig(cfg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This upgrade addresses an issue where the previous version intermittently returned signature errors, incorrectly marking valid credentials as unverified.
This does not resolve the mentioned issue. I can easily replicate the intermittent behaviour by taking a valid id+secret pair and adding a secondary invalid secret.
STORAGE_ACCESS_KEY_ID=AKIA...
#STORAGE_ACCESS_KEY_SECRET=...
STORAGE_ACCESS_KEY_SECRET=...
Output:
$ ./trufflehog filesystem /tmp/aws.txt
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
✅ Found verified result 🐷🔑
Detector Type: AWS
Decoder Type: PLAIN
...
$ ./trufflehog filesystem /tmp/aws.txt
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
Found unverified result 🐷🔑❓
Detector Type: AWS
Decoder Type: PLAIN
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rgmz after some experiment, I noted that if SaneHttpClient
is used to make calls, AWS returns Invalid Signature
issue. But things work as expected if default AWS SDK client is being used. I tried to use the most simple go http.Client
but invalid signature is appearing with that as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But things work as expected if default AWS SDK client is being used.
By this do you mean omitting config.WithHTTPClient(s.getClient()),
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct.
Yesterday, I was going through the AWS GO SDK documentation. They have provided a recommended way to customize the AWS HTTP client. Link. Few of the properties are allowed to be modified. I am trying that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, I noted that SaneHttpClient
is modifying two parts via http.Transport
layer.
- Modify connection related properties like
KeepAlive
ormaxIdleConnection
etc. These can be override in AWS http client. - Customized
User-Agent
: SDK does not provide any interface to do that directly view Http Client. The recommended way to override the agent is using the AWS Middleware. Which is not part of the HTTP client.
From documentation perspective, Both of the modification is doable via AWS SDK. I need to try out to see the results.
… returning errors randomly when verify canary tokens. ran go mod tidy.
SDK has changed the error if the provided Id is invalid, incorporated the handling for that error as well.
passing the user-agent via middleware in aws sdk. remove the hash logic since it was making the AWS Access key test as flaky by randomly generating the incorrect values.
00558c5
to
b906a35
Compare
Hey @rgmz, I have updated the PR and checked the issue you mentioned. The issue is no more reproducible with the changes. What's changed: Input:
Output - First attempt:
Output - Second attempt:
Also, I modified the test as generating the hash was causing flaky output. Sometime, it was getting passed and sometime not.
|
Description:
The AWS SDK for Go (aws-sdk-go) has entered maintenance mode, as noted in its README. This PR upgrades the SDK to v2, specifically for verifying AWS Canary tokens.
This upgrade addresses an issue where the previous version intermittently returned signature errors, incorrectly marking valid credentials as unverified.
Note: This upgrade is limited to AWS Canary token verification. The rest of the codebase will continue using the older AWS SDK version.
Checklist:
make test-community
)?make lint
this requires golangci-lint)?