bscan 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7cd2c132cb1c5719f640c8820bcea3eb7b0fa121
4
+ data.tar.gz: db78ba320a6d30b6d587b23f38d5b69f2841b0b7
5
+ SHA512:
6
+ metadata.gz: 1de53e763e7160627e70880ffeb82eee7991aab9cfcedc0ae42627ea200630fc708737910614ffc0cfb2e2e762832641d9a47f5f6e252252e9528154f8c64c0d
7
+ data.tar.gz: 1992b9fcac4775b3f5cdafb69c5b517b67b81bd9739daad4b40f9812d6c0abbde65ba4d1d80e5c387c2147afddc03e773ac4a5072a260cdfca79f75900062e1b
@@ -32,12 +32,17 @@ see BscannerHelper#search_path for details
32
32
 
33
33
  == BScan Parameters
34
34
  * bscan.modules - see 'CONVENTIONS' for details
35
- * bscan.inactivity_to - inactivity is sec that triggers exit
35
+ * bscan.inactivity_to - inactivity is sec that triggers exit and generating a report
36
+ * bscan.run_proxy - run Burp proxy and collect vulns in passive mode
37
+ Default: false
38
+ * bscan.report_url_prefix=<URL-prefix>|<path-to-report-file.xml> sort reports by URL
39
+ * bscan.report_def_name=<path-to-report-file.xml> default report file
36
40
  * bscan.issues=issues - output directory for findings/issues
37
41
  * scan.modules_only - if true, only modules with static requests
38
42
  will run (no spider)
39
43
  * bscan.url - URL to spider, multiple entries are OK. Have no effect
40
44
  if scan.modules_only=true
45
+ * proxy.listener0=1.<port>.1.0..0.0.1.0..0..0..0. - this is a burp's param, used to change a proxy's port number
41
46
 
42
47
  == BScan SMTP Parameters
43
48
  If specified an email will be sent. If 'include_report' is set
@@ -2,9 +2,12 @@
2
2
  == DESCRIPTION:
3
3
  BScan is a configurable and extendable command line application security scanner.
4
4
  It's built on top of arguably the most popular commercial security testing tool
5
- Burp Suite from PortSwigger and Buby from Eric Monti and Timur Duehr
5
+ Burp Suite from PortSwigger
6
6
 
7
7
  == USE CASES:
8
+ * Run Burp proxy from a command line and passively scan, e.g. QA regression traffic:
9
+ jruby -S bscan -c bscan.config -l bscan.log
10
+
8
11
  * Run security scans offline from a command line headless (without UI).
9
12
 
10
13
  * Change the type of scanning easily by changing configuration parameters.
@@ -22,13 +25,11 @@ Burp Suite from PortSwigger and Buby from Eric Monti and Timur Duehr
22
25
  == DOCS, CODE, etc.:
23
26
  * Documentation: http://gryb.info/bscan
24
27
  * Git repo: git://git.code.sf.net/p/b-scan/trunk
25
- * Sourceforge: http://sf.net/projects/b-scan/
26
28
  * Gem package: http://gemcutter.org (see 'BUILD/INSTALL')
27
29
 
28
30
  == REQUIREMENTS:
29
31
  * JRuby - http://jruby.org
30
32
  * Burp pro if you want to use default Burp's scanners
31
- * Buby 1.3.1 (see http://emonti.github.com/buby/) (not neccessary for modules_only mode)
32
33
 
33
34
  == BUILD/INSTALL:
34
35
 
@@ -37,14 +38,13 @@ Burp Suite from PortSwigger and Buby from Eric Monti and Timur Duehr
37
38
  sudo jruby -S gem install buby -d --source=http://gemcutter.org (not necessary for modules_only)
38
39
  sudo jruby -S gem install bscan --source=http://gemcutter.org
39
40
 
40
- After Buby and BScan are installed, you'll need to link BScan to Burp's JAR (see below)
41
41
 
42
42
  === Building Manually from Git
43
43
 
44
44
  git git://git.code.sf.net/p/b-scan/trunk <src_dir>
45
45
  cd <src_dir>
46
- jruby -S gem build bscan.gemspec
47
- jruby -S gem install -d --local bscan-*.gem
46
+ jruby -S rake build gemspec
47
+ sudo jruby -S gem install --local pkg/bscan-*.gem (sudo might not be necessary on some systems)
48
48
  bscan --help
49
49
  bscan --help config
50
50
 
@@ -52,22 +52,29 @@ Burp Suite from PortSwigger and Buby from Eric Monti and Timur Duehr
52
52
 
53
53
  * This step is not neccessary for modules_only mode
54
54
 
55
- After Buby and BScan are installed (either manually or by gem)
56
- you'll need to link them to a Burp's JAR.
55
+ Java code is used to register a Burp extension and to bind Burp's events to Ruby functions.
57
56
 
58
- The easiest way of doing that is to find the directory where buby.jar is located
59
- and then create a link from that directory to a Burp's jar:
57
+ You'll need to re-compile it in at least three following cases:
60
58
 
61
- cd <dir_where_buby.jar_is_located>
62
- ln -s <path_to_burp*.jar> <dir_where_buby.jar_is_located>/burp.jar
59
+ 1. You want to link to your own license version of Burp's jar. The default BScan comes with a public Burp's version.
60
+ 2. You want to update the Burp's jar when a new version is released (either public or licensed).
61
+ 3. You want to change the Java code.
63
62
 
64
- To find where buby.jar is located you can print JRuby's search path using:
65
-
66
- jruby -e 'puts $:'
63
+ Use the following commands to recompile Java and to put a generated jar to the right location
67
64
 
68
- and then run 'find' command for each dirctory in the search path:
69
-
70
- find <dir> -name buby.jar
65
+ cd <src-dir>/java
66
+ ./build.sh <path-to-burp-jar>
67
+
68
+ Verify that the Java build was successful by typing:
69
+
70
+ ls -l ../lib
71
+
72
+ You should look for two jar files in that directory:
73
+
74
+ bscan.jar
75
+ burp.jar
76
+
77
+ They will be deployed to JRuby locations when you install the gem
71
78
 
72
79
  == TEST AND USAGE EXAMPLE:
73
80
 
@@ -84,9 +91,8 @@ You need to register you burp.jar before you can run it headless
84
91
 
85
92
  * Not neccessary for modules_only mode
86
93
 
87
- * Run your Burp as usual with GUI and provide you license.
88
- After this is done, you can run it headless using 'bscan'
89
-
94
+ * Either run Burp with UI and upload the license there or run it headless and copy/paste the license when prompted.
95
+ * No license will be asked for a public version.
90
96
 
91
97
  == DOCUMENTATION, SAMPLES, RUNNING HEADLESSLY
92
98
  * Rdoc generated files: http://gryb.info/bscan/
@@ -103,8 +109,7 @@ You need to register you burp.jar before you can run it headless
103
109
  Copyright 2012 PortSwigger Ltd. All rights reserved.
104
110
  See http://portswigger.net for license terms.
105
111
 
106
- * Buby library and the accompanying BurpExtender.java implementation are
107
- written by Eric Monti @ Matasano Security. Matasano Security claims no
112
+ * Buby BurpExtender.java has been initially implemented by Eric Monti @ Matasano Security and modified by Oleg Gryb. Matasano Security claims no
108
113
  professional or legal affiliation with PortSwigger LTD.
109
114
 
110
115
  * This BScan tools and library written by Oleg Gryb who claims no professional or
@@ -121,8 +126,7 @@ You need to register you burp.jar before you can run it headless
121
126
  Copyright 2012 PortSwigger Ltd. All rights reserved.
122
127
  See http://portswigger.net for license terms.
123
128
 
124
- * The Buby library and its accompanying BurpExtender implementation are
125
- both freely available under the terms of the MIT public license:
129
+ * The BurpExtender implementation is freely available under the terms of the MIT public and BSD 2-Clause license:
126
130
 
127
131
  (The MIT License)
128
132
 
@@ -134,15 +138,12 @@ The above copyright notice and this permission notice shall be included in all c
134
138
 
135
139
  THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
136
140
 
137
- * The BScan tools and library are freely available under the terms of the MIT public license:
138
-
139
- (The MIT License)
140
-
141
- Copyright (C) 2012 Oleg Gryb
142
-
143
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
144
-
145
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
146
-
147
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
141
+ * The BScan tools and library are freely available under the terms of the BSD 2-Clause license:
148
142
 
143
+ Copyright (C) 2015, Oleg Gryb
144
+ All rights reserved.
145
+
146
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
147
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
148
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
149
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Rakefile CHANGED
@@ -1,3 +1,13 @@
1
+ =begin
2
+ Copyright (c) 2015, Oleg Gryb
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9
+ =end
10
+
1
11
  require 'rubygems'
2
12
  require 'rake'
3
13
  require 'rake/clean'
@@ -5,8 +15,10 @@ require 'rake/clean'
5
15
  begin
6
16
  require 'jeweler'
7
17
  Jeweler::Tasks.new do |gem|
8
- gem.add_dependency('buby', '>= 1.3.1')
18
+ # gem.add_dependency('buby', '>= 1.3.1')
19
+ # gem.add_dependency(nil)
9
20
  gem.name = "bscan"
21
+ gem.license = "BSD 2-Clause"
10
22
  gem.summary = %q{BScan is an extendable and configurable command line web application security scanner}
11
23
  gem.description = %q{BScan is a configurable and extendable web application security scanner that can be run from a command line headless (without UI). It's built on top of arguably the most popular commercial security testing tool Burp Suite from PortSwigger and Buby from Eric Monti and Timur Duehr}
12
24
  gem.email = "oleg@gryb.info"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.1
1
+ 3.0.0
data/bin/bscan CHANGED
@@ -1,24 +1,37 @@
1
1
  #!/usr/bin/env jruby
2
2
 
3
+ =begin
4
+ Copyright (c) 2015, Oleg Gryb
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11
+ =end
12
+
3
13
  #require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib bscan]))
4
14
  $: << File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib]))
5
15
 
16
+ require 'java'
6
17
  require 'getoptlong'
7
18
  require 'bscan/utils/bscan_helper'
8
19
  require 'json'
9
20
 
21
+
10
22
  include BscanHelper
11
23
 
12
24
  def usage
13
25
 
14
26
  puts %q{
15
27
  USAGE: jruby [-J-Xmx<nnn>M] [-J-Djava.awt.headless=true] -S bscan --config path_to_file \
16
- [--help [config]] [--loglevel n] [--logfile file] [--version]
28
+ [--configonly] [--help [config]] [--loglevel n] [--logfile file] [--version]
17
29
 
18
30
  -J-Xmx<nnn>M tells JVM to set maximum heap size to <nnn> MB
19
31
  -J-Djava.awt.headless=true tells JVM to run it headless (no UI)
20
32
  -S tells jruby to search for bscan in a PATH
21
33
  --config -c path_to_file path to config (see 'CONFIG' section in rdoc)
34
+ --configonly -O configure burp and exit
22
35
  --help -h this help
23
36
  --help config config help
24
37
  --loglevel -L 0 errors, 1 - warning, 2 - info, 3 - debug
@@ -64,6 +77,7 @@ def get_cmd_params
64
77
  [ '--help', '-h', GetoptLong::OPTIONAL_ARGUMENT ],
65
78
  [ '--version', '-v', GetoptLong::NO_ARGUMENT ],
66
79
  [ '--config', '-c', GetoptLong::REQUIRED_ARGUMENT ],
80
+ [ '--configonly', '-O', GetoptLong::NO_ARGUMENT ],
67
81
  [ '--loglevel', '-L', GetoptLong::REQUIRED_ARGUMENT ],
68
82
  [ '--logfile', '-l', GetoptLong::REQUIRED_ARGUMENT ]
69
83
  )
@@ -82,6 +96,8 @@ def get_cmd_params
82
96
  exit(1)
83
97
  when '--config'
84
98
  params['burp_config'], params['bscan_config'] = read_config(arg)
99
+ when '--configonly'
100
+ params['burp_config_only'] = true
85
101
  when '--loglevel'
86
102
  params['loglevel'] = arg
87
103
  when '--logfile'
@@ -108,10 +124,12 @@ init_internals params
108
124
  run_modules self
109
125
  exit 0 if @modules_only
110
126
 
111
- require 'buby'
112
- require 'burp'
127
+ #require 'buby'
128
+ #require 'burp'
113
129
  require 'bscan'
130
+ include BScan
131
+
132
+ #$burp = Buby.new()
133
+ #$burp.extend(BScan)
114
134
 
115
- $burp = Buby.new()
116
- $burp.extend(BScan)
117
- $burp.start_burp([params.to_json])
135
+ start_burp([params.to_json], ARGV)
Binary file
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ [ -f "$1" ] || (echo Usage: ./build.sh path_to_burp_jar && exit 1)
4
+
5
+ cp "$1" lib/.
6
+ rm -rf bin/burp bin/bscan*
7
+ javac -cp 'lib/*' -d bin src/burp/BurpExtender.java
8
+ jar -cf bin/bscan.jar -C bin burp/BurpExtender.class
9
+ cp bin/bscan.jar ../lib/.
10
+ cp lib/burp*.jar ../lib/burp.jar
Binary file
@@ -0,0 +1,146 @@
1
+ package burp;
2
+
3
+ import burp.*;
4
+
5
+ import org.jruby.*;
6
+ import org.jruby.javasupport.JavaUtil;
7
+ import org.jruby.runtime.ThreadContext;
8
+ import org.jruby.runtime.builtin.IRubyObject;
9
+ import org.jruby.RubyBoolean;
10
+
11
+ import java.io.File;
12
+ import java.util.HashMap;
13
+ import java.util.List;
14
+ import java.util.Map;
15
+
16
+ import javax.swing.JMenuItem;
17
+
18
+ public class BurpExtender implements IBurpExtender, IHttpListener, IScannerListener, ISessionHandlingAction {
19
+
20
+ // Internal reference to hold the ruby Burp handler
21
+ private static IRubyObject r_obj = null;
22
+ private IBurpExtenderCallbacks burp_cb = null;
23
+ public static void setHandler(IRubyObject hnd) { r_obj = hnd; }
24
+ public static IRubyObject getHandler() { return r_obj; }
25
+
26
+ public BurpExtender() {
27
+ if (r_obj !=null)
28
+ r_obj.callMethod(ctx(r_obj), "evt_extender_init", to_ruby(rt(r_obj), this));
29
+ }
30
+
31
+ public void setCommandLineArgs(String[] args) {
32
+ if(r_obj != null)
33
+ r_obj.callMethod(ctx(r_obj), "evt_commandline_args", to_ruby(rt(r_obj), args));
34
+ }
35
+
36
+ @Override
37
+ public void registerExtenderCallbacks(IBurpExtenderCallbacks cb) {
38
+ this.burp_cb = cb;
39
+ cb.setExtensionName("BScan");
40
+ cb.issueAlert("registering JRuby handler callbacks for BScan");
41
+ cb.registerHttpListener(this);
42
+ cb.registerScannerListener(this);
43
+ cb.registerSessionHandlingAction(this);
44
+ // this.burp_cb.issueAlert("Listeners: " + cb.getHttpListeners().get(0).toString());
45
+ if(r_obj != null) {
46
+ IRubyObject args[] = {to_ruby(rt(r_obj), cb), RubyBoolean.newBoolean(rt(r_obj), false)};
47
+ r_obj.callMethod(ctx(r_obj), "evt_register_callbacks", args[0]);
48
+ }
49
+ }
50
+ /*
51
+ public void processHttpMessage(
52
+ String toolName,
53
+ boolean messageIsRequest,
54
+ IHttpRequestResponse messageInfo )
55
+ {
56
+ this.burp_cb.issueAlert("HttpMessage from: " + toolName + " " + messageIsRequest);
57
+ if (r_obj != null && r_obj.respondsTo("evt_http_message")) {
58
+ Ruby rt = rt(r_obj);
59
+ IRubyObject http_msg[] = {
60
+ to_ruby(rt, toolName),
61
+ to_ruby(rt, messageIsRequest),
62
+ to_ruby(rt, messageInfo)
63
+ };
64
+
65
+ r_obj.callMethod(ctx(r_obj), "evt_http_message", http_msg);
66
+ }
67
+ }
68
+ */
69
+
70
+ @Override
71
+ public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo)
72
+ {
73
+ // this.burp_cb.issueAlert("HttpMessage from: " + toolFlag + " " + messageIsRequest);
74
+ if (r_obj != null) {
75
+ Ruby rt = rt(r_obj);
76
+ IRubyObject http_msg[] = {
77
+ to_ruby(rt, toolFlag),
78
+ to_ruby(rt, messageIsRequest),
79
+ to_ruby(rt, messageInfo)
80
+ };
81
+
82
+ // this.burp_cb.issueAlert("HttpMessage from: " + toolFlag);
83
+ r_obj.callMethod(ctx(r_obj), "evt_http_message", http_msg);
84
+ }
85
+ }
86
+
87
+ @Override
88
+ public void newScanIssue(IScanIssue issue) {
89
+
90
+ // this.burp_cb.issueAlert("newScanIssue: " + issue.getIssueDetail());
91
+ if (r_obj != null)
92
+ r_obj.callMethod(ctx(r_obj), "evt_scan_issue", to_ruby(rt(r_obj), issue));
93
+ }
94
+
95
+
96
+ public void applicationClosing() {
97
+ if (r_obj != null)
98
+ r_obj.callMethod(ctx(r_obj), "evt_application_closing");
99
+ }
100
+
101
+ private ThreadContext ctx(IRubyObject obj) {
102
+ return rt(obj).getThreadService().getCurrentContext();
103
+ }
104
+
105
+ private Ruby rt(IRubyObject obj) {
106
+ return obj.getRuntime();
107
+ }
108
+
109
+ public IRubyObject to_ruby(Ruby rt, Object obj) {
110
+ return JavaUtil.convertJavaToUsableRubyObject(rt, obj);
111
+ }
112
+ @Override
113
+ public String getActionName() {
114
+ String ret = "";
115
+ // this.burp_cb.issueAlert("getActionName");
116
+ if (r_obj != null)
117
+ ret = r_obj.callMethod(ctx(r_obj), "evt_get_action_name").asJavaString();
118
+ // this.burp_cb.issueAlert("getActionName " + ret);
119
+ return ret;
120
+ }
121
+ @Override
122
+ public void performAction(IHttpRequestResponse req,
123
+ IHttpRequestResponse[] macros) {
124
+ // this.burp_cb.issueAlert("perfromAction");
125
+
126
+ if (r_obj != null)
127
+ r_obj.callMethod(ctx(r_obj), "evt_perfrom_action", to_ruby(rt(r_obj), req));
128
+ }
129
+
130
+ public void loadConfig (RubyHash rh, String defConfigFile) {
131
+
132
+ if (defConfigFile != null) {
133
+ this.burp_cb.restoreState(new File(defConfigFile));
134
+ }
135
+
136
+ Map<String,String> map = new HashMap<String,String>();
137
+ for (Object k : rh.keys()) {
138
+ map.put((String) k, (String) rh.get(k));
139
+ }
140
+ this.burp_cb.loadConfig(map); // this will set custom config
141
+ // this.burp_cb.issueAlert("Config loaded");
142
+ // this.burp_cb.issueAlert("Listeners after load: " + this.burp_cb.getHttpListeners().get(0).toString());
143
+ }
144
+
145
+ }
146
+
Binary file
@@ -1,54 +1,173 @@
1
1
  #!/usr/bin/env jruby
2
2
 
3
- require 'buby'
3
+
4
+ =begin
5
+ Copyright (c) 2015, Oleg Gryb
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
9
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+ =end
13
+
4
14
  require 'getoptlong'
5
15
  require 'bscan/utils/bscan_helper'
6
16
  require 'bscan/utils/mailer'
7
17
  require 'java'
8
18
  require 'json'
19
+ require 'bscan.jar'
20
+ require 'burp.jar'
9
21
 
10
22
  module BScan
11
23
 
12
24
  include BscanHelper
13
25
  include Mailer
14
26
 
27
+ def start_burp args, arg_strs
28
+ Java.burp.BurpExtender.handler = self
29
+ init_internals JSON.parse(args[0])
30
+ Java.burp.StartBurp.main(arg_strs.to_java(:string))
31
+
32
+ end
15
33
 
34
+ def evt_extender_init ext
35
+ @burp_extender = ext
36
+ Log 2, "#"*70, "# BScan.evt_extender_init EXT: #{ext.toString}", "#"*70
37
+ end
38
+
16
39
  def evt_commandline_args args
17
40
  init_internals JSON.parse(args[0])
18
41
  end
19
42
 
43
+ def get_filtered_issues issues
44
+
45
+ info = get_bool_prop('bscan.ignore_info')
46
+ low = get_bool_prop('bscan.ignore_low')
47
+ medium = get_bool_prop('bscan.ignore_medium')
48
+ high = get_bool_prop('bscan.ignore_high')
49
+
50
+ return issues if (not (info or low or medium or high))
51
+
52
+ filtered = []
53
+ issues.each do |i|
54
+ # puts "=============ISSUE==================="
55
+ # puts i
56
+ # puts i.getSeverity()
57
+ # i.getClass().methods.each do |m|
58
+ # p m.getName()
59
+ # end
60
+ # puts
61
+ case i.getSeverity()
62
+ when 'Information'
63
+ filtered.push(i) if not info
64
+ when 'Low'
65
+ filtered.push(i) if not low
66
+ when 'Medium'
67
+ filtered.push(i) if not medium
68
+ when 'High'
69
+ filtered.push(i) if not high
70
+ end
71
+ end
72
+ return filtered
73
+ end
20
74
 
75
+ def gen_report
76
+ issues = nil
77
+ if not @url_prefs
78
+ issues = @burp_cb.getScanIssues(nil)
79
+ file = "report.xml"
80
+ file = @bscan_config['bscan.report_def_name'] if @bscan_config['bscan.report_def_name']
81
+ file = File.expand_path(File.join(@issues, [file])) if @issues
82
+ gen_report_params(issues,file)
83
+ else
84
+ i=1
85
+ @url_prefs.each do |url_name|
86
+ u, n = url_name.split('|')
87
+ n = 'pref' + i.to_s if not n
88
+ i += 1
89
+ issues = @burp_cb.getScanIssues(u)
90
+ n = File.expand_path(File.join(@issues, [n])) if @issues
91
+ gen_report_params(issues,n)
92
+ end
93
+ end
94
+ end
95
+ def gen_report_params issues, file
96
+ io = Java.java.io.File.new(file.to_java(:string))
97
+ filtered = get_filtered_issues(issues)
98
+ @burp_cb.generateScanReport("XML".to_java(:string), filtered, io)
99
+ Log 2, "#"*70, "# BScan.gen_report: #{file} #{io.to_s} #{filtered.to_s}", "#"*70
100
+ end
21
101
 
22
- def evt_http_message(tool_name, is_request, message_info)
23
- super(tool_name, is_request, message_info)
24
- if tool_name == 'Scanner'
25
- if is_request
26
- Log 2, "#"*70, "# BScan.evt_http_message REQUEST: #{message_info.url.toString}, tool: #{tool_name}", "#"*70
27
- Log 3, "BScan.evt_http_message #{message_info.req_str}", ""
28
- else
29
- Log 2, "# BScan.evt_http_message RESPONSE CODE: #{message_info.statusCode}", ""
30
- Log 3, "BScan.evt_http_message #{message_info.rsp_str}", ""
102
+ def evt_get_action_name
103
+ Log 2, "# BScan.evt_get_action_name"
104
+ ret = ''
105
+ acts = get_action
106
+ Log 2, "# BScan.evt_get_action_name"
107
+ ret = acts.join('+') if acts.size > 0
108
+ ret
109
+ end
110
+
111
+ def evt_perfrom_action req
112
+ acts = get_action
113
+ pars = get_action_params
114
+ Log 3, "BScan.evt_perform_action #{acts[0]} #{pars[0]}"
115
+ msg_info = @burp_cb.getHelpers().analyzeRequest(req)
116
+ msg_body = req.getRequest()[msg_info.getBodyOffset()..-1]
117
+ i = 0
118
+ acts.each do |a|
119
+ par = pars[i]
120
+ i++
121
+ case a
122
+ when 'add_header'
123
+ Log 3, "BScan.evt_perform_action #{msg_info.getRequest().to_s} #{a} #{par}"
124
+ hdrs = msg_info.getHeaders()
125
+ hdrs.add(par.to_java(:string))
126
+ msg = @burp_cb.getHelpers().buildHttpMessage(hdrs, msg_body)
127
+ @burp_cb.issueAlert(@burp_cb.getHelpers().bytesToString(msg))
128
+ req.setRequest(msg)
31
129
  end
32
130
  end
33
- if tool_name == 'Spider'
34
- if not is_request
35
- @activity[0] = true
36
- https = message_info.getProtocol() == "https" ? true : false
37
- Log 2, "BScan.evt_http_message Passively scanning: #{message_info.url.to_string}"
38
- do_passive_scan(message_info.getHost(), message_info.getPort(), https, message_info.getRequest(), message_info.getResponse())
39
- if (is_in_scope(message_info.url))
40
- Log 2, "BScan.evt_http_message Actively scanning: #{message_info.url.to_string}"
41
- isqi = do_active_scan(message_info.getHost(), message_info.getPort(), https, message_info.getRequest(), [])
42
- @queue.push(isqi)
43
- run_modules self, message_info
131
+ end
132
+
133
+ def evt_http_message(tool_name, is_request, message_info)
134
+ # super(tool_name, is_request, message_info)
135
+ begin
136
+ Log 3, "BScan.evt_http_message #{tool_name} #{Java.burp.IBurpExtenderCallbacks.TOOL_SPIDER} #{is_request} #{message_info.to_s}"
137
+ if tool_name == Java.burp.IBurpExtenderCallbacks.TOOL_SCANNER or tool_name == 'scanner'
138
+ if is_request
139
+ Log 2, "#"*70, "# BScan.evt_http_message REQUEST: #{message_info.url.toString}, tool: #{tool_name}", "#"*70
140
+ Log 3, "BScan.evt_http_message #{message_info.getRequest()}", ""
141
+ else
142
+ Log 2, "# BScan.evt_http_message RESPONSE CODE: #{message_info.statusCode}", ""
143
+ Log 3, "BScan.evt_http_message #{message_info.getResponse()}", ""
44
144
  end
45
- end
46
- end
145
+ end
146
+ if tool_name == Java.burp.IBurpExtenderCallbacks.TOOL_SPIDER or tool_name == 'spider'\
147
+ or tool_name == Java.burp.IBurpExtenderCallbacks.TOOL_PROXY or tool_name == 'proxy'
148
+ if not is_request
149
+ @activity[0] = true
150
+ https = message_info.getProtocol() == "https" ? true : false
151
+ Log 2, "BScan.evt_http_message Passively scanning: #{message_info.url.to_string}"
152
+ do_passive_scan(message_info.getHost(), message_info.getPort(), https, message_info.getRequest(), message_info.getResponse())
153
+ if (is_in_scope(message_info.url) and not excluded? message_info.url)
154
+ Log 2, "BScan.evt_http_message Actively scanning: #{message_info.url.to_string}"
155
+ # isqi = do_active_scan(message_info.getHost(), message_info.getPort(), https, message_info.getRequest(), [])
156
+ isqi = do_active_scan(message_info.getHost(), message_info.getPort(), https, message_info.getRequest())
157
+ @queue.push(isqi)
158
+ run_modules self, message_info
159
+ end
160
+ end
161
+ end
162
+ rescue Exception => e
163
+ Log 0, "BScan.evt_http_message Exception: #{e.message}"
164
+ Log 0, e.backtrace.join("\n")
165
+ end
47
166
  end
48
167
 
49
168
 
50
169
  def evt_scan_issue issue
51
- super(issue)
170
+ # super(issue)
52
171
  # Buby::HttpRequestResponseHelper.implant(issue.http_messages)
53
172
  write_issue_state issue
54
173
  end
@@ -64,10 +183,14 @@ module BScan
64
183
  def evt_application_closing
65
184
  begin
66
185
  Log 2,"BScan.evt_application_closing #{@bscan_config['bscan.smtp.server']} #{@bscan_config['bscan.smtp.to']}"
67
- @istream.close if @istream
68
- @stat['end_time'] = Time.now.strftime("%Y-%m-%d %H:%M:%S")
69
- send_email if @bscan_config['bscan.smtp.server'] and @bscan_config['bscan.smtp.to']
70
- @log.close if @log
186
+ if not @load_config_flag
187
+ @istream.close if @istream
188
+ @stat['end_time'] = Time.now.strftime("%Y-%m-%d %H:%M:%S")
189
+ send_email if @bscan_config['bscan.smtp.server'] and @bscan_config['bscan.smtp.to']
190
+ @log.close if @log
191
+ # exit_suite false
192
+ end
193
+ @load_config_flag = false
71
194
  rescue Exception => e
72
195
  Log 0, "BScan.evt_application_closing Exception: #{e.message}"
73
196
  Log 0, e.backtrace.join("\n")
@@ -75,7 +198,8 @@ module BScan
75
198
  end
76
199
 
77
200
  def evt_register_callbacks cb
78
- super(cb)
201
+ # super(cb)
202
+ @burp_cb = cb
79
203
  @burp ||= self
80
204
  begin
81
205
  Log 2, "="*30, "BScan.evt_register_callbacks registring, log = #{@cmd_params['logfile']} ", "="*30
@@ -84,14 +208,18 @@ module BScan
84
208
  @queue ||= []
85
209
  @inactivity_to = @bscan_config['bscan.inactivity_to']
86
210
  @inactivity_to ||= '30'
211
+ @max_proxy_time ||= '30'
87
212
  @inactivity_to = @inactivity_to.to_i
213
+ @max_proxy_time = @max_proxy_time.to_i
88
214
  # Will exit if @activity = 0 and @queue is empty two times
89
215
  if @monitor == nil
90
216
  Log 2, "="*30, "BScan.evt_register_callbacks Starting Monitor", "="*30
91
217
  @monitor = Thread.new(@queue, @activity) {|q,a|
92
218
  cnt=0;
93
219
  while (true)
94
- sleep(@inactivity_to/2)
220
+ sleep(@inactivity_to/2)
221
+ @max_proxy_time -= @inactivity_to/2
222
+
95
223
  q.delete_if {|e| e.getPercentageComplete() == 100}
96
224
  if q.length == 0 and not a[0]
97
225
  cnt += 1
@@ -99,11 +227,15 @@ module BScan
99
227
  cnt = 0
100
228
  # Log 2, "BScan.evt_register_callbacks QUEUE: #{q.length}, Activity: #{a[0]}"
101
229
  end
102
- if cnt > 1
103
- # Log 2, "BScan.evt_register_callbacks Scanning complete"
104
- exit_suite
230
+ if cnt > 1
231
+ Log 2, "BScan.evt_register_callbacks Scanning complete"
232
+ if @run_proxy
233
+ gen_report
234
+ end
235
+ exit_suite false
105
236
  break
106
237
  end
238
+ Log 2, "BScan.evt_register_callbacks monitor #{@run_proxy} #{@max_proxy_time}"
107
239
  a[0] = false
108
240
  end
109
241
  }
@@ -111,11 +243,19 @@ module BScan
111
243
 
112
244
  Log 2, '='*30, 'BScan.evt_register_callbacks Params', '='*30
113
245
  params = save_config
246
+ # params.each_pair {|k,v| Log 2,"#{k}:#{v}:#{v.class}"} # if k =~ /^(scanner|spider)/}
114
247
  params['target.scopeinclude0']='**empty**' # burp can store the previous scope somehow, thus need to clean
115
248
  @burp_config.each_pair do |k,v|
116
- params[k] = v
117
- end
118
- load_config params
249
+ params[k] = v if params[k]
250
+ end
251
+ add_spider_headers(params)
252
+ if @cmd_params['burp_config_only']
253
+ load_config params, @bscan_config['bscan.burp_defaults']
254
+ exit_suite false
255
+ else
256
+ load_config @burp_config
257
+ end
258
+
119
259
  params.each_pair {|k,v| Log 2,"#{k}:#{v}"} # if k =~ /^(scanner|spider)/}
120
260
 
121
261
  # run_modules
@@ -123,24 +263,27 @@ module BScan
123
263
 
124
264
  urls = @bscan_config['bscan.url']
125
265
  Log 2, "BScan.evt_register_callbacks urls: #{@modules_only} #{urls}"
126
-
127
- if not urls
266
+
267
+
268
+ if not urls and not @run_proxy
128
269
  Log 0, "BScan.evt_register_callbacks No URL's provided in config. Use bscan.url param. Multiple entries are OK"
129
- exit_suite
270
+ exit_suite false
130
271
  end
131
272
 
132
- urls = [urls] if not urls.kind_of?(Array)
273
+ urls = [urls] if urls and not urls.kind_of?(Array)
133
274
 
134
- urls.each do |u|
135
- Log 2, "BScan.evt_register_callbacks checking url: #{u}"
136
- if not is_in_scope(u)
137
- Log 2, "BScan.evt_register_callbacks including url: #{u}"
138
- include_in_scope(u)
275
+ if urls
276
+ urls.each do |u|
277
+ Log 2, "BScan.evt_register_callbacks checking url: #{u}"
278
+ if not is_in_scope(u)
279
+ Log 2, "BScan.evt_register_callbacks including url: #{u}"
280
+ include_in_scope(u)
281
+ end
282
+ Log 2, "BScan.evt_register_callbacks Sending to spider: #{u}"
283
+ send_to_spider(u)
139
284
  end
140
- Log 2, "BScan.evt_register_callbacks Sending to spider: #{u}"
141
- send_to_spider(u)
142
285
  end
143
- end
286
+ end
144
287
  rescue Exception => e
145
288
  Log 0, "BScan.evt_register_callbacks Exception: #{e.message}"
146
289
  Log 0, e.backtrace.join("\n")