sastbox_sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,238 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../../lib/sastbox-sdk'
3
+
4
+ RSpec.describe 'Scanner' do
5
+ let(:scanner) do
6
+ SastBox::Scanner.new(
7
+ name: 'test_name',
8
+ name_alias: 'test_alias',
9
+ description: 'test_desc',
10
+ support: ['test_support'],
11
+ version: '0.1',
12
+ tool: 'test_tool'
13
+ )
14
+ end
15
+
16
+ describe 'start_scan' do
17
+ context 'should raise name error for run method when correct options are provided' do
18
+ before do
19
+ scanner.parse_opts(['-o', 'xxx', '-c', 'aaa'])
20
+ end
21
+
22
+ it "should raise name error for run method when correct options are provided" do
23
+ expect { scanner.start_scan }.to raise_error(NameError) do |error| # #<NameError: undefined local variable or method `run' ...
24
+ expect( error.message ).to match(/undefined.*run/)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ describe 'finish_scan' do
31
+ context 'should exit with status 1' do
32
+ let(:filename) do
33
+ File.absolute_path(File.join(File.dirname(__FILE__), '..', 'samples/low.php'))
34
+ end
35
+
36
+ let(:snippet) do
37
+ scanner.snippet_read(filename, 10)
38
+ end
39
+
40
+ let(:issue) do
41
+ {
42
+ title: 'vuln_name',
43
+ description: 'vuln_description',
44
+ references: [],
45
+ filename: filename,
46
+ snippet: snippet
47
+ }
48
+ end
49
+
50
+ before do
51
+ scanner.parse_opts(['-o', 'xxx', '-c', 'aaa'])
52
+ scanner.add_issue(issue)
53
+ end
54
+
55
+ it do
56
+ expect { scanner.finish_scan }.to raise_error(SystemExit) do |error|
57
+ expect( error.status ).to eq(1)
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'should exit with status 0' do
63
+ let(:filename) do
64
+ File.absolute_path(File.join(File.dirname(__FILE__), '..', 'samples/low.php'))
65
+ end
66
+
67
+ let(:snippet) do
68
+ scanner.snippet_read(filename, 10)
69
+ end
70
+
71
+ before do
72
+ scanner.parse_opts(['-o', 'xxx', '-c', 'aaa'])
73
+ end
74
+
75
+ it do
76
+ expect { scanner.finish_scan }.to raise_error(SystemExit) do |error|
77
+ expect( error.status ).to eq(0)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ describe 'info' do
84
+ subject { scanner.info }
85
+ it 'name' do
86
+ expect(subject[:name]).to eq 'test_name'
87
+ end
88
+
89
+ it 'description' do
90
+ expect(subject[:description]).to eq 'test_desc'
91
+ end
92
+
93
+ it 'support' do
94
+ expect(subject[:support]).to eq ['test_support']
95
+ end
96
+
97
+ it 'version' do
98
+ expect(subject[:version]).to eq '0.1'
99
+ end
100
+ end
101
+
102
+ describe 'add_issue' do
103
+ context 'when issue should be skipped' do
104
+
105
+ let(:snippet) do
106
+ {evidence_line: {content: 'abc', hash: ''}, evidence_full: {content: 'abc', hash: ''}}
107
+ end
108
+
109
+ let(:issue) do
110
+ {
111
+ title: 'vuln_name',
112
+ description: 'vuln_description',
113
+ references: [],
114
+ filename: 'base/.git/xxx',
115
+ snippet: snippet
116
+ }
117
+ end
118
+
119
+ before do
120
+ @status = scanner.add_issue(issue)
121
+ end
122
+
123
+ it { expect(@status).to be nil }
124
+ it { expect(scanner.issues.length).to be 0}
125
+ end
126
+
127
+ context 'when issue should not be skipped' do
128
+
129
+ let(:filename) do
130
+ File.absolute_path(File.join(File.dirname(__FILE__), '..', 'samples/low.php'))
131
+ end
132
+
133
+ let(:snippet) do
134
+ scanner.snippet_read(filename, 10)
135
+ end
136
+
137
+ let(:issue) do
138
+ {
139
+ title: 'vuln_name',
140
+ description: 'vuln_description',
141
+ references: [],
142
+ filename: filename,
143
+ snippet: snippet
144
+ }
145
+ end
146
+
147
+ before do
148
+ scanner.parse_opts(['-c', '/abc/def/ghi'])
149
+ @status = scanner.add_issue(issue)
150
+ end
151
+
152
+ #it { expect(@status).to be scanner.issues }
153
+ it { expect(scanner.issues.length).to be 1}
154
+ it "hash_issue_v1" do
155
+ expect(scanner.issues.first[:hash_issue]).to eq '220da2ef86cb34b97e4253f5b212b2a720c93d717e7fec8f243d851441774181'
156
+ end
157
+
158
+ it "hash_issue_v2" do
159
+ expect(scanner.issues.first[:hash_issue_v2]).to eq '55a52215b49450ebf8fdb8db1d50f4be3d204959989834e25ba2be9e2f2d5b00'
160
+ end
161
+
162
+ end
163
+ end
164
+
165
+ describe 'parse_json_from_str' do
166
+ context 'should parse json from string' do
167
+ it "should parse json from string" do
168
+ expect(scanner.parse_json_from_str('{"abc": "123"}') ).to be_an Hash
169
+ expect(scanner.parse_json_from_str('{"abc": "123"}') ).to have_key("abc")
170
+ expect(scanner.parse_json_from_str('{"abc": "123"}')["abc"] ).to eq "123"
171
+ end
172
+
173
+ it "should return nil when json is invalid" do
174
+ expect(scanner.parse_json_from_str('xxxxx') ).to eq nil
175
+ end
176
+ end
177
+ end
178
+
179
+ describe 'parse_json_from_file' do
180
+ context 'should parse json from file' do
181
+ let(:filename_valid) { '/tmp/json_input_valid_test.json' }
182
+ let(:filename_invalid) { '/tmp/json_input_invalid_test.json' }
183
+
184
+ before do
185
+ File.write(filename_valid, '{"abc": "123"}')
186
+ File.write(filename_invalid, 'xxxxx')
187
+ end
188
+
189
+ it "should parse json from file" do
190
+ expect(scanner.parse_json_from_file(filename_valid) ).to be_an Hash
191
+ expect(scanner.parse_json_from_file(filename_valid) ).to have_key("abc")
192
+ expect(scanner.parse_json_from_file(filename_valid)["abc"] ).to eq "123"
193
+ end
194
+
195
+ it "should return nil when json is invalid" do
196
+ expect(scanner.parse_json_from_file(filename_invalid) ).to eq nil
197
+ end
198
+ end
199
+ end
200
+
201
+ describe 'save_results' do
202
+ context 'should save results to file' do
203
+ let(:report) { '/tmp/save_results.json' }
204
+
205
+ before do
206
+ File.delete(report) if File.exist?(report)
207
+
208
+ allow(scanner).to receive(:generate_sarif_report) { '{}' }
209
+
210
+ scanner.parse_opts(['-o', report])
211
+ scanner.save_scan_output
212
+ end
213
+
214
+ it "should save results to file" do
215
+ expect(File.exist?(report)).to be true
216
+ end
217
+ end
218
+ end
219
+
220
+ describe 'gen_random_tmp_filename' do
221
+ context 'should generate random filename' do
222
+
223
+ it "should generate random filename" do
224
+ expect(scanner.gen_random_tmp_filename('.xxxyyy')).to match /\/tmp\/.*\.xxxyyy/
225
+ end
226
+ end
227
+ end
228
+
229
+ describe 'gen_random_tmp_filename_json' do
230
+ context 'should generate random json filename' do
231
+
232
+ it "should generate random json filename" do
233
+ expect(scanner.gen_random_tmp_filename_json).to match /\/tmp\/.*\.json/
234
+ end
235
+ end
236
+ end
237
+ end
238
+
@@ -0,0 +1,126 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../../lib/sastbox-sdk'
3
+
4
+
5
+ RSpec.describe 'SeverityCalculator' do
6
+ let(:scanner) do
7
+ SastBox::Scanner.new(
8
+ name: 'test_name',
9
+ name_alias: 'test_alias',
10
+ description: 'test_desc',
11
+ support: ['test_support'],
12
+ version: '0.1',
13
+ tool: 'test_tool'
14
+ )
15
+ end
16
+
17
+ describe 'add_severity' do
18
+ context 'when dont have severity field' do
19
+ let(:issue) do
20
+ {
21
+ title: 'cmd exec',
22
+ description: 'cmd exec'
23
+ }
24
+ end
25
+
26
+ before do
27
+ scanner.add_severity(issue)
28
+ end
29
+
30
+ it {expect( issue[:severity]).to eq :critical}
31
+ end
32
+
33
+ context 'when have severity field different from accepted levels' do
34
+ let(:issue) do
35
+ {
36
+ title: 'cmd exec',
37
+ description: 'cmd exec',
38
+ severity: 'anything'
39
+ }
40
+ end
41
+
42
+ before do
43
+ scanner.add_severity(issue)
44
+ end
45
+
46
+ it {expect( issue[:severity]).to eq :critical}
47
+ end
48
+
49
+ context 'when have valid severity field' do
50
+ let(:issue) do
51
+ {
52
+ title: 'anything',
53
+ description: 'anything',
54
+ severity: :info
55
+ }
56
+ end
57
+
58
+ before do
59
+ scanner.add_severity(issue)
60
+ end
61
+
62
+ it {expect( issue[:severity]).to eq :info}
63
+ end
64
+ end
65
+
66
+
67
+ describe 'attempt_to_determine_severity' do
68
+ context 'when critical' do
69
+ let(:issue) do
70
+ {
71
+ title: 'cmd exec',
72
+ description: 'cmd exec'
73
+ }
74
+ end
75
+
76
+ it {expect( scanner.attempt_to_determine_severity(issue)).to eq :critical}
77
+ end
78
+
79
+ context 'when high' do
80
+ let(:issue) do
81
+ {
82
+ title: 'xss',
83
+ description: 'xss'
84
+ }
85
+ end
86
+
87
+ it {expect( scanner.attempt_to_determine_severity(issue)).to eq :high}
88
+ end
89
+
90
+ context 'when medium' do
91
+ let(:issue) do
92
+ {
93
+ title: 'csrf',
94
+ description: 'csrf'
95
+ }
96
+ end
97
+
98
+ it {expect( scanner.attempt_to_determine_severity(issue)).to eq :medium}
99
+ end
100
+
101
+ context 'when low' do
102
+ let(:issue) do
103
+ {
104
+ title: 'logging',
105
+ description: 'logging'
106
+ }
107
+ end
108
+
109
+ it {expect( scanner.attempt_to_determine_severity(issue)).to eq :low}
110
+ end
111
+
112
+ context 'when undefined' do
113
+ let(:issue) do
114
+ {
115
+ title: 'anything',
116
+ description: 'anything'
117
+ }
118
+ end
119
+
120
+ it {expect( scanner.attempt_to_determine_severity(issue)).to eq :undefined}
121
+ end
122
+ end
123
+
124
+
125
+ end
126
+
@@ -0,0 +1,175 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../../lib/sastbox-sdk'
3
+
4
+
5
+ RSpec.describe 'snippet' do
6
+ let(:scanner) do
7
+ SastBox::Scanner.new(
8
+ name: 'test_name',
9
+ name_alias: 'test_alias',
10
+ description: 'test_desc',
11
+ support: ['test_support'],
12
+ version: '0.1',
13
+ tool: 'test_tool'
14
+ )
15
+ end
16
+
17
+ let(:filename) do
18
+ File.absolute_path(File.join(File.dirname(__FILE__), '..', 'samples/low.php'))
19
+ end
20
+
21
+ describe 'filename_relative' do
22
+ before do
23
+ scanner.parse_opts(['-c', '/abc/def/ghi'])
24
+ end
25
+
26
+ context 'filename does not starts with codebase' do
27
+ it {expect( scanner.filename_relative('/xxx/yyy') ).to be nil }
28
+ end
29
+
30
+ context 'filename starts with codebase' do
31
+ it {expect( scanner.filename_relative('/abc/def/ghi/xxx/yyy') ).to eq 'xxx/yyy' }
32
+ end
33
+ end
34
+
35
+ describe 'snippet_calculate_hashes' do
36
+ context 'hashes to match correct value' do
37
+ let(:snippet) do
38
+ {evidence_line: {content: 'abc', hash: ''}, evidence_full: {content: 'abc', hash: ''}}
39
+ end
40
+
41
+ before do
42
+ scanner.snippet_calculate_hashes(snippet)
43
+ end
44
+
45
+ it {expect( snippet[:evidence_line][:hash]).to eq 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' }
46
+
47
+ it {expect( snippet[:evidence_full][:hash]).to eq 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' }
48
+ end
49
+ end
50
+
51
+ describe 'snippet_read' do
52
+ context 'when file exists and line is within range' do
53
+ subject {scanner.snippet_read(filename, 10) }
54
+
55
+ it 'snippet[:read_success]' do
56
+ expect(subject[:read_success]).to be true;
57
+ end
58
+
59
+ it 'snippet[:evidence_line][:content]' do
60
+ expect(subject[:evidence_line][:content]).to eq "\t\t$cmd = shell_exec( 'ping ' . $target );";
61
+ end
62
+
63
+ it 'snippet[:evidence_line][:hash]' do
64
+ expect(subject[:evidence_line][:hash]).to eq '9882497a714594ae1d4ac2e167cce7de6cdc7dd4cffa5456bffd7b3194c9d042';
65
+ end
66
+
67
+ it 'snippet[:evidence_full][:hash]' do
68
+ expect(subject[:evidence_full][:hash]).to eq 'c61da3e81b8847eb0b6b34bda42db8177e120b6b1fc8e19e0ed332d6751000f0';
69
+ end
70
+ end
71
+
72
+ context 'when file does not exist' do
73
+ subject {scanner.snippet_read('/tmp/qwuhasgnewhbeqwyegasdf', 10) }
74
+
75
+ it 'snippet[:read_success]' do
76
+ expect(subject[:read_success]).to be false;
77
+ end
78
+
79
+ it 'snippet[:evidence_line][:content]' do
80
+ expect(subject[:evidence_line][:content]).to eq ''
81
+ end
82
+
83
+ it 'snippet[:evidence_line][:hash]' do
84
+ expect(subject[:evidence_line][:hash]).to eq '';
85
+ end
86
+
87
+ it 'snippet[:evidence_full][:hash]' do
88
+ expect(subject[:evidence_full][:hash]).to eq '';
89
+ end
90
+ end
91
+
92
+ context 'when file exists and line is out of range' do
93
+ subject {scanner.snippet_read(filename, 50000) }
94
+
95
+ it 'snippet[:read_success]' do
96
+ expect(subject[:read_success]).to be false;
97
+ end
98
+
99
+ it 'snippet[:evidence_line][:content]' do
100
+ expect(subject[:evidence_line][:content]).to eq ''
101
+ end
102
+
103
+ it 'snippet[:evidence_line][:hash]' do
104
+ expect(subject[:evidence_line][:hash]).to eq '';
105
+ end
106
+
107
+ it 'snippet[:evidence_full][:hash]' do
108
+ expect(subject[:evidence_full][:hash]).to eq '';
109
+ end
110
+ end
111
+ end
112
+
113
+ describe 'snippet_read_range' do
114
+ context 'when file exists and start/end line is within range' do
115
+ subject {scanner.snippet_read_range(filename, 17, 18) }
116
+
117
+ it 'snippet[:read_success]' do
118
+ expect(subject[:read_success]).to be true;
119
+ end
120
+
121
+ it 'snippet[:evidence_line][:content]' do
122
+ expect(subject[:evidence_line][:content]).to eq "\t// Feedback for the end user\r\n\t$html .= \"<pre>{$cmd}</pre>\";\r\n";
123
+ end
124
+
125
+ it 'snippet[:evidence_line][:hash]' do
126
+ expect(subject[:evidence_line][:hash]).to eq '1beb122abba992b58df776523269522a6b0411679e991f62e2fa116db6d960ff';
127
+ end
128
+
129
+ it 'snippet[:evidence_full][:hash]' do
130
+ expect(subject[:evidence_full][:hash]).to eq '9a4a2ee8ed7a70956e9960036e036770499f48225f20c42bb8d21a2f40771dc6';
131
+ end
132
+ end
133
+
134
+ context 'when file does not exist' do
135
+ subject {scanner.snippet_read_range('/tmp/qwuhasgnewhbeqwyegasdf', 17, 18) }
136
+
137
+ it 'snippet[:read_success]' do
138
+ expect(subject[:read_success]).to be false;
139
+ end
140
+
141
+ it 'snippet[:evidence_line][:content]' do
142
+ expect(subject[:evidence_line][:content]).to eq ''
143
+ end
144
+
145
+ it 'snippet[:evidence_line][:hash]' do
146
+ expect(subject[:evidence_line][:hash]).to eq '';
147
+ end
148
+
149
+ it 'snippet[:evidence_full][:hash]' do
150
+ expect(subject[:evidence_full][:hash]).to eq '';
151
+ end
152
+ end
153
+
154
+ context 'when file exists and start/end line is out of range' do
155
+ subject {scanner.snippet_read_range(filename, 50000, 60000) }
156
+
157
+ it 'snippet[:read_success]' do
158
+ expect(subject[:read_success]).to be false;
159
+ end
160
+
161
+ it 'snippet[:evidence_line][:content]' do
162
+ expect(subject[:evidence_line][:content]).to eq ''
163
+ end
164
+
165
+ it 'snippet[:evidence_line][:hash]' do
166
+ expect(subject[:evidence_line][:hash]).to eq '';
167
+ end
168
+
169
+ it 'snippet[:evidence_full][:hash]' do
170
+ expect(subject[:evidence_full][:hash]).to eq '';
171
+ end
172
+ end
173
+ end
174
+ end
175
+