Skip to content

Commit b6cda75

Browse files
committed
Avoid failing scans outright when encountering extraction failures
Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
1 parent 5a4eed8 commit b6cda75

6 files changed

Lines changed: 129 additions & 0 deletions

File tree

cmd/mal/mal.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ var (
5050
allFlag bool
5151
concurrencyFlag int
5252
diffImageFlag bool
53+
exitExtractionFlag bool
5354
exitFirstHitFlag bool
5455
exitFirstMissFlag bool
5556
fileRiskChangeFlag bool
@@ -262,6 +263,7 @@ func main() {
262263

263264
mc = malcontent.Config{
264265
Concurrency: concurrency,
266+
ExitExtraction: exitExtractionFlag,
265267
ExitFirstHit: exitFirstHitFlag,
266268
ExitFirstMiss: exitFirstMissFlag,
267269
IgnoreSelf: ignoreSelfFlag,
@@ -287,6 +289,12 @@ func main() {
287289
Usage: "Ignore nothing within a provided scan path",
288290
Destination: &allFlag,
289291
},
292+
&cli.BoolFlag{
293+
Name: "exit-extraction",
294+
Value: true,
295+
Usage: "Exit when encountering file extraction errors",
296+
Destination: &exitExtractionFlag,
297+
},
290298
&cli.BoolFlag{
291299
Name: "exit-first-miss",
292300
Value: false,

pkg/action/archive_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,95 @@ func TestScanArchive(t *testing.T) {
260260
}
261261
}
262262

263+
func extractError(e error) error {
264+
if strings.Contains(e.Error(), "not a valid gzip archive") || strings.Contains(e.Error(), "not a valid zip file") {
265+
return nil
266+
}
267+
return e
268+
}
269+
270+
func TestScanInvalidArchive(t *testing.T) {
271+
t.Parallel()
272+
ctx := slogtest.Context(t)
273+
clog.FromContext(ctx).With("test", "scan_archive")
274+
275+
var out bytes.Buffer
276+
r, err := render.New("json", &out)
277+
if err != nil {
278+
t.Fatalf("render: %v", err)
279+
}
280+
281+
rfs := []fs.FS{rules.FS, thirdparty.FS}
282+
yrs, err := CachedRules(ctx, rfs)
283+
if err != nil {
284+
t.Fatalf("rules: %v", err)
285+
}
286+
287+
mc := malcontent.Config{
288+
Concurrency: runtime.NumCPU(),
289+
ExitExtraction: true,
290+
IgnoreSelf: false,
291+
MinFileRisk: 0,
292+
MinRisk: 0,
293+
Renderer: r,
294+
Rules: yrs,
295+
ScanPaths: []string{
296+
"testdata/17419.zip",
297+
"testdata/joblib_0.9.4.dev0_compressed_cache_size_pickle_py35_np19.gz",
298+
},
299+
}
300+
_, err = Scan(ctx, mc)
301+
err = extractError(err)
302+
if err != nil {
303+
t.Fatal(err)
304+
}
305+
}
306+
307+
func TestScanInvalidArchiveIgnore(t *testing.T) {
308+
t.Parallel()
309+
ctx := slogtest.Context(t)
310+
clog.FromContext(ctx).With("test", "scan_archive")
311+
312+
var out bytes.Buffer
313+
r, err := render.New("json", &out)
314+
if err != nil {
315+
t.Fatalf("render: %v", err)
316+
}
317+
318+
rfs := []fs.FS{rules.FS, thirdparty.FS}
319+
yrs, err := CachedRules(ctx, rfs)
320+
if err != nil {
321+
t.Fatalf("rules: %v", err)
322+
}
323+
324+
mc := malcontent.Config{
325+
Concurrency: runtime.NumCPU(),
326+
ExitExtraction: false,
327+
IgnoreSelf: false,
328+
MinFileRisk: 0,
329+
MinRisk: 0,
330+
Renderer: r,
331+
Rules: yrs,
332+
ScanPaths: []string{
333+
"testdata/17419.zip",
334+
"testdata/joblib_0.9.4.dev0_compressed_cache_size_pickle_py35_np19.gz",
335+
},
336+
}
337+
res, err := Scan(ctx, mc)
338+
if err != nil {
339+
t.Fatal(err)
340+
}
341+
if err := r.Full(ctx, nil, res); err != nil {
342+
t.Fatalf("full: %v", err)
343+
}
344+
345+
got := out.String()
346+
want := "{}\n"
347+
if diff := cmp.Diff(want, got); diff != "" {
348+
t.Errorf("output mismatch: (-want +got):\n%s", diff)
349+
}
350+
}
351+
263352
func TestGetExt(t *testing.T) {
264353
tests := []struct {
265354
path string

pkg/action/scan.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,11 @@ func processArchive(ctx context.Context, c malcontent.Config, rfs []fs.FS, archi
630630

631631
tmpRoot, err := archive.ExtractArchiveToTempDir(ctx, archivePath)
632632
if err != nil {
633+
// Avoid failing an entire scan when encountering problematic archives
634+
// e.g., joblib_0.8.4_compressed_pickle_py27_np17.gz: not a valid gzip archive
635+
if !c.ExitExtraction {
636+
return nil, nil
637+
}
633638
return nil, fmt.Errorf("extract to temp: %w", err)
634639
}
635640
// Ensure that tmpRoot is removed before returning if created successfully

pkg/action/testdata/17419.zip

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Advisory :
2+
3+
4+
Abysssec Public Exploit :
5+
6+
This module exploits a code execution vulnerability in Mozilla
7+
Firefox <= 3.6.16 caused by nsTreeSelection element. The specific flaw
8+
exists within the way Firefox handles user defined functions of
9+
a nsTreeSelection element. When executing the function
10+
invalidateSelection it is possible to free the nsTreeSelection object
11+
that the function operates on. Any further operations on the freed
12+
object can result in remote code execution.this exploit module is only
13+
tested on win7 and used a Another JAVA ROPto defeat DEP/ASLR (due to
14+
there is no more non-aslr module in Firefox) and in my tests works
15+
reliably on Windows7.
16+
17+
there is two version of this exploit XP and 7 and both use different
18+
method that used in MSF Exploit bounty !
19+
20+
XP Version: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/17419-1.zip (nsTreeRange_XP.zip)
21+
Win7 Version: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/17419-2.zip (nsTreeRange_7.zip)
22+
23+
24+
25+
26+
questions / comments : Info [at] abysssec.com
Binary file not shown.

pkg/malcontent/malcontent.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Renderer interface {
2323

2424
type Config struct {
2525
Concurrency int
26+
ExitExtraction bool
2627
ExitFirstHit bool
2728
ExitFirstMiss bool
2829
FileRiskChange bool

0 commit comments

Comments
 (0)