-
Notifications
You must be signed in to change notification settings - Fork 61
feat: add urls (http+https) to json report #681
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
*.dll | ||
*.so | ||
*.dylib | ||
|
||
.idea | ||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,14 +2,17 @@ package dynamicanalysis | |
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/ossf/package-analysis/internal/analysis" | ||
"github.com/ossf/package-analysis/internal/dnsanalyzer" | ||
"github.com/ossf/package-analysis/internal/log" | ||
"github.com/ossf/package-analysis/internal/packetcapture" | ||
"github.com/ossf/package-analysis/internal/sandbox" | ||
"github.com/ossf/package-analysis/internal/strace" | ||
"github.com/ossf/package-analysis/pkg/api/analysisrun" | ||
"io/ioutil" | ||
"os/exec" | ||
"strings" | ||
"syscall" | ||
) | ||
|
||
const ( | ||
|
@@ -20,6 +23,7 @@ const ( | |
type Result struct { | ||
StraceSummary analysisrun.StraceSummary | ||
FileWrites analysisrun.FileWrites | ||
URLs []string | ||
} | ||
|
||
var resultError = &Result{ | ||
|
@@ -28,6 +32,24 @@ var resultError = &Result{ | |
}, | ||
} | ||
|
||
func ParseURLsFromSSlStripOutput(content []byte) []string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it is worth de-duping URLs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could do this further downstream? (i.e. during reporting) - having all the original data could be useful for some cases There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's very useful to have the raw data as it will allow us to analyze it and search for data such as exfiltrated secrets for example, nevertheless, we ought to have the URLS in the report as some addresses are proven IOC's. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be more efficient if this method took an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you still have to parse it so you ought to read the file. |
||
var result []string | ||
ret := strings.Split(string(content), "\n") | ||
|
||
for _, value := range ret { | ||
lineParts := strings.Split(value, " ") | ||
if len(lineParts) < 11 { | ||
continue | ||
} | ||
|
||
schema := lineParts[3] | ||
host := lineParts[8] | ||
path := lineParts[10] | ||
result = append(result, schema+"://"+host+path) | ||
Comment on lines
+41
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be useful having an example line from the log here so readers can understand what is being parsed. |
||
} | ||
return result | ||
} | ||
|
||
func Run(sb sandbox.Sandbox, args []string) (*Result, error) { | ||
log.Info("Running dynamic analysis", | ||
"args", args) | ||
|
@@ -45,11 +67,58 @@ func Run(sb sandbox.Sandbox, args []string) (*Result, error) { | |
// Run the command | ||
log.Debug("Running dynamic analysis command", | ||
"args", args) | ||
|
||
log.Debug("Reroute all http traffic through sslsplit") | ||
iptables := exec.Command("iptables", "-t", "nat", "-A", "PREROUTING", "-i", "cni-analysis", "-p", "tcp", "--dport", "80", "-j", "REDIRECT", "--to-port", "8081") | ||
err := iptables.Start() | ||
|
||
if err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
err = iptables.Wait() | ||
if err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
|
||
log.Debug("Reroute all https traffic through sslsplit") | ||
iptables = exec.Command("iptables", "-t", "nat", "-A", "PREROUTING", "-i", "cni-analysis", "-p", "tcp", "--dport", "443", "-j", "REDIRECT", "--to-port", "8080") | ||
Comment on lines
+72
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I think that either these two rules can be added to a However, it may be desirable to only optionally enable SSLSplit, in which case it would be ideal if these two rules were removed after the sandbox exits (even better if it had a |
||
err = iptables.Start() | ||
|
||
if err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
err = iptables.Wait() | ||
if err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
|
||
log.Debug("starting sslsplit") | ||
sslsplit := exec.Command("sslsplit", "-d", "-L", "/tmp/ssl.flow", "-l", "/tmp/sslLinks.flow", "-k", "/proxy/certs/ca.pem", "-c", "/proxy/certs/ca.crt", "http", "0.0.0.0", "8081", "https", "0.0.0.0", "8080") | ||
Alik-Kold marked this conversation as resolved.
Show resolved
Hide resolved
|
||
err = sslsplit.Start() | ||
|
||
if err != nil { | ||
log.Fatal(err.Error()) | ||
} | ||
|
||
r, err := sb.Run(args...) | ||
if err != nil { | ||
return resultError, fmt.Errorf("sandbox failed (%w)", err) | ||
} | ||
|
||
log.Debug("stopping sslsplit") | ||
err = sslsplit.Process.Signal(syscall.SIGINT) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
log.Debug("reading sslsplit results") | ||
body, err1 := ioutil.ReadFile("/tmp/sslLinks.flow") | ||
if err1 != nil { | ||
log.Fatal("unable to read file: %v", err1) | ||
} | ||
|
||
urls := ParseURLsFromSSlStripOutput(body) | ||
|
||
log.Debug("Stop the packet capture") | ||
pcap.Close() | ||
|
||
|
@@ -73,11 +142,11 @@ func Run(sb sandbox.Sandbox, args []string) (*Result, error) { | |
Stderr: lastLines(r.Stderr(), maxOutputLines, maxOutputBytes), | ||
}, | ||
} | ||
analysisResult.setData(straceResult, dns) | ||
analysisResult.setData(straceResult, dns, urls) | ||
return &analysisResult, nil | ||
} | ||
|
||
func (d *Result) setData(straceResult *strace.Result, dns *dnsanalyzer.DNSAnalyzer) { | ||
func (d *Result) setData(straceResult *strace.Result, dns *dnsanalyzer.DNSAnalyzer, sslSplitResult []string) { | ||
for _, f := range straceResult.Files() { | ||
d.StraceSummary.Files = append(d.StraceSummary.Files, analysisrun.FileResult{ | ||
Path: f.Path, | ||
|
@@ -121,4 +190,5 @@ func (d *Result) setData(straceResult *strace.Result, dns *dnsanalyzer.DNSAnalyz | |
} | ||
d.StraceSummary.DNS = append(d.StraceSummary.DNS, c) | ||
} | ||
d.URLs = sslSplitResult | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,7 +89,7 @@ type Sandbox interface { | |
// The result of the supplied command will be returned in an instance of | ||
// RunResult. | ||
Run(...string) (*RunResult, error) | ||
|
||
UploadFileToContainer(srcFile string, destFile string) *exec.Cmd | ||
Alik-Kold marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Clean cleans up a Sandbox. | ||
// | ||
// Once called the Sandbox cannot be used again. | ||
|
@@ -127,6 +127,16 @@ type podmanSandbox struct { | |
volumes []volume | ||
} | ||
|
||
func (s *podmanSandbox) UploadFileToContainer(srcFile string, destFile string) *exec.Cmd { | ||
destParam := fmt.Sprintf("%s:%s", s.container, destFile) | ||
args := []string{ | ||
"cp", | ||
srcFile, | ||
destParam, | ||
} | ||
return podman(args...) | ||
} | ||
|
||
type ( | ||
Option interface{ set(*podmanSandbox) } | ||
option func(*podmanSandbox) // option implements Option. | ||
|
@@ -428,6 +438,14 @@ func (s *podmanSandbox) Run(args ...string) (*RunResult, error) { | |
} | ||
errWriter := io.MultiWriter(errWriters...) | ||
|
||
log.Debug("upload certs to container") | ||
uploadCmd := s.UploadFileToContainer("/proxy/certs/ca.crt", "/usr/local/share/ca-certificates/ca.crt") //upload certs to container | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than hardcoding the input cert location, I suggest creating an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please take a look at the new |
||
uploadCmd.Stdout = logOut | ||
uploadCmd.Stderr = logErr | ||
if err := uploadCmd.Run(); err != nil { | ||
return result, fmt.Errorf("error uploading file to container: %w", err) | ||
} | ||
|
||
// Start the container | ||
startCmd := s.startContainerCmd(logDir) | ||
startCmd.Stdout = logOut | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,17 @@ | |
*filter | ||
:INPUT ACCEPT [0:0] | ||
:CNI-ADMIN - [0:0] | ||
|
||
# SSLSplit Routing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll need to check that these don't accidentally allow the sandbox to bypass the rules below for the given ports. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These rules do allow traffic heading to ports 80,443,8080,8081 to hit the blocked addresses below. Please update these rules so that they don't allow the rules at the bottom to be bypassed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I spent some time today playing with this and have found a way to ensure undesired traffic is not inadvertently able to bypass the filter. Basically, we add PREROUTING rules to The iptables.rules file I have that works is:
|
||
-A INPUT -p tcp --dport 80 -j ACCEPT | ||
-A OUTPUT -p tcp --dport 80 -j ACCEPT | ||
-A INPUT -p tcp --dport 443 -j ACCEPT | ||
-A OUTPUT -p tcp --dport 443 -j ACCEPT | ||
-A INPUT -p tcp --dport 8081 -j ACCEPT | ||
-A OUTPUT -p tcp --dport 8081 -j ACCEPT | ||
-A INPUT -p tcp --dport 8080 -j ACCEPT | ||
-A OUTPUT -p tcp --dport 8080 -j ACCEPT | ||
|
||
# Block access to this host from the container network. | ||
-A INPUT -s 172.16.16.0/24 -j DROP | ||
# Block access to metadata.google.internal/AWS metadata. | ||
|
Uh oh!
There was an error while loading. Please reload this page.