ronin-vulns 0.1.1 → 0.1.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +14 -0
- data/.rubocop.yml +28 -0
- data/ChangeLog.md +11 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -2
- data/bin/ronin-vulns +6 -7
- data/gemspec.yml +1 -1
- data/lib/ronin/vulns/cli/commands/open_redirect.rb +1 -0
- data/lib/ronin/vulns/cli/commands/rfi.rb +1 -1
- data/lib/ronin/vulns/cli/commands/scan.rb +6 -6
- data/lib/ronin/vulns/cli/commands/ssti.rb +2 -1
- data/lib/ronin/vulns/cli/logging.rb +3 -0
- data/lib/ronin/vulns/cli/web_vuln_command.rb +48 -10
- data/lib/ronin/vulns/lfi.rb +5 -6
- data/lib/ronin/vulns/open_redirect.rb +13 -2
- data/lib/ronin/vulns/reflected_xss/context.rb +7 -8
- data/lib/ronin/vulns/reflected_xss/test_string.rb +1 -2
- data/lib/ronin/vulns/reflected_xss.rb +2 -3
- data/lib/ronin/vulns/rfi.rb +1 -1
- data/lib/ronin/vulns/sqli.rb +9 -9
- data/lib/ronin/vulns/ssti/test_expression.rb +1 -1
- data/lib/ronin/vulns/ssti.rb +3 -3
- data/lib/ronin/vulns/url_scanner.rb +3 -0
- data/lib/ronin/vulns/version.rb +1 -1
- data/lib/ronin/vulns/web_vuln/http_request.rb +2 -2
- data/lib/ronin/vulns/web_vuln.rb +1 -1
- data/ronin-vulns.gemspec +4 -2
- metadata +9 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c80dfbe1e5e0f67d7f6ae908b5514f937004354a809a4e408025ad47f96bf8e7
         | 
| 4 | 
            +
              data.tar.gz: 7af7ed3b5e0abed7e2f0bdf0fc4b774ed568412369f4db44971fd2520d663bd5
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b06b563a221760c4f58fb55394ccdf01b510ed240b78d51f12dfd7bf122513f42d512f17bf3d5eb0857f61eda1b3db981c2d4583d9bedbb186c108216eec709f
         | 
| 7 | 
            +
              data.tar.gz: 905e0de6182206b232358dab499af99f7849513bb09585e9242445505791dcc8a6c23a381be314f9078cf20848f388ca0c277b6d1647c845c7a56a9c6e10fcec
         | 
    
        data/.github/workflows/ruby.yml
    CHANGED
    
    | @@ -30,3 +30,17 @@ jobs: | |
| 30 30 | 
             
                    run: bundle install --jobs 4 --retry 3
         | 
| 31 31 | 
             
                  - name: Run tests
         | 
| 32 32 | 
             
                    run: bundle exec rake test
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              # rubocop linting
         | 
| 35 | 
            +
              rubocop:
         | 
| 36 | 
            +
                runs-on: ubuntu-latest
         | 
| 37 | 
            +
                steps:
         | 
| 38 | 
            +
                  - uses: actions/checkout@v2
         | 
| 39 | 
            +
                  - name: Set up Ruby
         | 
| 40 | 
            +
                    uses: ruby/setup-ruby@v1
         | 
| 41 | 
            +
                    with:
         | 
| 42 | 
            +
                      ruby-version: 3.0
         | 
| 43 | 
            +
                  - name: Install dependencies
         | 
| 44 | 
            +
                    run: bundle install --jobs 4 --retry 3
         | 
| 45 | 
            +
                  - name: Run rubocop
         | 
| 46 | 
            +
                    run: bundle exec rubocop --parallel
         | 
    
        data/.rubocop.yml
    ADDED
    
    | @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            AllCops:
         | 
| 2 | 
            +
              NewCops: enable
         | 
| 3 | 
            +
              SuggestExtensions: false
         | 
| 4 | 
            +
              TargetRubyVersion: 3.1
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            inherit_gem:
         | 
| 7 | 
            +
              rubocop-ronin: rubocop.yml
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # we need to make the branching logic extremely explicit here
         | 
| 10 | 
            +
            Lint/DuplicateBranch:
         | 
| 11 | 
            +
              Exclude:
         | 
| 12 | 
            +
                - 'lib/ronin/vulns/lfi.rb'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            # we need to use eval() in the specs to test the SSTI test expression
         | 
| 15 | 
            +
            Security/Eval:
         | 
| 16 | 
            +
              Exclude:
         | 
| 17 | 
            +
                - 'spec/ssti_spec.rb'
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            # we need to call URLScanner.scan with a block
         | 
| 20 | 
            +
            Lint/EmptyBlock:
         | 
| 21 | 
            +
              Exclude:
         | 
| 22 | 
            +
                - 'spec/reflected_xss_spec.rb'
         | 
| 23 | 
            +
                - 'spec/url_scanner_spec.rb'
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            # Ronin::Vulns::Vuln does not define an #initialize method
         | 
| 26 | 
            +
            Lint/MissingSuper:
         | 
| 27 | 
            +
              Exclude:
         | 
| 28 | 
            +
                - 'lib/ronin/vulns/web_vuln.rb'
         | 
    
        data/ChangeLog.md
    CHANGED
    
    | @@ -1,3 +1,14 @@ | |
| 1 | 
            +
            ### 0.1.2 / 2023-03-01
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Require `ronin-support` ~> 1.0, >= 1.0.1
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            #### CLI
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Validate that given URLs start with either `http://` or `https://`, and print
         | 
| 8 | 
            +
              an error message otherwise.
         | 
| 9 | 
            +
            * Print a `No vulnerabilities found` message when no vulnerabilities were
         | 
| 10 | 
            +
              discovered.
         | 
| 11 | 
            +
             | 
| 1 12 | 
             
            ### 0.1.1 / 2023-02-02
         | 
| 2 13 |  | 
| 3 14 | 
             
            * Fixed typo in {Ronin::Vulns::CLI::WebVulnCommand#process_url} which effected
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            source 'https://rubygems.org'
         | 
| 2 4 |  | 
| 3 5 | 
             
            gemspec
         | 
| @@ -31,4 +33,6 @@ group :development do | |
| 31 33 | 
             
              gem 'dead_end',        require: false
         | 
| 32 34 | 
             
              gem 'sord',            require: false, platform: :mri
         | 
| 33 35 | 
             
              gem 'stackprof',       require: false, platform: :mri
         | 
| 36 | 
            +
              gem 'rubocop',         require: false, platform: :mri
         | 
| 37 | 
            +
              gem 'rubocop-ronin',   require: false, platform: :mri
         | 
| 34 38 | 
             
            end
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/bin/ronin-vulns
    CHANGED
    
    | @@ -1,17 +1,16 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # frozen_string_literal: true
         | 
| 2 3 |  | 
| 3 4 | 
             
            require 'rubygems'
         | 
| 4 5 |  | 
| 5 6 | 
             
            root = File.expand_path(File.join(File.dirname(__FILE__),'..'))
         | 
| 6 7 | 
             
            if File.file?(File.join(root,'Gemfile.lock'))
         | 
| 7 8 | 
             
              Dir.chdir(root) do
         | 
| 8 | 
            -
                 | 
| 9 | 
            -
             | 
| 10 | 
            -
                 | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                  exit -1
         | 
| 14 | 
            -
                end
         | 
| 9 | 
            +
                require 'bundler/setup'
         | 
| 10 | 
            +
              rescue LoadError => e
         | 
| 11 | 
            +
                warn e.message
         | 
| 12 | 
            +
                warn "Run `gem install bundler` to install Bundler"
         | 
| 13 | 
            +
                exit(-1)
         | 
| 15 14 | 
             
              end
         | 
| 16 15 | 
             
            end
         | 
| 17 16 |  | 
    
        data/gemspec.yml
    CHANGED
    
    
| @@ -98,7 +98,7 @@ module Ronin | |
| 98 98 | 
             
                                                     'double-encode' => :double_encode,
         | 
| 99 99 | 
             
                                                     'suffix-escape' => :suffix_escape,
         | 
| 100 100 | 
             
                                                     'null-byte'     => :null_byte
         | 
| 101 | 
            -
                                                   } | 
| 101 | 
            +
                                                   }
         | 
| 102 102 | 
             
                                                 },
         | 
| 103 103 | 
             
                                                 desc: 'Optional filter-bypass strategy to use'
         | 
| 104 104 |  | 
| @@ -127,7 +127,7 @@ module Ronin | |
| 127 127 | 
             
                      option :sqli_terminate, desc: 'Terminates the SQL expression with a --'
         | 
| 128 128 |  | 
| 129 129 | 
             
                      option :ssti_test_expr, value: {
         | 
| 130 | 
            -
                                                type:  | 
| 130 | 
            +
                                                type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
         | 
| 131 131 | 
             
                                                usage: '{X*Y | X/Z | X+Y | X-Y}'
         | 
| 132 132 | 
             
                                              },
         | 
| 133 133 | 
             
                                              desc: 'Optional numeric test to use' do |expr|
         | 
| @@ -260,10 +260,10 @@ module Ronin | |
| 260 260 | 
             
                      def scan_kwargs
         | 
| 261 261 | 
             
                        kwargs = super()
         | 
| 262 262 |  | 
| 263 | 
            -
                        kwargs[:lfi] | 
| 264 | 
            -
                        kwargs[:rfi] | 
| 265 | 
            -
                        kwargs[:sqli] | 
| 266 | 
            -
                        kwargs[:ssti] | 
| 263 | 
            +
                        kwargs[:lfi]           = lfi_kwargs
         | 
| 264 | 
            +
                        kwargs[:rfi]           = rfi_kwargs
         | 
| 265 | 
            +
                        kwargs[:sqli]          = sqli_kwargs
         | 
| 266 | 
            +
                        kwargs[:ssti]          = ssti_kwargs
         | 
| 267 267 | 
             
                        kwargs[:open_redirect] = open_redirect_kwargs
         | 
| 268 268 | 
             
                        kwargs[:reflected_xss] = reflected_xss_kwargs
         | 
| 269 269 |  | 
| @@ -63,7 +63,7 @@ module Ronin | |
| 63 63 |  | 
| 64 64 | 
             
                      option :test_expr, short: '-T',
         | 
| 65 65 | 
             
                                         value: {
         | 
| 66 | 
            -
                                           type:  | 
| 66 | 
            +
                                           type: %r{\A\d+\s*[\*/\+\-]\s*\d+\z},
         | 
| 67 67 | 
             
                                           usage: '{X*Y | X/Z | X+Y | X-Y}'
         | 
| 68 68 | 
             
                                         },
         | 
| 69 69 | 
             
                                         desc: 'Optional numeric test to use' do |expr|
         | 
| @@ -86,6 +86,7 @@ module Ronin | |
| 86 86 | 
             
                      #
         | 
| 87 87 | 
             
                      def scan_kwargs
         | 
| 88 88 | 
             
                        kwargs = super()
         | 
| 89 | 
            +
             | 
| 89 90 | 
             
                        kwargs[:test_expr] = @test_expr if @test_expr
         | 
| 90 91 | 
             
                        return kwargs
         | 
| 91 92 | 
             
                      end
         | 
| @@ -53,7 +53,9 @@ module Ronin | |
| 53 53 | 
             
                                    desc: 'Sets an additional header' do |header|
         | 
| 54 54 | 
             
                                      name, value = header.split(/:\s*/,2)
         | 
| 55 55 |  | 
| 56 | 
            +
                                      # lazy initialize the headers
         | 
| 56 57 | 
             
                                      @headers ||= {}
         | 
| 58 | 
            +
             | 
| 57 59 | 
             
                                      @headers[name] = value
         | 
| 58 60 | 
             
                                    end
         | 
| 59 61 |  | 
| @@ -74,14 +76,16 @@ module Ronin | |
| 74 76 | 
             
                                          desc: 'Sets an additional cookie param' do |param|
         | 
| 75 77 | 
             
                                            name, value = param.split('=',2)
         | 
| 76 78 |  | 
| 79 | 
            +
                                            # lazy initialize the cookie
         | 
| 77 80 | 
             
                                            @cookie ||= Support::Network::HTTP::Cookie.new
         | 
| 81 | 
            +
             | 
| 78 82 | 
             
                                            @cookie[name] = value
         | 
| 79 83 | 
             
                                          end
         | 
| 80 84 |  | 
| 81 85 | 
             
                    option :referer, short: '-R',
         | 
| 82 86 | 
             
                                     value: {
         | 
| 83 87 | 
             
                                       type: String,
         | 
| 84 | 
            -
                                       usage: 'URL' | 
| 88 | 
            +
                                       usage: 'URL'
         | 
| 85 89 | 
             
                                     },
         | 
| 86 90 | 
             
                                     desc: 'Sets the Referer header' do |referer|
         | 
| 87 91 | 
             
                                       @referer = referer
         | 
| @@ -95,7 +99,9 @@ module Ronin | |
| 95 99 | 
             
                                        desc: 'Sets an additional form param' do |param|
         | 
| 96 100 | 
             
                                          name, value = param.split('=',2)
         | 
| 97 101 |  | 
| 102 | 
            +
                                          # lazy initialize the form data
         | 
| 98 103 | 
             
                                          @form_data ||= {}
         | 
| 104 | 
            +
             | 
| 99 105 | 
             
                                          @form_data[name] = value
         | 
| 100 106 | 
             
                                        end
         | 
| 101 107 |  | 
| @@ -104,7 +110,9 @@ module Ronin | |
| 104 110 | 
             
                                                usage: 'NAME'
         | 
| 105 111 | 
             
                                              },
         | 
| 106 112 | 
             
                                              desc: 'Tests the URL query param name' do |name|
         | 
| 113 | 
            +
                                                # lazy initialize the test query params
         | 
| 107 114 | 
             
                                                @test_query_params ||= Set.new
         | 
| 115 | 
            +
             | 
| 108 116 | 
             
                                                @test_query_params << name
         | 
| 109 117 | 
             
                                              end
         | 
| 110 118 |  | 
| @@ -117,7 +125,9 @@ module Ronin | |
| 117 125 | 
             
                                                usage: 'NAME'
         | 
| 118 126 | 
             
                                              },
         | 
| 119 127 | 
             
                                              desc: 'Tests the HTTP Header name' do |name|
         | 
| 128 | 
            +
                                                # lazy initialize the test heade rnames
         | 
| 120 129 | 
             
                                                @test_header_names ||= Set.new
         | 
| 130 | 
            +
             | 
| 121 131 | 
             
                                                @test_header_names << name
         | 
| 122 132 | 
             
                                              end
         | 
| 123 133 |  | 
| @@ -126,7 +136,9 @@ module Ronin | |
| 126 136 | 
             
                                                 usage: 'NAME'
         | 
| 127 137 | 
             
                                               },
         | 
| 128 138 | 
             
                                               desc: 'Tests the HTTP Cookie name' do |name|
         | 
| 139 | 
            +
                                                 # lazy initialize the test cookie params
         | 
| 129 140 | 
             
                                                 @test_cookie_params ||= Set.new
         | 
| 141 | 
            +
             | 
| 130 142 | 
             
                                                 @test_cookie_params << name
         | 
| 131 143 | 
             
                                               end
         | 
| 132 144 |  | 
| @@ -135,11 +147,13 @@ module Ronin | |
| 135 147 | 
             
                    end
         | 
| 136 148 |  | 
| 137 149 | 
             
                    option :test_form_param, value: {
         | 
| 138 | 
            -
             | 
| 150 | 
            +
                                               type: String,
         | 
| 139 151 | 
             
                                                 usage: 'NAME'
         | 
| 140 | 
            -
             | 
| 152 | 
            +
                                             },
         | 
| 141 153 | 
             
                                               desc: 'Tests the form param name' do |name|
         | 
| 154 | 
            +
                                                 # lazy initialize the test form params
         | 
| 142 155 | 
             
                                                 @test_form_params ||= Set.new
         | 
| 156 | 
            +
             | 
| 143 157 | 
             
                                                 @test_form_params << name
         | 
| 144 158 | 
             
                                               end
         | 
| 145 159 |  | 
| @@ -235,19 +249,27 @@ module Ronin | |
| 235 249 | 
             
                    #   The URL(s) to scan.
         | 
| 236 250 | 
             
                    #
         | 
| 237 251 | 
             
                    def run(*urls)
         | 
| 252 | 
            +
                      unless (options[:input] || !urls.empty?)
         | 
| 253 | 
            +
                        print_error "must specify URL(s) or --input"
         | 
| 254 | 
            +
                        exit(-1)
         | 
| 255 | 
            +
                      end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                      vulns_discovered = false
         | 
| 258 | 
            +
             | 
| 238 259 | 
             
                      if options[:input]
         | 
| 239 260 | 
             
                        File.open(options[:input]) do |file|
         | 
| 240 261 | 
             
                          file.each_line(chomp: true) do |url|
         | 
| 241 | 
            -
                            process_url(url)
         | 
| 262 | 
            +
                            vulns_discovered ||= process_url(url)
         | 
| 242 263 | 
             
                          end
         | 
| 243 264 | 
             
                        end
         | 
| 244 265 | 
             
                      elsif !urls.empty?
         | 
| 245 266 | 
             
                        urls.each do |url|
         | 
| 246 | 
            -
                          process_url(url)
         | 
| 267 | 
            +
                          vulns_discovered ||= process_url(url)
         | 
| 247 268 | 
             
                        end
         | 
| 248 | 
            -
                       | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 269 | 
            +
                      end
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                      unless vulns_discovered
         | 
| 272 | 
            +
                        puts colors.green("No vulnerabilities found")
         | 
| 251 273 | 
             
                      end
         | 
| 252 274 | 
             
                    end
         | 
| 253 275 |  | 
| @@ -257,16 +279,32 @@ module Ronin | |
| 257 279 | 
             
                    # @param [String] url
         | 
| 258 280 | 
             
                    #   A URL to scan.
         | 
| 259 281 | 
             
                    #
         | 
| 282 | 
            +
                    # @return [Boolean]
         | 
| 283 | 
            +
                    #   Indicates whether a vulnerability was discovered in the URL.
         | 
| 284 | 
            +
                    #
         | 
| 260 285 | 
             
                    def process_url(url)
         | 
| 286 | 
            +
                      unless url.start_with?('http://') || url.start_with?('https://')
         | 
| 287 | 
            +
                        print_error("URL must start with http:// or https://: #{url.inspect}")
         | 
| 288 | 
            +
                        exit(-1)
         | 
| 289 | 
            +
                      end
         | 
| 290 | 
            +
             | 
| 291 | 
            +
                      vuln_discovered = false
         | 
| 292 | 
            +
             | 
| 261 293 | 
             
                      if @scan_mode == :first
         | 
| 262 294 | 
             
                        if (first_vuln = test_url(url))
         | 
| 263 295 | 
             
                          log_vuln(first_vuln)
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                          vuln_discovered = true
         | 
| 264 298 | 
             
                        end
         | 
| 265 299 | 
             
                      else
         | 
| 266 300 | 
             
                        scan_url(url) do |vuln|
         | 
| 267 301 | 
             
                          log_vuln(vuln)
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                          vuln_discovered = true
         | 
| 268 304 | 
             
                        end
         | 
| 269 305 | 
             
                      end
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                      return vuln_discovered
         | 
| 270 308 | 
             
                    end
         | 
| 271 309 |  | 
| 272 310 | 
             
                    #
         | 
| @@ -295,7 +333,7 @@ module Ronin | |
| 295 333 | 
             
                        kwargs[:query_params]  = true
         | 
| 296 334 | 
             
                      end
         | 
| 297 335 |  | 
| 298 | 
            -
                      kwargs[:header_names] | 
| 336 | 
            +
                      kwargs[:header_names] = @test_header_names if @test_header_names
         | 
| 299 337 |  | 
| 300 338 | 
             
                      if @test_cookie_params
         | 
| 301 339 | 
             
                        kwargs[:cookie_params] = @test_cookie_params
         | 
| @@ -303,7 +341,7 @@ module Ronin | |
| 303 341 | 
             
                        kwargs[:cookie_params] = true
         | 
| 304 342 | 
             
                      end
         | 
| 305 343 |  | 
| 306 | 
            -
                      kwargs[:form_params] | 
| 344 | 
            +
                      kwargs[:form_params] = @test_form_params if @test_form_params
         | 
| 307 345 |  | 
| 308 346 | 
             
                      return kwargs
         | 
| 309 347 | 
             
                    end
         | 
    
        data/lib/ronin/vulns/lfi.rb
    CHANGED
    
    | @@ -57,7 +57,7 @@ module Ronin | |
| 57 57 | 
             
                  attr_reader :os
         | 
| 58 58 |  | 
| 59 59 | 
             
                  # Optional filter bypass technique to use.
         | 
| 60 | 
            -
                  # | 
| 60 | 
            +
                  #
         | 
| 61 61 | 
             
                  # @return [:null_byte, :base64, :rot13, :zlib, nil]
         | 
| 62 62 | 
             
                  attr_reader :filter_bypass
         | 
| 63 63 |  | 
| @@ -176,7 +176,7 @@ module Ronin | |
| 176 176 | 
             
                      "#{@escape_path}#{path[3..]}"
         | 
| 177 177 | 
             
                    elsif @os == :windows && path =~ /\A[A-Z]:/
         | 
| 178 178 | 
             
                      # pass through absolute Windows paths to other drives
         | 
| 179 | 
            -
             | 
| 179 | 
            +
                      path
         | 
| 180 180 | 
             
                    elsif path.start_with?(@separator)
         | 
| 181 181 | 
             
                      # escape absolute paths
         | 
| 182 182 | 
             
                      "#{@escape_path}#{path[1..]}"
         | 
| @@ -234,10 +234,9 @@ module Ronin | |
| 234 234 | 
             
                      Crypto.rot(body,-13) =~ @test_file
         | 
| 235 235 | 
             
                    when :zlib
         | 
| 236 236 | 
             
                      body.scan(Text::Patterns::BASE64).any? do |string|
         | 
| 237 | 
            -
                         | 
| 238 | 
            -
             | 
| 239 | 
            -
                         | 
| 240 | 
            -
                        end
         | 
| 237 | 
            +
                        Compression.zlib_inflate(Base64.decode64(string)) =~ @test_file
         | 
| 238 | 
            +
                      rescue Zlib::DataError
         | 
| 239 | 
            +
                        # not zlib compressed Base64, ignore
         | 
| 241 240 | 
             
                      end
         | 
| 242 241 | 
             
                    else
         | 
| 243 242 | 
             
                      body =~ @test_file
         | 
| @@ -80,7 +80,7 @@ module Ronin | |
| 80 80 | 
             
                    when '301', '302', '303', '307', '308'
         | 
| 81 81 | 
             
                      if (locations = response.get_fields('Location'))
         | 
| 82 82 | 
             
                        escaped_test_url = Regexp.escape(@test_url)
         | 
| 83 | 
            -
                        regexp | 
| 83 | 
            +
                        regexp           = /\A#{escaped_test_url}(?:[\?&].+)?\z/
         | 
| 84 84 |  | 
| 85 85 | 
             
                        locations.last =~ regexp
         | 
| 86 86 | 
             
                      end
         | 
| @@ -89,7 +89,18 @@ module Ronin | |
| 89 89 |  | 
| 90 90 | 
             
                      if content_type && content_type.include?('text/html')
         | 
| 91 91 | 
             
                        escaped_test_url = Regexp.escape(CGI.escapeHTML(@test_url))
         | 
| 92 | 
            -
             | 
| 92 | 
            +
             | 
| 93 | 
            +
                        regexp = %r{
         | 
| 94 | 
            +
                          <meta\s+
         | 
| 95 | 
            +
                            http-equiv\s*=\s*(?: "refresh" | 'refresh' | refresh )\s+
         | 
| 96 | 
            +
                            content\s*=\s*
         | 
| 97 | 
            +
                            (?:
         | 
| 98 | 
            +
                             "\s*\d+\s*;\s*url\s*=\s*'\s*#{escaped_test_url}\s*'\s*"|
         | 
| 99 | 
            +
                             '\s*\d+\s*;\s*url\s*=\s*"\s*#{escaped_test_url}\s*"\s*'|
         | 
| 100 | 
            +
                             \s*\d+;url=(?: "#{escaped_test_url}" | '#{escaped_test_url}' )
         | 
| 101 | 
            +
                            )\s*
         | 
| 102 | 
            +
                            (?:/\s*)?>
         | 
| 103 | 
            +
                        }xi
         | 
| 93 104 |  | 
| 94 105 | 
             
                        response.body =~ regexp
         | 
| 95 106 | 
             
                      end
         | 
| @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 2 | 
             
            #
         | 
| 4 3 | 
             
            # ronin-vulns - A Ruby library for blind vulnerability testing.
         | 
| 5 4 | 
             
            #
         | 
| @@ -115,33 +114,33 @@ module Ronin | |
| 115 114 | 
             
                    # value.
         | 
| 116 115 | 
             
                    #
         | 
| 117 116 | 
             
                    # @api private
         | 
| 118 | 
            -
                    IN_DOUBLE_QUOTED_ATTR_VALUE =  | 
| 117 | 
            +
                    IN_DOUBLE_QUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\s*=\s*"[^"]+\z/
         | 
| 119 118 |  | 
| 120 119 | 
             
                    # Regexp matching when an XSS occurs within a single-quoted attribute
         | 
| 121 120 | 
             
                    # value.
         | 
| 122 121 | 
             
                    #
         | 
| 123 122 | 
             
                    # @api private
         | 
| 124 | 
            -
                    IN_SINGLE_QUOTED_ATTR_VALUE =  | 
| 123 | 
            +
                    IN_SINGLE_QUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\s*=\s*'[^']+\z/
         | 
| 125 124 |  | 
| 126 125 | 
             
                    # Regexp matching when an XSS occurs within an unquoted attribute value.
         | 
| 127 126 | 
             
                    #
         | 
| 128 127 | 
             
                    # @api private
         | 
| 129 | 
            -
                    IN_UNQUOTED_ATTR_VALUE =  | 
| 128 | 
            +
                    IN_UNQUOTED_ATTR_VALUE = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})=[^"'\s]+\z/
         | 
| 130 129 |  | 
| 131 130 | 
             
                    # Regexp matching when an XSS occurs within an attribute's name.
         | 
| 132 131 | 
             
                    #
         | 
| 133 132 | 
             
                    # @api private
         | 
| 134 | 
            -
                    IN_ATTR_NAME =  | 
| 133 | 
            +
                    IN_ATTR_NAME = /<(#{TAG_NAME})#{ATTR_LIST}\s+(#{ATTR_NAME})\z/
         | 
| 135 134 |  | 
| 136 135 | 
             
                    # Regexp matching when an XSS occurs within a tag's attribute list.
         | 
| 137 136 | 
             
                    #
         | 
| 138 137 | 
             
                    # @api private
         | 
| 139 | 
            -
                    IN_ATTR_LIST =  | 
| 138 | 
            +
                    IN_ATTR_LIST = /<(#{TAG_NAME})#{ATTR_LIST}\s+\z/
         | 
| 140 139 |  | 
| 141 140 | 
             
                    # Regexp matching when an XSS occurs within a tag's name.
         | 
| 142 141 | 
             
                    #
         | 
| 143 142 | 
             
                    # @api private
         | 
| 144 | 
            -
                    IN_TAG_NAME =  | 
| 143 | 
            +
                    IN_TAG_NAME = /<(#{TAG_NAME})\z/
         | 
| 145 144 |  | 
| 146 145 | 
             
                    #
         | 
| 147 146 | 
             
                    # Determine the context of the XSS by checking the characters that come
         | 
| @@ -161,7 +160,7 @@ module Ronin | |
| 161 160 | 
             
                    def self.identify(body,index)
         | 
| 162 161 | 
             
                      prefix = body[0,index]
         | 
| 163 162 |  | 
| 164 | 
            -
                      if | 
| 163 | 
            +
                      if    (match = prefix.match(IN_TAG_BODY))
         | 
| 165 164 | 
             
                        new(:tag_body, tag: match[1])
         | 
| 166 165 | 
             
                      elsif (match = prefix.match(IN_DOUBLE_QUOTED_ATTR_VALUE))
         | 
| 167 166 | 
             
                        new(:double_quoted_attr_value, tag: match[1], attr: match[2])
         | 
| @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 2 | 
             
            #
         | 
| 4 3 | 
             
            # ronin-vulns - A Ruby library for blind vulnerability testing.
         | 
| 5 4 | 
             
            #
         | 
| @@ -67,7 +66,7 @@ module Ronin | |
| 67 66 | 
             
                      '/' => ['%2F'],
         | 
| 68 67 | 
             
                      '<' => ['%3C', '<'],
         | 
| 69 68 | 
             
                      '>' => ['%3E', '>'],
         | 
| 70 | 
            -
                      '&' => ['%26', '&'] | 
| 69 | 
            +
                      '&' => ['%26', '&']
         | 
| 71 70 | 
             
                    }
         | 
| 72 71 |  | 
| 73 72 | 
             
                    #
         | 
| @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 2 | 
             
            #
         | 
| 4 3 | 
             
            # ronin-vulns - A Ruby library for blind vulnerability testing.
         | 
| 5 4 | 
             
            #
         | 
| @@ -91,7 +90,7 @@ module Ronin | |
| 91 90 | 
             
                  #   The test string to send.
         | 
| 92 91 | 
             
                  #
         | 
| 93 92 | 
             
                  # @yield [body, match]
         | 
| 94 | 
            -
                  #   If a block is given, it will be passed the response body and the | 
| 93 | 
            +
                  #   If a block is given, it will be passed the response body and the
         | 
| 95 94 | 
             
                  #   regular expression match data, if the response contains the test
         | 
| 96 95 | 
             
                  #   string.
         | 
| 97 96 | 
             
                  #
         | 
| @@ -119,7 +118,7 @@ module Ronin | |
| 119 118 | 
             
                  # Tests which HTML characters are accepted or escaped/filtered.
         | 
| 120 119 | 
             
                  #
         | 
| 121 120 | 
             
                  # @yield [body, match]
         | 
| 122 | 
            -
                  #   If a block is given, it will be passed the response body and the | 
| 121 | 
            +
                  #   If a block is given, it will be passed the response body and the
         | 
| 123 122 | 
             
                  #   regular expression match data, if the response contains the test
         | 
| 124 123 | 
             
                  #   string.
         | 
| 125 124 | 
             
                  #
         | 
    
        data/lib/ronin/vulns/rfi.rb
    CHANGED
    
    
    
        data/lib/ronin/vulns/sqli.rb
    CHANGED
    
    | @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 2 | 
             
            #
         | 
| 4 3 | 
             
            # ronin-vulns - A Ruby library for blind vulnerability testing.
         | 
| 5 4 | 
             
            #
         | 
| @@ -42,7 +41,7 @@ module Ronin | |
| 42 41 | 
             
                  attr_reader :escape_quote
         | 
| 43 42 |  | 
| 44 43 | 
             
                  # Specifies whether to escape parenthesis.
         | 
| 45 | 
            -
                  # | 
| 44 | 
            +
                  #
         | 
| 46 45 | 
             
                  # @return [Boolean]
         | 
| 47 46 | 
             
                  attr_reader :escape_parens
         | 
| 48 47 |  | 
| @@ -205,7 +204,7 @@ module Ronin | |
| 205 204 | 
             
                      /ERROR: parser: parse error at or near/,
         | 
| 206 205 | 
             
                      /PostgreSQL query failed/,
         | 
| 207 206 | 
             
                      /org\.postgresql\.jdbc/,
         | 
| 208 | 
            -
                       | 
| 207 | 
            +
                      %r{Pdo[\./_\\]Pgsql},
         | 
| 209 208 | 
             
                      /PSQLException/
         | 
| 210 209 | 
             
                    ],
         | 
| 211 210 |  | 
| @@ -219,12 +218,12 @@ module Ronin | |
| 219 218 | 
             
                      /MySqlClient\./,
         | 
| 220 219 | 
             
                      /com\.mysql\.jdbc/,
         | 
| 221 220 | 
             
                      /Zend_Db_(?:Adapter|Statement)_Mysqli_Exception/,
         | 
| 222 | 
            -
                       | 
| 221 | 
            +
                      %r{Pdo[\./_\\]Mysql},
         | 
| 223 222 | 
             
                      /MySqlException/
         | 
| 224 223 | 
             
                    ],
         | 
| 225 224 |  | 
| 226 225 | 
             
                    sqlite: ErrorPattern[
         | 
| 227 | 
            -
                      / | 
| 226 | 
            +
                      %r{SQLite/JDBCDriver},
         | 
| 228 227 | 
             
                      /SQLite\.Exception/,
         | 
| 229 228 | 
             
                      /(Microsoft|System)\.Data\.SQLite\.SQLiteException/,
         | 
| 230 229 | 
             
                      /Warning.*\W(?:sqlite_|SQLite3::)/,
         | 
| @@ -233,7 +232,7 @@ module Ronin | |
| 233 232 | 
             
                      /sqlite3\.OperationalError:/,
         | 
| 234 233 | 
             
                      /SQLite3::SQLException/,
         | 
| 235 234 | 
             
                      /org\.sqlite\.JDBC/,
         | 
| 236 | 
            -
                       | 
| 235 | 
            +
                      %r{Pdo[\./_\\]Sqlite},
         | 
| 237 236 | 
             
                      /SQLiteException/
         | 
| 238 237 | 
             
                    ],
         | 
| 239 238 |  | 
| @@ -254,7 +253,7 @@ module Ronin | |
| 254 253 | 
             
                      /macromedia\.jdbc\.sqlserver/,
         | 
| 255 254 | 
             
                      /Zend_Db_(?:Adapter|Statement)_Sqlsrv_Exception/,
         | 
| 256 255 | 
             
                      /com\.microsoft\.sqlserver\.jdbc/,
         | 
| 257 | 
            -
                       | 
| 256 | 
            +
                      %r{Pdo[\./_\\](?:Mssql|SqlSrv)},
         | 
| 258 257 | 
             
                      /SQL(?:Srv|Server)Exception/
         | 
| 259 258 | 
             
                    ],
         | 
| 260 259 |  | 
| @@ -268,7 +267,7 @@ module Ronin | |
| 268 267 | 
             
                      /macromedia\.jdbc\.oracle/,
         | 
| 269 268 | 
             
                      /oracle\.jdbc/,
         | 
| 270 269 | 
             
                      /Zend_Db_(?:Adapter|Statement)_Oracle_Exception/,
         | 
| 271 | 
            -
                       | 
| 270 | 
            +
                      %r{Pdo[\./_\\](?:Oracle|OCI)},
         | 
| 272 271 | 
             
                      /OracleException/
         | 
| 273 272 | 
             
                    ]
         | 
| 274 273 | 
             
                  }
         | 
| @@ -304,7 +303,7 @@ module Ronin | |
| 304 303 | 
             
                  # @api private
         | 
| 305 304 | 
             
                  #
         | 
| 306 305 | 
             
                  def random_id
         | 
| 307 | 
            -
                    rand(8_999) | 
| 306 | 
            +
                    rand(8_999..9999)
         | 
| 308 307 | 
             
                  end
         | 
| 309 308 |  | 
| 310 309 | 
             
                  #
         | 
| @@ -317,6 +316,7 @@ module Ronin | |
| 317 316 | 
             
                  #
         | 
| 318 317 | 
             
                  def test_or_true_and_false
         | 
| 319 318 | 
             
                    id = random_id
         | 
| 319 | 
            +
             | 
| 320 320 | 
             
                    response1 = exploit("OR #{id}=#{id}")
         | 
| 321 321 | 
             
                    response2 = exploit("AND #{random_id}=#{random_id}")
         | 
| 322 322 |  | 
| @@ -68,7 +68,7 @@ module Ronin | |
| 68 68 | 
             
                    #   Could not parse the test expression.
         | 
| 69 69 | 
             
                    #
         | 
| 70 70 | 
             
                    def self.parse(string)
         | 
| 71 | 
            -
                      unless (match = string.match( | 
| 71 | 
            +
                      unless (match = string.match(%r{\A(\d+)\s*([\*/\+\-])\s*(\d+)\z}))
         | 
| 72 72 | 
             
                        raise(ArgumentError,"could not parse the expression: #{string.inspect}")
         | 
| 73 73 | 
             
                      end
         | 
| 74 74 |  | 
    
        data/lib/ronin/vulns/ssti.rb
    CHANGED
    
    | @@ -87,8 +87,8 @@ module Ronin | |
| 87 87 | 
             
                  #   A random test expression.
         | 
| 88 88 | 
             
                  #
         | 
| 89 89 | 
             
                  def self.random_test
         | 
| 90 | 
            -
                    int1 = rand( | 
| 91 | 
            -
                    int2 = rand( | 
| 90 | 
            +
                    int1 = rand(1_000..1_999)
         | 
| 91 | 
            +
                    int2 = rand(1_000..1_999)
         | 
| 92 92 |  | 
| 93 93 | 
             
                    string  = "#{int1}*#{int2}"
         | 
| 94 94 | 
             
                    result  = (int1 * int2).to_s
         | 
| @@ -108,7 +108,7 @@ module Ronin | |
| 108 108 | 
             
                  # @option kwargs [Proc, nil] :escape
         | 
| 109 109 | 
             
                  #   The escape method to use. If `escape:` is not given, then all escapes
         | 
| 110 110 | 
             
                  #   in {ESCAPES} will be tested..
         | 
| 111 | 
            -
                  # | 
| 111 | 
            +
                  #
         | 
| 112 112 | 
             
                  # @option kwargs [Array<Symbol, String>, Symbol, String, true, nil] :query_params
         | 
| 113 113 | 
             
                  #   The query param name(s) to test.
         | 
| 114 114 | 
             
                  #
         | 
    
        data/lib/ronin/vulns/version.rb
    CHANGED
    
    
| @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 | 
            -
            # frozen_string_literal: true
         | 
| 3 2 | 
             
            #
         | 
| 4 3 | 
             
            # ronin-vulns - A Ruby library for blind vulnerability testing.
         | 
| 5 4 | 
             
            #
         | 
| @@ -119,9 +118,10 @@ module Ronin | |
| 119 118 | 
             
                                        cookie:         nil,
         | 
| 120 119 | 
             
                                        form_data:      nil)
         | 
| 121 120 | 
             
                      @url = url
         | 
| 122 | 
            -
             | 
| 121 | 
            +
             | 
| 123 122 | 
             
                      if query_params && !query_params.empty?
         | 
| 124 123 | 
             
                        @url = url.dup
         | 
| 124 | 
            +
             | 
| 125 125 | 
             
                        @url.query_params = query_params
         | 
| 126 126 | 
             
                      end
         | 
| 127 127 |  | 
    
        data/lib/ronin/vulns/web_vuln.rb
    CHANGED
    
    
    
        data/ronin-vulns.gemspec
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require 'yaml'
         | 
| 2 4 |  | 
| 3 5 | 
             
            Gem::Specification.new do |gem|
         | 
| @@ -20,7 +22,7 @@ Gem::Specification.new do |gem| | |
| 20 22 | 
             
              gem.homepage    = gemspec['homepage']
         | 
| 21 23 | 
             
              gem.metadata    = gemspec['metadata'] if gemspec['metadata']
         | 
| 22 24 |  | 
| 23 | 
            -
              glob =  | 
| 25 | 
            +
              glob = ->(patterns) { gem.files & Dir[*patterns] }
         | 
| 24 26 |  | 
| 25 27 | 
             
              gem.files  = `git ls-files`.split($/)
         | 
| 26 28 | 
             
              gem.files  = glob[gemspec['files']] if gemspec['files']
         | 
| @@ -44,7 +46,7 @@ Gem::Specification.new do |gem| | |
| 44 46 | 
             
              gem.required_rubygems_version = gemspec['required_rubygems_version']
         | 
| 45 47 | 
             
              gem.post_install_message      = gemspec['post_install_message']
         | 
| 46 48 |  | 
| 47 | 
            -
              split =  | 
| 49 | 
            +
              split = ->(string) { string.split(/,\s*/) }
         | 
| 48 50 |  | 
| 49 51 | 
             
              if gemspec['dependencies']
         | 
| 50 52 | 
             
                gemspec['dependencies'].each do |name,versions|
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ronin-vulns
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Postmodern
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023- | 
| 11 | 
            +
            date: 2023-03-02 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: ronin-support
         | 
| @@ -17,6 +17,9 @@ dependencies: | |
| 17 17 | 
             
                - - "~>"
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 19 | 
             
                    version: '1.0'
         | 
| 20 | 
            +
                - - ">="
         | 
| 21 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            +
                    version: 1.0.1
         | 
| 20 23 | 
             
              type: :runtime
         | 
| 21 24 | 
             
              prerelease: false
         | 
| 22 25 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -24,6 +27,9 @@ dependencies: | |
| 24 27 | 
             
                - - "~>"
         | 
| 25 28 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 29 | 
             
                    version: '1.0'
         | 
| 30 | 
            +
                - - ">="
         | 
| 31 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            +
                    version: 1.0.1
         | 
| 27 33 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 34 | 
             
              name: ronin-core
         | 
| 29 35 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -70,6 +76,7 @@ files: | |
| 70 76 | 
             
            - ".github/workflows/ruby.yml"
         | 
| 71 77 | 
             
            - ".gitignore"
         | 
| 72 78 | 
             
            - ".rspec"
         | 
| 79 | 
            +
            - ".rubocop.yml"
         | 
| 73 80 | 
             
            - ".ruby-version"
         | 
| 74 81 | 
             
            - ".yardopts"
         | 
| 75 82 | 
             
            - COPYING.txt
         |