Skip to content

Commit 83b1948

Browse files
authored
Merge pull request diffblue#536 from diffblue/jd/feature/entry_point_passthrough_refactor
[SEC-580] Remove class names detection and replace with alternate capabilities
2 parents 10684ba + 6518bf1 commit 83b1948

9 files changed

+67
-40
lines changed

driver/run.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,10 @@ def create_parser():
9292
parser.add_argument("-L", "--libraries", nargs='+', default=[],
9393
help="A list of disk paths to libraries you want to include into class path. A path "
9494
"can either be a path-name of a JAR file, or a directory.")
95-
parser.add_argument("-E", "--entry-point", type=str,
96-
help="Allows you to specify a Java function which will be considered by the analyser as the "
95+
parser.add_argument("-E", "--entry-point", "--entry-points", nargs='+', default=[],
96+
help="Allows you to specify a list of Java functions which will be considered by the analyser as an "
9797
"entry point. Typically, a function of a class implementing javax.servlet.http.HttpServlet "
98-
"is a good candidate. When not specified, all functions of all classes are considered "
99-
"as potential entry points. The function must be fully classified (i.e. with the package "
98+
"is a good candidate. The function must be fully classified (i.e. with the package "
10099
"and class included).")
101100
parser.add_argument("-R", "--results-dir", type=str,
102101
help="A directory into which all results from the analysis of the given Java web applicaton "
@@ -229,17 +228,8 @@ def prepare_scan(cmdline):
229228
configuration["collectedClassesInfoPath"] = \
230229
os.path.join(cmdline.common_dir, "collected_classes_info.json")
231230

232-
# If we have an entry point coming in, just replace all rules.
233231
if cmdline.entry_point:
234-
class_name, method_name = cmdline.entry_point.rsplit('.', 1)
235-
configuration["patternGroup"] = \
236-
[{
237-
"id": "General",
238-
"patterns": [{
239-
"methodPattern": {"names": [re.escape(method_name)]},
240-
"classPattern": {"names": [re.escape(class_name)]}
241-
}]
242-
}]
232+
configuration["entryPoints"] = cmdline.entry_point
243233

244234
print("Copying config and updating with generated values.")
245235

@@ -369,10 +359,6 @@ def __main():
369359
"a WAR file: " + os.path.abspath(cmdline.input_path))
370360
return
371361

372-
if cmdline.entry_point is not None and len(cmdline.entry_point) == 0:
373-
print("ERROR[--entry-point (-E)]: The entry point is empty. It must represent a fully classified function nane.")
374-
return
375-
376362
if cmdline.results_dir is None:
377363
print("ERROR[--results-dir (-R)]: The root directory where all results from the analysis should be saved into "
378364
"was not specified.")

src/java-class-info/class_pattern.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,11 @@
44

55
bool class_patternt::is_empty() const
66
{
7-
return names.empty() && annotations.empty() && extends.empty() &&
8-
implements.empty();
7+
return annotations.empty() && extends.empty() && implements.empty();
98
}
109

1110
class_patternt::class_patternt(const jsont &json)
1211
{
13-
for(const jsont &element : json[json_namest::names].array)
14-
{
15-
names.emplace_back(element.value);
16-
}
17-
1812
for(const jsont &element : json[json_namest::extends].array)
1913
{
2014
extends.push_back(element.value);

src/java-class-info/class_pattern.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ class class_patternt
1717

1818
explicit class_patternt(const jsont &j);
1919

20-
std::vector<std::regex> names;
2120
std::vector<std::string> extends;
2221
std::vector<std::string> implements;
2322
std::vector<std::string> annotations;
@@ -30,7 +29,6 @@ class class_patternt
3029
class json_namest
3130
{
3231
public:
33-
static constexpr const char *names = "names";
3432
static constexpr const char *extends = "extends";
3533
static constexpr const char *implements = "implements";
3634
static constexpr const char *annotations = "annotations";

src/java-class-info/default_config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"collectedClassesInfoPath": "",
44
"detectedEntryPointsPath": "",
55
"diConfigurationPath": "",
6+
"entryPoints": [],
67
"patternGroup": [
78
{
89
"id": "Spring MVC",

src/java-class-info/default_config.schema.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@
2525
"default": ""
2626
},
2727

28+
"entryPoints": {
29+
"type": "array",
30+
"description": "An array of fully-qualified entry-points that the system should use instead of detection."
31+
"items": {
32+
"type": "string",
33+
"description": "An individual entry-point to look at."
34+
}
35+
},
36+
2837
"patternGroup": {
2938
"type": "array",
3039
"description": "A pattern group is a set of class and method patterns that when considered together are used by a certain framework or technique to signify a website / web service entry-point.",
@@ -91,14 +100,6 @@
91100
"additionalProperties": false,
92101
"properties": {
93102

94-
"names": {
95-
"type": "array",
96-
"description": "An array of regular expressions that the class should match. Only one match needs to be found.",
97-
"items": {
98-
"type": "string"
99-
}
100-
},
101-
102103
"extends": {
103104
"type": "array",
104105
"description": "An array of fully-qualified classes that the class extend from. Only one match needs to be found.",

src/java-class-info/entry_point_detection.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ void entry_point_detectiont::find_entry_points(
155155
{
156156
const java_bytecode_parse_treet::classt &parsed_class =
157157
parse_tree.parsed_class;
158+
159+
if(this->entry_points.empty())
160+
search_for_entry_points(parsed_class);
161+
else
162+
find_static_entry_points(parsed_class);
163+
}
164+
165+
/// Use the patterns we've been given to search for valid entry-points
166+
/// in the target systems source.
167+
void entry_point_detectiont::search_for_entry_points(
168+
const java_bytecode_parse_treet::classt &parsed_class)
169+
{
158170
const std::string &class_name = id2string(parsed_class.name);
159171

160172
// for each group and pattern in those groups.
@@ -166,9 +178,6 @@ void entry_point_detectiont::find_entry_points(
166178
const class_patternt &class_patterns = pattern.class_patterns;
167179
if(!class_patterns.is_empty())
168180
{
169-
if(!match_name(class_patterns.names, class_name))
170-
continue;
171-
172181
if(
173182
!match_extends(
174183
class_patterns.extends, id2string(parsed_class.super_class)))
@@ -249,3 +258,25 @@ void entry_point_detectiont::find_entry_points(
249258
}
250259
}
251260
}
261+
262+
/// Attempt a search through any direct entry-points that we've been passed.
263+
void entry_point_detectiont::find_static_entry_points(
264+
const java_bytecode_parse_treet::classt &parsed_class)
265+
{
266+
const std::string &class_name = id2string(parsed_class.name);
267+
for(const methodt &parsed_method : parsed_class.methods)
268+
{
269+
const std::string method_name = class_name + "." + id2string(parsed_method.name);
270+
const std::string method_signature =
271+
method_name + ":" + (parsed_method.signature.has_value()
272+
? parsed_method.signature.value()
273+
: parsed_method.descriptor);
274+
275+
if(
276+
this->entry_points.find(method_name) != entry_points.end() ||
277+
this->entry_points.find(method_signature) != entry_points.end())
278+
{
279+
detected_entry_points.emplace_back(class_name, parsed_method);
280+
}
281+
}
282+
}

src/java-class-info/entry_point_detection.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ class entry_point_detectiont
1515
{
1616
public:
1717
entry_point_detectiont(generation_configurationt &config, messaget &message)
18-
: pattern_group(config.pattern_group), log(message)
18+
: entry_points(config.entry_points),
19+
pattern_group(config.pattern_group),
20+
log(message)
1921
{
2022
}
2123

2224
bool enabled()
2325
{
24-
return !pattern_group.empty();
26+
return !pattern_group.empty() || !entry_points.empty();
2527
}
2628

2729
void find_entry_points(java_bytecode_parse_treet &parse_tree);
@@ -32,7 +34,13 @@ class entry_point_detectiont
3234
}
3335

3436
private:
37+
void search_for_entry_points(
38+
const java_bytecode_parse_treet::classt &parse_tree);
39+
void find_static_entry_points(
40+
const java_bytecode_parse_treet::classt &parse_tree);
41+
3542
detected_entry_pointst detected_entry_points;
43+
std::set<std::string> entry_points;
3644
std::vector<pattern_groupt> pattern_group;
3745
messaget log;
3846
};

src/java-class-info/generation_configuration.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ generation_configurationt::generation_configurationt(const jsont &json)
1515
{
1616
pattern_group.emplace_back(element);
1717
}
18+
for(const jsont &element : json[json_namest::entry_points].array)
19+
{
20+
entry_points.insert(element.value);
21+
}
22+
1823
if(!pattern_group.empty())
1924
{
2025
if(detected_entry_points_path.empty())

src/java-class-info/generation_configuration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define SECURITY_SCANNER_GENERATION_CONFIGURATIONT_H
55

66
#include "pattern_group.h"
7+
#include <set>
78
#include <optional.h>
89

910
/// Object representation of the main configuration file used to drive
@@ -14,6 +15,7 @@ class generation_configurationt
1415
explicit generation_configurationt(const jsont &json);
1516

1617
std::vector<pattern_groupt> pattern_group;
18+
std::set<std::string> entry_points;
1719
std::string collected_classes_path;
1820
std::string collected_classes_info_path;
1921
std::string detected_entry_points_path;
@@ -38,6 +40,7 @@ class generation_configurationt
3840
static constexpr const char *detected_entry_points_path =
3941
"detectedEntryPointsPath";
4042
static constexpr const char *di_configuration_path = "diConfigurationPath";
43+
static constexpr const char *entry_points = "entryPoints";
4144
};
4245

4346
std::vector<std::string> errors;

0 commit comments

Comments
 (0)