Skip to content

Commit

Permalink
validate: try multiple exploits for poly vulns
Browse files Browse the repository at this point in the history
Problem:
The detectors are eager to exploit higher-order
polynomially vulnerable regexes.

In doing so they may overstep and cause a match,
so no backtracking is required.

Example:
See discussion in Weideman:
  NicolaasWeideman/RegexStaticAnalysis#11

Solution:
In such a case the lesser polynomials may still be effective.
validate-vuln.pl now iterates over the proposed list of pumpPairs
and tries pumpPairs 1..$i.
If any time out we have a winner.

Fixes: #40

Test:
- Various tests for check-regex

Misc:
- Also fixes issue in check-regex: wrong path to cache-client
  • Loading branch information
davisjam committed Apr 11, 2018
1 parent cbd7640 commit d3f3597
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 23 deletions.
2 changes: 1 addition & 1 deletion bin/check-regex.pl
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ sub queryCache {
"result" => $PATTERN_UNKNOWN,
};

my $cacheClient = "$ENV{VULN_REGEX_DETECTOR_ROOT}/src/cache/client/cache-client.js";
my $cacheClient = "$ENV{VULN_REGEX_DETECTOR_ROOT}/src/cache/client/cli/cache-client.js";
if (not -f $cacheClient) {
&log("queryCache: Could not find client $cacheClient");
return $unknownResponse;
Expand Down
2 changes: 1 addition & 1 deletion bin/test/check-regex/causeDetectorTimeout-1.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"pattern": "(a{1,40}){1,40}$", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2}
{"pattern": "(a{1,40}){1,40}$", "validateVuln_language": "javascript", "detectVuln_timeLimit": 10, "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache":0}
2 changes: 1 addition & 1 deletion bin/test/check-regex/edgecase-1.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"pattern": "0", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2}
{"pattern": "0", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache": 0}
2 changes: 1 addition & 1 deletion bin/test/check-regex/unsafe-1.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"pattern": "(a+)+$", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2}
{"pattern": "(a+)+$", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache": 0}
1 change: 1 addition & 0 deletions bin/test/check-regex/unsafe-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pattern": ".+\\@.+\\..+", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache": 0}
1 change: 1 addition & 0 deletions bin/test/check-regex/unsafe-3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pattern": "(a|a)+$", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache": 0}
1 change: 1 addition & 0 deletions bin/test/check-regex/unsafe-4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pattern": ".+\\@.+\\..+a.+a.+a.+", "validateVuln_language": "javascript", "validateVuln_nPumps": 100000, "validateVuln_timeLimit": 2, "useCache": 0}
48 changes: 29 additions & 19 deletions src/validate/validate-vuln.pl
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,40 @@
$json->{nPumps} = int($json->{nPumps});
$json->{timeLimit} = int($json->{timeLimit});

my $result = $json;
$result->{timedOut} = 0;

# Compute an attackString from evilInput.
my $attackString = "";
for my $pumpPair (@{$json->{evilInput}->{pumpPairs}}) {
$attackString .= $pumpPair->{prefix};
$attackString .= ($pumpPair->{pump} x $json->{nPumps});
}
$attackString .= $json->{evilInput}->{suffix};
# If the detector recommended a cubic or higher (>= 2 pumpPairs), try all polynomial powers
# by working our way up the list of pumpPairs.
# See https://github.com/NicolaasWeideman/RegexStaticAnalysis/issues/11.
my @pumpPairs = @{$json->{evilInput}->{pumpPairs}};
for my $nPumpPairs (1 .. scalar(@pumpPairs)) {
my $attackString = "";
for my $pumpPair (@pumpPairs[0 .. $nPumpPairs-1]) {
$attackString .= $pumpPair->{prefix};
$attackString .= ($pumpPair->{pump} x $json->{nPumps});
}
$attackString .= $json->{evilInput}->{suffix};

# Prep an input file.
my $input = { "pattern" => $json->{pattern},
"input" => $attackString,
};
my $tmpFile = "/tmp/validate-vuln-$$.json";
&writeToFile("file"=>$tmpFile, "contents"=>encode_json($input));
# Prep an input file.
my $input = { "pattern" => $json->{pattern},
"input" => $attackString,
};
my $tmpFile = "/tmp/validate-vuln-$$.json";
&writeToFile("file"=>$tmpFile, "contents"=>encode_json($input));

# Invoke the appropriate validator.
my $validator = $language2validator{$json->{language}};
# Invoke the appropriate validator.
my $validator = $language2validator{$json->{language}};

my ($rc, $out) = &cmd("timeout $json->{timeLimit}s $validator $tmpFile");
unlink $tmpFile;
my $timedOut = ($rc eq 124) ? 1 : 0;
my ($rc, $out) = &cmd("timeout $json->{timeLimit}s $validator $tmpFile");
unlink $tmpFile;
my $timedOut = ($rc eq 124) ? 1 : 0;

my $result = $json;
$result->{timedOut} = $timedOut;
if ($timedOut) {
$result->{timedOut} = 1;
}
}

print STDOUT encode_json($result) . "\n";
exit 0;
Expand Down

0 comments on commit d3f3597

Please sign in to comment.