heimdall_tools 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/Guardfile +4 -0
- data/LICENSE.md +9 -0
- data/README.md +122 -0
- data/Rakefile +24 -0
- data/exe/heimdall_tools +14 -0
- data/lib/data/cwe-nist-mapping.csv +195 -0
- data/lib/data/gitkeep +0 -0
- data/lib/data/owasp-nist-mapping.csv +11 -0
- data/lib/heimdall_tools/cli.rb +42 -0
- data/lib/heimdall_tools/command.rb +50 -0
- data/lib/heimdall_tools/fortify_mapper.rb +93 -0
- data/lib/heimdall_tools/help/fortify_mapper.md +5 -0
- data/lib/heimdall_tools/help/sonarqube_mapper.md +5 -0
- data/lib/heimdall_tools/help/zap_mapper.md +5 -0
- data/lib/heimdall_tools/help.rb +9 -0
- data/lib/heimdall_tools/sonarqube_mapper.rb +291 -0
- data/lib/heimdall_tools/version.rb +3 -0
- data/lib/heimdall_tools/zap_mapper.rb +131 -0
- data/lib/heimdall_tools.rb +11 -0
- data/lib/utilities/gitkeep +0 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 16faf735e553864867f8e551ea92b96621eeb415
|
4
|
+
data.tar.gz: 2baa94079e6561d38c5c8511e39691a15d360619
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ba635075511c4299786f38a763625197da934bf3aa72d992c9da464bdfc8f992f7734d26907aaf67aa71c40c9f37f22232e32173e44e7302d06254a788c7a618
|
7
|
+
data.tar.gz: 7dbe62ad30fef7ed3a6eef4570ad5e4500345947013b2d152842c024fbffb4a5bf640f431861443ad49d1d5d99c429db7d39d8149c05c97a2b0e3b69480c2563
|
data/CHANGELOG.md
ADDED
data/Guardfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Licensed under the Apache 2.0 license.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
4
|
+
|
5
|
+
* Redistributions of source code must retain the above copyright/ digital rights legend, this list of conditions and the following Notice.
|
6
|
+
|
7
|
+
* Redistributions in binary form must reproduce the above copyright copyright/ digital rights legend, this list of conditions and the following Notice in the documentation and/or other materials provided with the distribution.
|
8
|
+
|
9
|
+
* Neither the name of The MITRE Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
data/README.md
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# WIP - ALPHA
|
2
|
+
|
3
|
+
# HeimdallTools
|
4
|
+
|
5
|
+
HeimdallTools supplies several methods to convert output from various tools to "Heimdall Data Format"(HDF) format to be viewable in Heimdall. The converters in version 1.1.1 are from:
|
6
|
+
|
7
|
+
* __sonarqube_mapper__ - open-source static code analysis tool
|
8
|
+
* __fortify_mapper__ - commercial static code analysis tool
|
9
|
+
* __zap_mapper__ - OWASP ZAP - open-source dynamic code analysis tool
|
10
|
+
|
11
|
+
# Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```
|
16
|
+
gem 'heimdall_tools', :git => "https://github.com/mitre/heimdall_tools"
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
```
|
22
|
+
$ bundle
|
23
|
+
```
|
24
|
+
|
25
|
+
Clone the repo and install it yourself as:
|
26
|
+
|
27
|
+
```
|
28
|
+
$ gem install heimdall_tools
|
29
|
+
```
|
30
|
+
|
31
|
+
## Command line Usage
|
32
|
+
|
33
|
+
On the Command Line, `heimdall_tools help` will print a listing of all the command with a short description.
|
34
|
+
For detailed help on any command, run `heimdall_tools help [COMMAND]`. Help can also be called with the `-h, --help` flags after any command, like `heimdall_tools fortify_mapper -h`.
|
35
|
+
|
36
|
+
## sonarqube_mapper
|
37
|
+
|
38
|
+
sonarqube_mapper pulls SonarQube results, for the specified project, from the API and outputs in HDF format Json to be viewed on Heimdall
|
39
|
+
|
40
|
+
```
|
41
|
+
USAGE: heimdall_tools sonarqube_mapper [OPTIONS] -n <project-name> -u <api-url> -o <scan-results.json>
|
42
|
+
|
43
|
+
FLAGS:
|
44
|
+
-n --name <project-name> : name of the project in SonarQube, aka Project Key
|
45
|
+
-u --api_url <api-url> : url of the SonarQube Server API. Typically ends with /api.
|
46
|
+
-o --output <scan-results> : path to output scan-results json.
|
47
|
+
-V --verbose : verbose run [optional].
|
48
|
+
|
49
|
+
example: heimdall_tools sonarqube_mapper -n sonar_project -u http://sonar:9000/api -o scan_results.json
|
50
|
+
```
|
51
|
+
|
52
|
+
## fortify_mapper
|
53
|
+
|
54
|
+
fortify_mapper translates an Fortify results FVDL file into HDF format json to be viewable in Heimdall
|
55
|
+
|
56
|
+
```
|
57
|
+
USAGE: heimdall_tools fortify_mapper [OPTIONS] -f <fortify-fvdl> -o <scan-results.json>
|
58
|
+
|
59
|
+
FLAGS:
|
60
|
+
-f --fvdl <fortify-fvdl> : path to Fortify Scan FVDL file.
|
61
|
+
-o --output <scan-results> : path to output scan-results json.
|
62
|
+
-V --verbose : verbose run [optional].
|
63
|
+
|
64
|
+
example: heimdall_tools fortify_mapper -f audit.fvdl -o scan_results.json
|
65
|
+
```
|
66
|
+
|
67
|
+
## zap_mapper
|
68
|
+
|
69
|
+
zap_mapper translates OWASP ZAP results Json to HDF format Json be viewed on Heimdall
|
70
|
+
|
71
|
+
```
|
72
|
+
USAGE: heimdall_tools zap_mapper [OPTIONS] -j <zap-json> -n <site-name> -o <scan-results.json>
|
73
|
+
|
74
|
+
FLAGS:
|
75
|
+
-j --json <zap-json> : path to OWASP ZAP results JSON file.
|
76
|
+
-n --name <site-name> : URL of the site being evaluated.
|
77
|
+
-o --output <scan-results> : path to output scan-results json.
|
78
|
+
-V --verbose : verbose run [optional].
|
79
|
+
|
80
|
+
example: heimdall_tools zap_mapper -j zap_results.json -n site_name -o scan_results.json
|
81
|
+
```
|
82
|
+
|
83
|
+
## version
|
84
|
+
|
85
|
+
Prints out the gem version
|
86
|
+
|
87
|
+
```
|
88
|
+
USAGE: heimdall_tools version
|
89
|
+
```
|
90
|
+
|
91
|
+
# Development
|
92
|
+
|
93
|
+
This gem was developed using the [CLI Template](https://github.com/tongueroo/cli-template), a generator tool that builds a starter CLI project.
|
94
|
+
|
95
|
+
There are a set of unit tests. Run `rake test` to run the tests.
|
96
|
+
|
97
|
+
To release a new version, update the version number in `version.rb` according to the [Semantic Versioning Policy](https://semver.org/). Then, run `bundle exec rake release` which will create a git tag for the specified version, push git commits and tags, and push the `.gem` file to [github.com](https://github.com/mitre/heimdall_tools).
|
98
|
+
|
99
|
+
|
100
|
+
# License and Author
|
101
|
+
|
102
|
+
### Authors
|
103
|
+
|
104
|
+
- Author:: Rony Xavier [rx294](https://github.com/rx294)
|
105
|
+
- Author:: Dan Mirsky [mirskiy](https://github.com/mirskiy)
|
106
|
+
|
107
|
+
### NOTICE
|
108
|
+
|
109
|
+
© 2018 The MITRE Corporation.
|
110
|
+
|
111
|
+
Approved for Public Release; Distribution Unlimited. Case Number 18-3678.
|
112
|
+
|
113
|
+
### NOTICE
|
114
|
+
MITRE hereby grants express written permission to use, reproduce, distribute, modify, and otherwise leverage this software to the extent permitted by the licensed terms provided in the LICENSE.md file included with this project.
|
115
|
+
|
116
|
+
### NOTICE
|
117
|
+
|
118
|
+
This software was produced for the U. S. Government under Contract Number HHSM-500-2012-00008I, and is subject to Federal Acquisition Regulation Clause 52.227-14, Rights in Data-General.
|
119
|
+
|
120
|
+
No other use other than that granted to the U. S. Government, or to those acting on behalf of the U. S. Government under that Clause is authorized without the express written permission of The MITRE Corporation.
|
121
|
+
|
122
|
+
For further information, please contact The MITRE Corporation, Contracts Management Office, 7515 Colshire Drive, McLean, VA 22102-7539, (703) 983-6000.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/testtask"
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.libs << "lib"
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :test do
|
13
|
+
Rake::TestTask.new(:windows) do |t|
|
14
|
+
t.libs << 'test'
|
15
|
+
t.libs << "lib"
|
16
|
+
t.test_files = Dir.glob([
|
17
|
+
'test/unit/heimdall_tools/zap_mapper_test.rb',
|
18
|
+
])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :test
|
23
|
+
|
24
|
+
|
data/exe/heimdall_tools
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Trap ^C
|
4
|
+
Signal.trap('INT') {
|
5
|
+
puts "\nCtrl-C detected. Exiting..."
|
6
|
+
sleep 1
|
7
|
+
exit
|
8
|
+
}
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
11
|
+
require 'heimdall_tools'
|
12
|
+
require 'heimdall_tools/cli'
|
13
|
+
|
14
|
+
HeimdallTools::CLI.start(ARGV)
|
@@ -0,0 +1,195 @@
|
|
1
|
+
CWE-ID,CWE Name,NIST-ID,Rev,NIST Name
|
2
|
+
5, J2EE Misconfiguration: Data Transmission Without Encryption,SC-8,4,Transmission Confidentiality and Integrity
|
3
|
+
6, J2EE Misconfiguration: Insufficient Session-ID Length,SC-23,4,Session Authenticity
|
4
|
+
7, J2EE Misconfiguration: Missing Custom Error Page,SI-11,4,Error Handling
|
5
|
+
8, J2EE Misconfiguration: Entity Bean Declared Remote,AC-3,4,Access Enforcement
|
6
|
+
9, J2EE Misconfiguration: Weak Access Permissions for EJB Methods,AC-3,4,Access Enforcement
|
7
|
+
11, ASP.NET Misconfiguration: Creating Debug Binary,SI-11,4,Error Handling
|
8
|
+
14, Compiler Removal of Code to Clear Buffers,SI-16,4,Memory Protection
|
9
|
+
15, External Control of System or Configuration Setting,SI-10,4,Information Input Validation
|
10
|
+
20, Improper Input Validation,SI-10,4,Information Input Validation
|
11
|
+
22, Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'),SI-10,4,Information Input Validation
|
12
|
+
23, Relative Path Traversal,SI-10,4,Information Input Validation
|
13
|
+
36, Absolute Path Traversal,SI-10,4,Information Input Validation
|
14
|
+
73, External Control of File Name or Path,SI-10,4,Information Input Validation
|
15
|
+
77, Improper Neutralization of Special Elements used in a Command ('Command Injection'),SI-10,4,Information Input Validation
|
16
|
+
78, Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection'),SI-10,4,Information Input Validation
|
17
|
+
79, Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'),SI-10,4,Information Input Validation
|
18
|
+
89, Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'),SI-10,4,Information Input Validation
|
19
|
+
90, Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection'),SI-10,4,Information Input Validation
|
20
|
+
91, XML Injection (aka Blind XPath Injection),SI-10,4,Information Input Validation
|
21
|
+
94, Improper Control of Generation of Code ('Code Injection'),SI-10,4,Information Input Validation
|
22
|
+
95, Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection'),SI-10,4,Information Input Validation
|
23
|
+
99, Improper Control of Resource Identifiers ('Resource Injection'),SI-10,4,Information Input Validation
|
24
|
+
101, Struts Validation Problems,SI-10,4,Information Input Validation
|
25
|
+
102, Struts: Duplicate Validation Forms,SI-10,4,Information Input Validation
|
26
|
+
103, Struts: Incomplete validate() Method Definition,SI-10,4,Information Input Validation
|
27
|
+
104, Struts: Form Bean Does Not Extend Validation Class,SI-10,4,Information Input Validation
|
28
|
+
105, Struts: Form Field Without Validator,SI-10,4,Information Input Validation
|
29
|
+
106, Struts: Plug-in Framework not in Use,SI-10,4,Information Input Validation
|
30
|
+
107, Struts: Unused Validation Form,SI-10,4,Information Input Validation
|
31
|
+
108, Struts: Unvalidated Action Form,SI-10,4,Information Input Validation
|
32
|
+
109, Struts: Validator Turned Off,SI-10,4,Information Input Validation
|
33
|
+
110, Struts: Validator Without Form Field,SI-10,4,Information Input Validation
|
34
|
+
111, Direct Use of Unsafe JNI,SI-10,4,Information Input Validation
|
35
|
+
112, Missing XML Validation,SI-10,4,Information Input Validation
|
36
|
+
113, Improper Neutralization of CRLF Sequences in HTTP Headers ('HTTP Response Splitting'),SI-10,4,Information Input Validation
|
37
|
+
114, Process Control,SI-10,4,Information Input Validation
|
38
|
+
117, Improper Output Neutralization for Logs,SI-10,4,Information Input Validation
|
39
|
+
119, Improper Restriction of Operations within the Bounds of a Memory Buffer,SI-10,4,Information Input Validation
|
40
|
+
120, Buffer Copy without Checking Size of Input ('Classic Buffer Overflow'),SI-10,4,Information Input Validation
|
41
|
+
125, Out-of-bounds Read,SI-10,4,Information Input Validation
|
42
|
+
126, Buffer Over-read,SI-10,4,Information Input Validation
|
43
|
+
129, Improper Validation of Array Index,,4,
|
44
|
+
131, Incorrect Calculation of Buffer Size,SI-10,4,Information Input Validation
|
45
|
+
134, Uncontrolled Format String,SI-10,4,Information Input Validation
|
46
|
+
170, Improper Null Termination,SI-10,4,Information Input Validation
|
47
|
+
176, Improper Handling of Unicode Encoding,,4,
|
48
|
+
185, Incorrect Regular Expression,,4,
|
49
|
+
190, Integer Overflow or Wraparound,SI-10,4,Information Input Validation
|
50
|
+
195, Signed to Unsigned Conversion Error,,4,
|
51
|
+
200, Information Exposure,SC-8,4,Transmission Confidentiality and Integrity
|
52
|
+
209, Information Exposure Through an Error Message,,4,
|
53
|
+
215, Information Exposure Through Debug Information,SI-11,4,Error Handling
|
54
|
+
226, Sensitive Information Uncleared Before Release,SC-4,4,Information in Shared Resources
|
55
|
+
235, Improper Handling of Extra Parameters,SI-10,4,Information Input Validation
|
56
|
+
242, Use of Inherently Dangerous Function,,4,
|
57
|
+
243, Creation of chroot Jail Without Changing Working Directory,AC-3,4,Access Enforcement
|
58
|
+
244, Improper Cleaning of Heap Memory,SC-4,4,Information in Shared Resources
|
59
|
+
245, J2EE Bad Practices: Direct Management of Connections,,4,
|
60
|
+
246, J2EE Bad Practices: Direct Use of Sockets,,4,
|
61
|
+
248, Uncaught Exception,,4,
|
62
|
+
250, Execution with Unnecessary Privileges,AC-6,4,Least Privilege: Privilege Levels for Code Execution
|
63
|
+
251, Often Misused: String Management,,4,
|
64
|
+
252, Unchecked Return Value,,4,
|
65
|
+
256, Plaintext Storage of a Password,SC-28,4,Protection of Information at Rest
|
66
|
+
258, Empty Password in Configuration File,SC-28,4,Protection of Information at Rest
|
67
|
+
259, Use of Hard-coded Password,,4,
|
68
|
+
260, Password in Configuration File,SC-28,4,Protection of Information at Rest
|
69
|
+
261, Weak Cryptography for Passwords,SC-13,4,Cryptographic Protection
|
70
|
+
265, Privilege / Sandbox Issues,AC-6,4,Least Privilege
|
71
|
+
269, Improper Privilege Management,AC-4,4,Information Flow Enforcement
|
72
|
+
272, Least Privilege Violation,AC-6,4,Least Privilege: Privilege Levels for Code Execution -8
|
73
|
+
275, Permission Issues,AC-3,4,Access Enforcement
|
74
|
+
284, Improper Access Control,AC-3,4,Access Enforcement
|
75
|
+
285, Improper Authorization,AC-3,4,Access Enforcement
|
76
|
+
288, Authentication Bypass Using an Alternate Path or Channel,IA-8,4,Identification and Authentication (Non-Organizational Users)
|
77
|
+
297, Improper Validation of Certificate with Host Mismatch,SC-8,4,Transmission Confidentiality and Integrity
|
78
|
+
302, Authentication Bypass by Assumed-Immutable Data,SC-23,4,Session Authenticity
|
79
|
+
305, Authentication Bypass by Primary Weakness,IA-8,4,Identification and Authentication (Non-Organizational Users)
|
80
|
+
306, Missing Authentication for Critical Function,AC-3,4,Access Enforcement
|
81
|
+
307, Improper Restriction of Excessive Authentication Attempts,AC-7,4,Unsuccessful Logon Attempts
|
82
|
+
311, Missing Encryption of Sensitive Data,SC-8,4,Transmission Confidentiality and Integrity
|
83
|
+
321, Use of Hard-coded Cryptographic Key,SC-12,4,Cryptographic Key Establishment and Management
|
84
|
+
325, Missing Required Cryptographic Step,SC-13,4,Cryptographic Protection
|
85
|
+
326, Inadequate Encryption Strength,SC-12,4,Cryptographic Key Establishment and Management
|
86
|
+
327, Use of a Broken or Risky Cryptographic Algorithm,SC-13,4,Cryptographic Protection
|
87
|
+
328, Reversible One-Way Hash,SC-13,4,Cryptographic Protection
|
88
|
+
329, Not Using a Random IV with CBC Mode,SC-12,4,Cryptographic Key Establishment and Management
|
89
|
+
330, Use of Insufficiently Random Values,SC-13,4,Cryptographic Protection
|
90
|
+
331, Insufficient Entropy,SC-13,4,Cryptographic Protection
|
91
|
+
335, PRNG Seed Error,SC-13,4,Cryptographic Protection
|
92
|
+
336, Same Seed in PRNG,SC-13,4,Cryptographic Protection
|
93
|
+
338, Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG),SC-13,4,Cryptographic Protection
|
94
|
+
345, Insufficient Verification of Data Authenticity,SC-8,4,Transmission Confidentiality and Integrity
|
95
|
+
350, Reliance on Reverse DNS Resolution for a Security-Critical Function,SI-10,4,Information Input Validation
|
96
|
+
352, Cross-Site Request Forgery (CSRF),AC-3,4,Access Enforcement
|
97
|
+
358, Improperly Implemented Security Check for Standard,AC-3,4,Access Enforcement
|
98
|
+
359, Exposure of Private Information ('Privacy Violation'),SC-28,4,Protection of Information at Rest
|
99
|
+
362, Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition'),SC-4,4,Information in Shared Resources
|
100
|
+
364, Signal Handler Race Condition,,4,
|
101
|
+
369, Divide by Zero,,4,
|
102
|
+
377, Insecure Temporary File,SC-4,4,Information in Shared Resources (P1)
|
103
|
+
382, J2EE Bad Practices: Use of System.exit(),,4,
|
104
|
+
383, J2EE Bad Practices: Direct Use of Threads,,4,
|
105
|
+
384, Session Fixation,SC-23,4,Session Authenticity
|
106
|
+
388, Error Handling,SI-11,4,Error Handling
|
107
|
+
391, Unchecked Error Condition,SI-11,4,Error Handling
|
108
|
+
395, Use of NullPointerException Catch to Detect NULL Pointer Dereference,SI-11,4,Error Handling
|
109
|
+
396, Declaration of Catch for Generic Exception,SI-11,4,Error Handling
|
110
|
+
397, Declaration of Throws for Generic Exception,SI-11,4,Error Handling
|
111
|
+
398, Indicator of Poor Code Quality,,4,
|
112
|
+
400, Uncontrolled Resource Consumption ('Resource Exhaustion'),SI-10,4,Information Input Validation
|
113
|
+
401, Improper Release of Memory Before Removing Last Reference,,4,
|
114
|
+
404, Improper Resource Shutdown or Release,,4,
|
115
|
+
415, Double Free,,4,
|
116
|
+
416, Use after Free,,4,
|
117
|
+
434, Unrestricted Upload of File with Dangerous Type,AC-6,4,Least Privilege: Privilege Levels for Code Execution
|
118
|
+
457, Use of Uninitialized Variable,,4,
|
119
|
+
466, Return of Pointer Value Outside of Expected Range,,4,
|
120
|
+
470, Use of Externally-Controlled Input to Select Classes or Code ('Unsafe Reflection'),SI-10,4,Information Input Validation
|
121
|
+
471, Modification of Assumed-Immutable DATA (MAID),AC-3,4,Access Enforcement
|
122
|
+
474, Use of Function with Inconsistent Implementations,,4,
|
123
|
+
475, Undefined Behavior for Input to API,,4,
|
124
|
+
476, NULL Pointer Dereference,,4,
|
125
|
+
477, Use of Obsolete Functions,,4,
|
126
|
+
478, Missing Default Case in Switch Statement,,4,
|
127
|
+
492, Use of Inner Class Containing Sensitive Data,AC-3,4,Access Enforcement
|
128
|
+
493, Critical Public Variable Without Final Modifier,SI-11,4,Error Handling
|
129
|
+
494, Download of Code Without Integrity Check,SI-10,4,Information Input Validation
|
130
|
+
495, Private Array-Typed Field Returned From A Public Method,AC-3,4,Access Enforcement
|
131
|
+
497, Exposure of System Data to an Unauthorized Control Sphere,SI-11,4,Error Handling
|
132
|
+
501, Trust Boundary Violation,SI-10,4,Information Input Validation
|
133
|
+
521, Weak Password Requirements,IA-5,4,Authenticator Management : -1 Password-based Authentication
|
134
|
+
522, Insufficiently Protected Credentials,SC-8,4,Transmission Confidentiality and Integrity
|
135
|
+
539, Information Exposure Through Persistent Cookies,SC-23,4,Session Authenticity
|
136
|
+
546, Suspicious Comment,,4,
|
137
|
+
557, Concurrency Issues,,4,
|
138
|
+
560, Use of umask() with chmod-style Argument,,4,
|
139
|
+
561, Dead Code,,4,
|
140
|
+
562, Return of Stack Variable Address,,4,
|
141
|
+
563, Assigntment to Variable without Use,,4,
|
142
|
+
564, SQL Injection: Hibernate,SI-10,4,Information Input Validation
|
143
|
+
566, Authorization Bypass Through User-Controlled SQL Primary Key,AC-3,4,Access Enforcement
|
144
|
+
568, finalize() Method without super.finalize(),,4,
|
145
|
+
574, EJB Bad Practices: Use of Synchronization Primitives,,4,
|
146
|
+
575, EJB Bad Practices: Use of AWT Swing,,4,
|
147
|
+
576, EJB Bad Practices: Use of java I/O,,4,
|
148
|
+
577, EJB Bad Practices: Use of Sockets,,4,
|
149
|
+
578, EJB Bad Practices: Use of Class Loader,,4,
|
150
|
+
579, J2EE Bad Practices: Non-serializable Object Stored in Session,,4,
|
151
|
+
580, clone() Method Without super.clone(),,4,
|
152
|
+
581, Object Model Violation: Just One of Equals and Hashcode Defined,,4,
|
153
|
+
582, Array Declared Public,AC-3,4,Access Enforcement
|
154
|
+
583, finalize() Method Declared Public,AC-3,4,Access Enforcement
|
155
|
+
584, Return Inside Finally Block,SI-11,4,Error Handling
|
156
|
+
586, Explicit Call to Finalize(),,4,
|
157
|
+
590, Free of Memory not on the Heap,,4,
|
158
|
+
591, Sensitive Data Storage in Improperly Locked Memory,SC-4,4,Information in Shared Resources
|
159
|
+
601, URL Redirection to Untrusted Site ('Open Redirect'),SI-10,4,Information Input Validation
|
160
|
+
607, Public Static Final Field References Mutable Object,,4,
|
161
|
+
609, Double-Checked Locking,,4,
|
162
|
+
611, Improper Restriction of XML External Entity Reference ('XXE'),,4,
|
163
|
+
613, Insufficient Session Expiration,AC-12,4,Session Termination
|
164
|
+
614, Sensitive Cookie in HTTPS Session Without 'Secure' Attribute,SC-8,4,Transmission Confidentiality and Integrity
|
165
|
+
615, Information Exposure Through Comments,AC-3,4,Access Enforcement : -5 Security-Relevant Information
|
166
|
+
639, Authorization Bypass Through User-Controlled Key,AC-3,4,Access Enforcement
|
167
|
+
642, External Control of Critical State Data,,4,
|
168
|
+
643, Improper Neutralization of Data within XPath Expressions ('XPath Injection'),SI-10,4,Information Input Validation
|
169
|
+
651, Information Exposure Through WSDL File,,4,
|
170
|
+
652, Improper Neutralization of Data within XQuery Expressions ('XQuery Injection'),SI-10,4,Information Input Validation
|
171
|
+
662, Improper Synchonization,,4,
|
172
|
+
667, Improper Locking,,4,
|
173
|
+
676, Use of Potentially Dangerous Function,,4,
|
174
|
+
690,: Unchecked Return Value to NULL Pointer Dereference,,4,
|
175
|
+
691, Insufficient Control Flow Management,SI-11,4,Error Handling
|
176
|
+
694, Use of Multiple Resources with Duplicate Identifier,,4,
|
177
|
+
732, Incorrect Permission Assignment for Critical Resource,AC-3,4,Access Enforcement
|
178
|
+
733, Compiler Optimization Removal or Modification of Security-critical Code,,4,
|
179
|
+
759, Use of a One-Way Hash without a Salt,SC-13,4,Cryptographic Protection
|
180
|
+
760, Use of a One-Way Hash with a Predictable Salt,SC-13,4,Cryptographic Protection
|
181
|
+
776, Improper Restriction of Recursive Entity References in DTDs ('XML Entity Expansion'),,4,
|
182
|
+
780, Use of RSA Algorithm without OAEP,SC-13,4,Cryptographic Protection
|
183
|
+
785, Use of Path Manipulation Function without Maximum-sized Buffer,SI-10,4,Information Input Validation
|
184
|
+
787, Out-of-bounds Write,SI-10,4,Information Input Validation
|
185
|
+
798, Use of Hard-coded Credentials,,4,
|
186
|
+
805, Buffer Access with Incorrect Length Value,SI-10,4,Information Input Validation
|
187
|
+
807, Reliance on Untrusted Inputs in a Security Decision,SC-23,4,Session Authenticity
|
188
|
+
820, Missing Synchronization,,4,
|
189
|
+
821, Incorrect Synchronization,,4,
|
190
|
+
829, Inclusion of Functionality from Untrusted Control Sphere,,4,
|
191
|
+
862, Missing Authorization,AC-3,4,Access Enforcement
|
192
|
+
863, Incorrect Authorization,AC-3,4,Access Enforcement
|
193
|
+
915, Improperly Controlled Modification of Dynamically-Determined Object Attributes,SI-10,4,Information Input Validation
|
194
|
+
916, Use of Password Hash With Insufficient Computational Effort,SC-13,4,Cryptographic Protection
|
195
|
+
918, Server-Side Request Forgery (SSRF),SI-10,4,Information Input Validation
|
data/lib/data/gitkeep
ADDED
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
OWASP-ID,OWASP Name,NIST-ID,Rev,NIST Name
|
2
|
+
A1,Injection,SI-10,4,Information Input Validation
|
3
|
+
A2,Broken Authentication,SC-23,4,Session Authenticity
|
4
|
+
A3,Sensitive Data Exposure,SI-11,4,Error Handling
|
5
|
+
A4,XML External Entities (XXE),SI-10,4,Information Input Validation
|
6
|
+
A5,Broken Access Control,AC-3,4,Access Enforcement
|
7
|
+
A6,Security Misconfiguration,CM-6,4,Configuration Settings
|
8
|
+
A7,Cross-Site Scripting (XSS),SI-10,4,Information Input Validation
|
9
|
+
A8,Insecure Deserialization,SC-23,4,Session Authenticity
|
10
|
+
A9,Using Components with Known Vulnerabilities,SI-2,4,Flaw Remediation
|
11
|
+
A10,Insufficient Logging&Monitoring,AU-12,4,Audit Generation
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# require_relative '../utilities/' Place any utility code in utilities folder and require here
|
2
|
+
|
3
|
+
module HeimdallTools
|
4
|
+
class CLI < Command
|
5
|
+
desc 'fortify_mapper', 'fortify_mapper translates Fortify fvdl files to HDF format Json be viewed on Heimdall'
|
6
|
+
long_desc Help.text(:fortify_mapper)
|
7
|
+
option :fvdl, required: true, aliases: '-f'
|
8
|
+
option :output, required: true, aliases: '-o'
|
9
|
+
option :verbose, type: :boolean, aliases: '-V'
|
10
|
+
def fortify_mapper
|
11
|
+
hdf = HeimdallTools::FortifyMapper.new(File.read(options[:fvdl])).to_hdf
|
12
|
+
File.write(options[:output], hdf)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'zap_mapper', 'zap_mapper translates OWASP ZAP results Json to HDF format Json be viewed on Heimdall'
|
16
|
+
long_desc Help.text(:fortify_mapper)
|
17
|
+
option :json, required: true, aliases: '-j'
|
18
|
+
option :name, required: true, aliases: '-n'
|
19
|
+
option :output, required: true, aliases: '-o'
|
20
|
+
option :verbose, type: :boolean, aliases: '-V'
|
21
|
+
def zap_mapper
|
22
|
+
hdf = HeimdallTools::ZapMapper.new(File.read(options[:json]), options[:name]).to_hdf
|
23
|
+
File.write(options[:output], hdf)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'sonarqube_mapper', 'sonarqube_mapper pulls SonarQube results, for the specified project name, from the API and outputs in HDF format Json to be viewed on Heimdall'
|
27
|
+
long_desc Help.text(:sonarqube_mapper)
|
28
|
+
option :name, required: true, aliases: '-n'
|
29
|
+
option :api_url, required: true, aliases: '-u'
|
30
|
+
option :output, required: true, aliases: '-o'
|
31
|
+
option :verbose, type: :boolean, aliases: '-V'
|
32
|
+
def sonarqube_mapper
|
33
|
+
hdf = HeimdallTools::SonarQubeMapper.new(options[:name], options[:api_url]).to_hdf
|
34
|
+
File.write(options[:output], hdf)
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'version', 'prints version'
|
38
|
+
def version
|
39
|
+
puts VERSION
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
# Override thor's long_desc identation behavior
|
4
|
+
# https://github.com/erikhuda/thor/issues/398
|
5
|
+
|
6
|
+
# rubocop:disable Naming/UncommunicativeMethodParamName
|
7
|
+
|
8
|
+
class Thor
|
9
|
+
module Shell
|
10
|
+
class Basic
|
11
|
+
def print_wrapped(message, _options = {})
|
12
|
+
message = "\n#{message}" unless message[0] == "\n"
|
13
|
+
stdout.puts message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module HeimdallTools
|
20
|
+
class Command < Thor
|
21
|
+
class << self
|
22
|
+
def dispatch(m, args, options, config)
|
23
|
+
# Allow calling for help via:
|
24
|
+
# heimdall_tools command help
|
25
|
+
# heimdall_tools command -h
|
26
|
+
# heimdall_tools command --help
|
27
|
+
# heimdall_tools command -D
|
28
|
+
#
|
29
|
+
# as well thor's normal way:
|
30
|
+
#
|
31
|
+
# heimdall_tools help command
|
32
|
+
help_flags = Thor::HELP_MAPPINGS + ['help']
|
33
|
+
if args.length > 1 && !(args & help_flags).empty?
|
34
|
+
args -= help_flags
|
35
|
+
args.insert(-2, 'help')
|
36
|
+
end
|
37
|
+
|
38
|
+
# heimdall_tools version
|
39
|
+
# heimdall_tools --version
|
40
|
+
# heimdall_tools -v
|
41
|
+
version_flags = ['--version', '-v']
|
42
|
+
if args.length == 1 && !(args & version_flags).empty?
|
43
|
+
args = ['version']
|
44
|
+
end
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'nori'
|
4
|
+
|
5
|
+
NIST_REFERENCE_NAME = 'Standards Mapping - NIST Special Publication 800-53 Revision 4'.freeze
|
6
|
+
|
7
|
+
module HeimdallTools
|
8
|
+
class FortifyMapper
|
9
|
+
def initialize(fvdl, verbose = false)
|
10
|
+
@fvdl = fvdl
|
11
|
+
@verbose = verbose
|
12
|
+
|
13
|
+
begin
|
14
|
+
data = Nori.new(empty_tag_value: true).parse(fvdl)
|
15
|
+
@timestamp = data['FVDL']['CreatedTS']
|
16
|
+
@vulns = data['FVDL']['Vulnerabilities']['Vulnerability']
|
17
|
+
@snippets = data['FVDL']['Snippets']['Snippet']
|
18
|
+
@rules = data['FVDL']['Description']
|
19
|
+
rescue StandardError => e
|
20
|
+
raise "Invalid Fortify FVDL file provided Exception: #{e}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_entry(entry)
|
25
|
+
snippetid = entry['Node']['SourceLocation']['@snippet']
|
26
|
+
finding = {}
|
27
|
+
finding['status'] = 'failed'
|
28
|
+
finding['code_desc'] = snippet(snippetid)
|
29
|
+
finding
|
30
|
+
end
|
31
|
+
|
32
|
+
def primaries(classid)
|
33
|
+
matched_vulns = @vulns.select { |x| x['ClassInfo']['ClassID'].eql?(classid) }
|
34
|
+
findings = []
|
35
|
+
matched_vulns.each do |vuln|
|
36
|
+
traces = vuln['AnalysisInfo']['Unified']['Trace']
|
37
|
+
traces = [traces] unless traces.is_a?(Array)
|
38
|
+
traces.each do |trace|
|
39
|
+
entries = trace['Primary']['Entry']
|
40
|
+
entries = [entries] unless entries.is_a?(Array)
|
41
|
+
entries = entries.reject { |x| x['Node'].nil? }
|
42
|
+
entries.each do |entry|
|
43
|
+
findings << process_entry(entry)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
findings.uniq
|
48
|
+
end
|
49
|
+
|
50
|
+
def snippet(snippetid)
|
51
|
+
snippet = @snippets.select { |x| x['@id'].eql?(snippetid) }.first
|
52
|
+
"\nPath: #{snippet['File']}\n" \
|
53
|
+
"StartLine: #{snippet['StartLine']}, " \
|
54
|
+
"EndLine: #{snippet['EndLine']}\n" \
|
55
|
+
"Code:\n#{snippet['Text'].strip}" \
|
56
|
+
end
|
57
|
+
|
58
|
+
def nist_tag(rule)
|
59
|
+
references = rule['References']['Reference']
|
60
|
+
references = [references] unless references.is_a?(Array)
|
61
|
+
tag = references.detect { |x| x['Author'].eql?(NIST_REFERENCE_NAME) }
|
62
|
+
tag.nil? ? 'unmapped' : tag['Title'].match(/[a-zA-Z][a-zA-Z]-\d{1,2}/)
|
63
|
+
end
|
64
|
+
|
65
|
+
def impact(classid)
|
66
|
+
vuln = @vulns.detect { |x| x['ClassInfo']['ClassID'].eql?(classid) }
|
67
|
+
vuln['ClassInfo']['DefaultSeverity'].to_f / 5
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_hdf
|
71
|
+
inpsec_json = {}
|
72
|
+
|
73
|
+
inpsec_json['name'] = 'Fortify Static Analyzer Scan'
|
74
|
+
inpsec_json['version'] = [@timestamp['@date'], @timestamp['@time']].join(' ')
|
75
|
+
inpsec_json['controls'] = []
|
76
|
+
|
77
|
+
@rules.each do |rule|
|
78
|
+
@item = {}
|
79
|
+
@item['id'] = rule['@classID']
|
80
|
+
@item['desc'] = rule['Explanation']
|
81
|
+
@item['title'] = rule['Abstract']
|
82
|
+
@item['impact'] = impact(rule['@classID'])
|
83
|
+
@item['code'] = ''
|
84
|
+
@item['results'] = []
|
85
|
+
@item['results'] = primaries(@item['id'])
|
86
|
+
@item['tags'] = {}
|
87
|
+
@item['tags']['nist'] = [nist_tag(rule).to_s, 'Rev_4']
|
88
|
+
inpsec_json['controls'] << @item
|
89
|
+
end
|
90
|
+
inpsec_json.to_json
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
MAPPING_FILES = {
|
6
|
+
cwe: './lib/data/cwe-nist-mapping.csv'.freeze,
|
7
|
+
owasp: './lib/data/owasp-nist-mapping.csv'.freeze
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
IMPACT_MAPPING = {
|
11
|
+
BLOCKER: 1.0,
|
12
|
+
CRITICAL: 0.7,
|
13
|
+
MAJOR: 0.5,
|
14
|
+
MINOR: 0.3,
|
15
|
+
INFO: 0.0
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def check_response(response)
|
19
|
+
raise "API Error: #{response.status}\n#{response.body}" unless response.ok?
|
20
|
+
end
|
21
|
+
|
22
|
+
class SonarQubeApi
|
23
|
+
ISSUES_ENDPOINT = '/issues/search'.freeze
|
24
|
+
RULES_ENDPOINT = '/rules/search'.freeze
|
25
|
+
RULE_ENDPOINT = '/rules/show'.freeze
|
26
|
+
SOURCE_ENDPOINT = '/sources/raw'.freeze
|
27
|
+
VERSION_ENDPOINT = '/server/version'.freeze
|
28
|
+
|
29
|
+
PAGE_SIZE = 100
|
30
|
+
|
31
|
+
def initialize(api_url)
|
32
|
+
@api_url = api_url
|
33
|
+
end
|
34
|
+
|
35
|
+
# Query issues endpoint, get all vulnerabilities
|
36
|
+
# This query is based on the url params used by the web project issue view
|
37
|
+
def query_issues(project_name)
|
38
|
+
issues = []
|
39
|
+
params = {
|
40
|
+
componentKeys: project_name,
|
41
|
+
resolved: 'false',
|
42
|
+
types: 'VULNERABILITY',
|
43
|
+
ps: PAGE_SIZE,
|
44
|
+
p: 1
|
45
|
+
}
|
46
|
+
|
47
|
+
loop do # Get all pages
|
48
|
+
response = HTTParty.get(@api_url + ISSUES_ENDPOINT, { query: params })
|
49
|
+
check_response response
|
50
|
+
issues += response['issues']
|
51
|
+
|
52
|
+
if params[:p] * PAGE_SIZE >= response['paging']['total']
|
53
|
+
break
|
54
|
+
end
|
55
|
+
|
56
|
+
params[:p] += 1
|
57
|
+
end
|
58
|
+
|
59
|
+
issues
|
60
|
+
end
|
61
|
+
|
62
|
+
# Query rules endpoint to get additional info for 800-53 mapping
|
63
|
+
def query_rule(rule)
|
64
|
+
params = {
|
65
|
+
key: rule
|
66
|
+
}
|
67
|
+
response = HTTParty.get(@api_url + RULE_ENDPOINT, { query: params })
|
68
|
+
check_response response
|
69
|
+
response['rule']
|
70
|
+
end
|
71
|
+
|
72
|
+
# Query the source endpoint for a code snippet showing a vulnerability
|
73
|
+
# SonarQube has 3 relevant source endpoints.
|
74
|
+
# The web gui uses sources/list (not in webservices), returns each line w/ html formatting and scm
|
75
|
+
# sources/show returns just the source lines, but still w/ html formatting
|
76
|
+
# Both of the above allow filtering by line, whereas raw does not.
|
77
|
+
# sources/raw returns the entire file
|
78
|
+
# We are going to use sources/raw for now so we don't have to deal with the html
|
79
|
+
def query_code_snippet(component, start_line, end_line)
|
80
|
+
params = {
|
81
|
+
key: component
|
82
|
+
}
|
83
|
+
response = HTTParty.get(@api_url + SOURCE_ENDPOINT, { query: params })
|
84
|
+
check_response response
|
85
|
+
response.body.split("\n")[start_line..end_line].join("\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
# Query the version of the SonarQube server
|
89
|
+
def query_version
|
90
|
+
response = HTTParty.get(@api_url + VERSION_ENDPOINT)
|
91
|
+
check_response response
|
92
|
+
response.body
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
module HeimdallTools
|
97
|
+
class SonarQubeMapper
|
98
|
+
# Fetches the necessary data from the API and builds report
|
99
|
+
def initialize(project_name, sonarqube_url)
|
100
|
+
@project_name = project_name
|
101
|
+
@api = SonarQubeApi.new(sonarqube_url)
|
102
|
+
|
103
|
+
@mappings = load_nist_mappings
|
104
|
+
@findings = @api.query_issues(@project_name).map { |x| Finding.new(x, @api) }
|
105
|
+
@controls = _get_controls
|
106
|
+
end
|
107
|
+
|
108
|
+
# Build an array of Controls based on the SonarQube findings
|
109
|
+
def _get_controls
|
110
|
+
control_key_to_findings_map = Hash.new { |h, k| h[k] = [] }
|
111
|
+
@findings.each { |f| control_key_to_findings_map[f.control_key] << f }
|
112
|
+
control_key_to_findings_map.map { |control_key, findings| Control.new(control_key, findings, @api, @mappings) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_nist_mappings
|
116
|
+
mappings = {}
|
117
|
+
MAPPING_FILES.each do |mapping_type, path|
|
118
|
+
csv_data = CSV.read(path, { encoding: 'UTF-8',
|
119
|
+
headers: true,
|
120
|
+
header_converters: :symbol,
|
121
|
+
converters: :all })
|
122
|
+
mappings[mapping_type] = Hash[csv_data.map { |row|
|
123
|
+
[row[(mapping_type.to_s.downcase + 'id').to_sym].to_s, [row[:nistid], "Rev_#{row[:rev]}"]]
|
124
|
+
}]
|
125
|
+
end
|
126
|
+
mappings
|
127
|
+
end
|
128
|
+
|
129
|
+
# Returns a report in HDF format
|
130
|
+
def to_hdf
|
131
|
+
{
|
132
|
+
controls: @controls.map(&:hdf),
|
133
|
+
# currently on heimdall version tag is displayed as time on profile view
|
134
|
+
# this wil be updated after heimdal update to fix this
|
135
|
+
version: Time.now.strftime("%a,%d %b %Y %X"),
|
136
|
+
name: "#{@project_name} SonarQube Scan"
|
137
|
+
}.to_json
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class Control
|
143
|
+
# CWE and CERT will be stated generically in tags (ie. it just says cwe or cert, not which number)
|
144
|
+
# OWASP is stated specifically, ex owasp-a1
|
145
|
+
#
|
146
|
+
# SonarQube is inconsistent with tags (ex some cwe rules don't have cwe number in desc,) as noted below
|
147
|
+
TAG_DATA = {} # NOTE: We count on Ruby to preserve order for TAG_DATA
|
148
|
+
TAG_DATA[:cwe] = {
|
149
|
+
# Some rules with cwe tag don't have cwe number in description!
|
150
|
+
# Currently only squid:S2658, but it has OWASP tag so we can use that.
|
151
|
+
regex: 'cwe.mitre.org/data/definitions/([^\.]*)' # Sometimes the "http://" is not part of the url
|
152
|
+
}
|
153
|
+
TAG_DATA[:owasp] = {
|
154
|
+
# Many (19 currently) owasp have don't cwe (ex. squid:S3355)
|
155
|
+
}
|
156
|
+
TAG_DATA[:cert] = {
|
157
|
+
# Some rules only have cert tag (ex. kotlin:S1313)
|
158
|
+
# Some rules with cert tag don't actually have cert in description!
|
159
|
+
# Currently only squid:S4434, but it has OWASP tag so we can use that.
|
160
|
+
regex: 'CERT,?\n? ([^<]*)\.?<'
|
161
|
+
}
|
162
|
+
# All sans-tagged rules have CWE number, so no need to map SANS
|
163
|
+
# There some tags which we can map directly (ex. denial-of-service)
|
164
|
+
# But there are currently no rules with such a tag that don't have a better tag (ex. cwe)
|
165
|
+
# So we will be leaving this functionality out until necessary
|
166
|
+
|
167
|
+
# These rules don't have the cert/cwe number in description or have other problems
|
168
|
+
# If there is an error with them, ignore it since we know they have problems.
|
169
|
+
KNOWN_BAD_RULES = %w{squid:S4434 squid:S2658}.to_set
|
170
|
+
|
171
|
+
# @param [SonarQubeApi] sonar_api
|
172
|
+
def initialize(control_key, findings, sonar_api, mappings)
|
173
|
+
@key = control_key
|
174
|
+
@findings = findings
|
175
|
+
@api = sonar_api
|
176
|
+
@mappings = mappings
|
177
|
+
|
178
|
+
@data = @api.query_rule(@key)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Get specific tags for a given type.
|
182
|
+
# ex. for cwe, get the CWE numbers
|
183
|
+
# Output: [] # ["cwe-295", ...]
|
184
|
+
def _get_parsed_tags(tag_type)
|
185
|
+
tag_data = TAG_DATA[tag_type]
|
186
|
+
parsed_tags = []
|
187
|
+
|
188
|
+
if tag_data.key? :regex
|
189
|
+
# If the tag type has a regex, try to find the specified tag in the description
|
190
|
+
# NOTE: Some tag types can have multiple matches, such as cwe
|
191
|
+
reg = Regexp.new(tag_data[:regex], Regexp::IGNORECASE)
|
192
|
+
parsed_tags += @data['htmlDesc'].scan(reg).map(&:first)
|
193
|
+
|
194
|
+
if parsed_tags.empty? and not KNOWN_BAD_RULES.include? @key
|
195
|
+
puts "Error: Rule #{@key}: No regex matches for #{tag_type} tag." if parsed_tags.empty?
|
196
|
+
end
|
197
|
+
else
|
198
|
+
# If the tag type doesn't have a regex, it is specific enough to be mapped directly
|
199
|
+
# Ex. Rule with tag owasp-a1 can be mapped directly.
|
200
|
+
parsed_tags = @data['sysTags'] & @mappings[tag_type].keys
|
201
|
+
|
202
|
+
if parsed_tags.empty? and not KNOWN_BAD_RULES.include? @key
|
203
|
+
puts "Warning: Rule #{@key}: Has #{tag_type} tag but no usable mapping found."
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
parsed_tags
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns the a list of the NIST 800-53 control based on the tags
|
211
|
+
def get_nist_tags
|
212
|
+
# Since we only care about the most important 800-53 control,
|
213
|
+
# we check for tags in order of importance/specificity (cwe's, then owasp, etc. Same as order of tag_data)
|
214
|
+
# and return a 800-53 control for the first tag we can map
|
215
|
+
TAG_DATA.each do |tag_type, _|
|
216
|
+
next unless @data['sysTags'].any? { |tag| tag.start_with? tag_type.to_s }
|
217
|
+
|
218
|
+
parsed_tags = _get_parsed_tags tag_type
|
219
|
+
next if parsed_tags.empty?
|
220
|
+
|
221
|
+
parsed_tag = parsed_tags.find { |tag| @mappings[tag_type].key? tag }
|
222
|
+
next if parsed_tag.nil?
|
223
|
+
|
224
|
+
return [@mappings[tag_type][parsed_tag]].flatten.uniq
|
225
|
+
end
|
226
|
+
|
227
|
+
['unmapped'] # HDF expects this to be a list, but not an empty list even if there aren't results
|
228
|
+
end
|
229
|
+
|
230
|
+
def hdf
|
231
|
+
# Note: Structure is based on fortify -> HDF converter output
|
232
|
+
{
|
233
|
+
title: @data['name'],
|
234
|
+
desc: @data['htmlDesc'],
|
235
|
+
impact: IMPACT_MAPPING[@data['severity'].to_sym],
|
236
|
+
tags: {
|
237
|
+
nist: get_nist_tags
|
238
|
+
},
|
239
|
+
results: @findings.map(&:get_result),
|
240
|
+
code: '', # This should be the inspec code for the control, which we don't have
|
241
|
+
id: @key
|
242
|
+
}
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
class Finding
|
247
|
+
attr_reader :control_key
|
248
|
+
|
249
|
+
# @param [SonarQubeApi] sonar_api
|
250
|
+
def initialize(vuln_data, sonar_api)
|
251
|
+
@data = vuln_data
|
252
|
+
@api = sonar_api
|
253
|
+
|
254
|
+
@key = @data['key']
|
255
|
+
@control_key = @data['rule']
|
256
|
+
@project = @data['project']
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_result
|
260
|
+
vuln_start = @data['textRange']['startLine']
|
261
|
+
vuln_end = @data['textRange']['endLine']
|
262
|
+
component = @data['component']
|
263
|
+
snip_start = [1, vuln_start - 3].max
|
264
|
+
snip_end = vuln_end + 3 # api doesn't care if we request lines past end of file
|
265
|
+
snip = @api.query_code_snippet(component, snip_start, snip_end)
|
266
|
+
|
267
|
+
snip_html = "StartLine: #{snip_start}, EndLine: #{snip_end}<br>Code:<pre>#{snip}</pre>"
|
268
|
+
{
|
269
|
+
status: 'failed',
|
270
|
+
code_desc: "Path:#{component}:#{vuln_start}:#{vuln_end} #{snip_html}"
|
271
|
+
}
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
if $PROGRAM_NAME == __FILE__
|
276
|
+
puts 'Getting data from SonarQube API'
|
277
|
+
|
278
|
+
url = 'http://sonar:9000/api'
|
279
|
+
project_name = 'ansible-test'
|
280
|
+
|
281
|
+
MAPPING_FILES = {
|
282
|
+
cwe: '../data/cwe-nist-mapping.csv'.freeze,
|
283
|
+
owasp: '../data/owasp-nist-mapping.csv'.freeze
|
284
|
+
}.freeze
|
285
|
+
|
286
|
+
sonar_mapper = HeimdallTools::SonarQubeMapper.new(project_name, url)
|
287
|
+
File.open('sonarqube_hdf_output.json', 'w') do |f|
|
288
|
+
f.write(sonar_mapper.to_hdf)
|
289
|
+
end
|
290
|
+
|
291
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
CWE_NIST_MAPPING_FILE = './lib/data/cwe-nist-mapping.csv'.freeze
|
6
|
+
|
7
|
+
# rubocop:disable Metrics/AbcSize
|
8
|
+
|
9
|
+
module HeimdallTools
|
10
|
+
class ZapMapper
|
11
|
+
def initialize(zap_json, name, verbose = false)
|
12
|
+
@zap_json = zap_json
|
13
|
+
@verbose = verbose
|
14
|
+
|
15
|
+
begin
|
16
|
+
data = JSON.parse(zap_json, symbolize_names: true)
|
17
|
+
|
18
|
+
unless data[:site].map { |x| x[:@name] }.include?(name)
|
19
|
+
abort("Specified site name: #{name} is not defined in the JSON provided.")
|
20
|
+
end
|
21
|
+
|
22
|
+
site = data[:site].select { |x| x[:@name].eql?(name) }.first
|
23
|
+
|
24
|
+
@cwe_nist_mapping = parse_mapper
|
25
|
+
@zap_verison = data[:@version]
|
26
|
+
@timestamp = data[:@generated]
|
27
|
+
@name = site[:@name]
|
28
|
+
@host = site[:@host]
|
29
|
+
@port = site[:@port]
|
30
|
+
@ssl = site[:@ssl]
|
31
|
+
@alerts = site[:alerts]
|
32
|
+
rescue StandardError => e
|
33
|
+
raise "Invalid ZAP results JSON file provided Exception: #{e}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_instances(instances)
|
38
|
+
findings = []
|
39
|
+
instances.each do |instance|
|
40
|
+
findings << finding(instance)
|
41
|
+
end
|
42
|
+
findings.uniq
|
43
|
+
end
|
44
|
+
|
45
|
+
def finding(instance)
|
46
|
+
finding = {}
|
47
|
+
finding['status'] = 'failed'
|
48
|
+
finding['code_desc'] = format_code_desc(instance)
|
49
|
+
finding
|
50
|
+
end
|
51
|
+
|
52
|
+
def format_code_desc(code_desc)
|
53
|
+
desc = ''
|
54
|
+
code_desc.keys.each do |key|
|
55
|
+
desc += "#{key.capitalize}: #{code_desc[key]}\n"
|
56
|
+
end
|
57
|
+
desc
|
58
|
+
end
|
59
|
+
|
60
|
+
def nist_tag(cweid)
|
61
|
+
entries = @cwe_nist_mapping.select { |x| x[:cweid].to_s.eql?(cweid.to_s) }
|
62
|
+
tags = entries.map { |x| [x[:nistid], "Rev_#{x[:rev]}"] }
|
63
|
+
tags.empty? ? ['unmapped'] : tags.flatten.uniq
|
64
|
+
end
|
65
|
+
|
66
|
+
def impact(riskcode)
|
67
|
+
if riskcode.to_i.between?(0, 1)
|
68
|
+
0.3
|
69
|
+
elsif riskcode.to_i == 2
|
70
|
+
0.5
|
71
|
+
elsif riskcode.to_i >= 3
|
72
|
+
0.7
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def checktext(alert)
|
77
|
+
[alert[:solution], alert[:otherinfo], alert[:otherinfo]].join("\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
def parse_mapper
|
81
|
+
csv_data = CSV.read(CWE_NIST_MAPPING_FILE, { encoding: 'UTF-8',
|
82
|
+
headers: true,
|
83
|
+
header_converters: :symbol,
|
84
|
+
converters: :all })
|
85
|
+
csv_data.map(&:to_hash)
|
86
|
+
end
|
87
|
+
|
88
|
+
def fix_duplicates(controls)
|
89
|
+
control_ids = controls.map { |x| x['id'] }
|
90
|
+
dup_ids = control_ids.select { |x| control_ids.count(x) > 1 }.uniq
|
91
|
+
dup_ids.each do |dup_id|
|
92
|
+
index = 1
|
93
|
+
controls.select { |x| x['id'].eql?(dup_id) }.each do |control|
|
94
|
+
control['id'] = control['id'] + '.' + index.to_s
|
95
|
+
index += 1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_hdf
|
101
|
+
inpsec_profile = {}
|
102
|
+
|
103
|
+
inpsec_profile['name'] = "#{@host} OWASP ZAP Scan"
|
104
|
+
inpsec_profile['version'] = @timestamp
|
105
|
+
|
106
|
+
inpsec_profile['controls'] = []
|
107
|
+
|
108
|
+
@alerts.each do |alert|
|
109
|
+
@item = {}
|
110
|
+
@item['id'] = alert[:pluginid].to_s
|
111
|
+
@item['title'] = alert[:name].to_s
|
112
|
+
@item['desc'] = Nokogiri::HTML(alert[:desc]).text
|
113
|
+
@item['impact'] = impact(alert[:riskcode]).to_s
|
114
|
+
@item['tags'] = {}
|
115
|
+
@item['tags']['nist'] = nist_tag(alert[:cweid])
|
116
|
+
@item['tags']['cweid'] = alert[:cweid].to_s
|
117
|
+
@item['tags']['wascid'] = alert[:wascid].to_s
|
118
|
+
@item['tags']['sourceid'] = alert[:sourceid].to_s
|
119
|
+
@item['tags']['confidence'] = alert[:confidence].to_s
|
120
|
+
@item['tags']['riskdesc'] = alert[:riskdesc].to_s
|
121
|
+
@item['tags']['check'] = checktext(alert)
|
122
|
+
@item['code'] = ''
|
123
|
+
@item['results'] = process_instances(alert[:instances])
|
124
|
+
|
125
|
+
inpsec_profile['controls'] << @item
|
126
|
+
end
|
127
|
+
fix_duplicates(inpsec_profile['controls'])
|
128
|
+
inpsec_profile.to_json
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(__dir__))
|
2
|
+
require 'heimdall_tools/version'
|
3
|
+
|
4
|
+
module HeimdallTools
|
5
|
+
autoload :Help, 'heimdall_tools/help'
|
6
|
+
autoload :Command, 'heimdall_tools/command'
|
7
|
+
autoload :CLI, 'heimdall_tools/cli'
|
8
|
+
autoload :FortifyMapper, 'heimdall_tools/fortify_mapper'
|
9
|
+
autoload :ZapMapper, 'heimdall_tools/zap_mapper'
|
10
|
+
autoload :SonarQubeMapper, 'heimdall_tools/sonarqube_mapper'
|
11
|
+
end
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heimdall_tools
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Thew
|
8
|
+
- Rony Xavier
|
9
|
+
- Aaron Lippold
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2019-02-04 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.2.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 4.2.3
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: colorize
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: nokogiri
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.8'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1.8'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: nori
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: OptionParser
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: thor
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0.19'
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0.19'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: bundler
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: minitest
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '5.0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '5.0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: pry
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - "~>"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - "~>"
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: rake
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - "~>"
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '10.0'
|
148
|
+
type: :runtime
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - "~>"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '10.0'
|
155
|
+
description: Converter utils that can be included as a gem or used from the command
|
156
|
+
line
|
157
|
+
email:
|
158
|
+
- rxavier@mitre.org
|
159
|
+
executables:
|
160
|
+
- heimdall_tools
|
161
|
+
extensions: []
|
162
|
+
extra_rdoc_files: []
|
163
|
+
files:
|
164
|
+
- CHANGELOG.md
|
165
|
+
- Guardfile
|
166
|
+
- LICENSE.md
|
167
|
+
- README.md
|
168
|
+
- Rakefile
|
169
|
+
- exe/heimdall_tools
|
170
|
+
- lib/data/cwe-nist-mapping.csv
|
171
|
+
- lib/data/gitkeep
|
172
|
+
- lib/data/owasp-nist-mapping.csv
|
173
|
+
- lib/heimdall_tools.rb
|
174
|
+
- lib/heimdall_tools/cli.rb
|
175
|
+
- lib/heimdall_tools/command.rb
|
176
|
+
- lib/heimdall_tools/fortify_mapper.rb
|
177
|
+
- lib/heimdall_tools/help.rb
|
178
|
+
- lib/heimdall_tools/help/fortify_mapper.md
|
179
|
+
- lib/heimdall_tools/help/sonarqube_mapper.md
|
180
|
+
- lib/heimdall_tools/help/zap_mapper.md
|
181
|
+
- lib/heimdall_tools/sonarqube_mapper.rb
|
182
|
+
- lib/heimdall_tools/version.rb
|
183
|
+
- lib/heimdall_tools/zap_mapper.rb
|
184
|
+
- lib/utilities/gitkeep
|
185
|
+
homepage: https://github.com/mitre/heimdall_tools
|
186
|
+
licenses:
|
187
|
+
- Apache-2.0
|
188
|
+
metadata:
|
189
|
+
allowed_push_host: https://rubygems.org
|
190
|
+
post_install_message:
|
191
|
+
rdoc_options: []
|
192
|
+
require_paths:
|
193
|
+
- lib
|
194
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
requirements: []
|
205
|
+
rubyforge_project:
|
206
|
+
rubygems_version: 2.6.14
|
207
|
+
signing_key:
|
208
|
+
specification_version: 4
|
209
|
+
summary: Convert Forify, Openzap and Sonarqube results to HDF
|
210
|
+
test_files: []
|