Codebase list ruby-cms-scanner / 42d78d3
Update upstream source from tag 'upstream/0.8.4' Update to upstream version '0.8.4' with Debian dir c6a215b7e4b78bc95137ba2d63f0fac51623ff2d Sophie Brun 4 years ago
33 changed file(s) with 187 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
0 name: Build
1
2 on: [push, pull_request]
3
4 jobs:
5 build:
6
7 runs-on: ubuntu-latest
8
9 strategy:
10 matrix:
11 ruby: [2.4, 2.5, 2.6, 2.7]
12
13 steps:
14 - name: Checkout code
15 uses: actions/checkout@v1
16
17 - name: Set up Ruby ${{ matrix.ruby }}
18 uses: actions/setup-ruby@v1
19 with:
20 ruby-version: ${{ matrix.ruby }}
21
22 - name: Restore GEM cache
23 uses: actions/cache@v1
24 with:
25 path: vendor/bundle
26 key: ${{ runner.os }}-${{ matrix.ruby }}-gem-${{ hashFiles('**/cms_scanner.gemspec') }}
27 restore-keys: |
28 ${{ runner.os }}-${{ matrix.ruby }}-gem-
29
30 - name: Install GEMs
31 run: |
32 gem install bundler
33 bundle config force_ruby_platform true
34 bundle config path vendor/bundle
35 bundle install --jobs 4 --retry 3
36
37 - name: rubocop
38 run: |
39 bundle exec rubocop
40
41 - name: rspec
42 run: |
43 bundle exec rspec
44
45 - name: Coveralls
46 uses: coverallsapp/github-action@master
47 with:
48 github-token: ${{ secrets.GITHUB_TOKEN }}
0
1 if ENV['GITHUB_ACTION']
2 require 'simplecov-lcov'
3
4 SimpleCov::Formatter::LcovFormatter.config do |c|
5 c.single_report_path = 'coverage/lcov.info'
6 c.report_with_single_file = true
7 end
8
9 SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
10 end
11
012 SimpleCov.start do
13 enable_coverage :branch # Only supported for Ruby >= 2.5
14
115 add_filter '/example/'
216 add_filter '/spec/'
317 add_filter 'helper'
4 end
18 end
+0
-34
.travis.yml less more
0 language: ruby
1 sudo: false
2 cache: bundler
3 rvm:
4 - 2.4.1
5 - 2.4.2
6 - 2.4.3
7 - 2.4.4
8 - 2.4.5
9 - 2.4.6
10 - 2.4.7
11 - 2.4.8
12 - 2.4.9
13 - 2.5.0
14 - 2.5.1
15 - 2.5.2
16 - 2.5.3
17 - 2.5.4
18 - 2.5.5
19 - 2.5.6
20 - 2.5.7
21 - 2.6.0
22 - 2.6.1
23 - 2.6.2
24 - 2.6.3
25 - 2.6.4
26 - 2.6.5
27 - 2.7.0
28 script:
29 - bundle exec rubocop
30 - bundle exec rspec
31 notifications:
32 email:
33 - [email protected]
00 # CMSScanner
11
22 [![Gem Version](https://badge.fury.io/rb/cms_scanner.svg)](https://badge.fury.io/rb/cms_scanner)
3 [![Build Status](https://travis-ci.org/wpscanteam/CMSScanner.svg?branch=master)](https://travis-ci.org/wpscanteam/CMSScanner)
3 ![Build](https://github.com/wpscanteam/CMSScanner/workflows/Build/badge.svg)
44 [![Coverage Status](https://img.shields.io/coveralls/wpscanteam/CMSScanner.svg)](https://coveralls.io/r/wpscanteam/CMSScanner)
55 [![Code Climate](https://api.codeclimate.com/v1/badges/b90b7f9f6982792ef8d6/maintainability)](https://codeclimate.com/github/wpscanteam/CMSScanner/maintainability)
66
1313 require_relative 'models/interesting_finding'
1414 require_relative 'models/robots_txt'
1515 require_relative 'models/fantastico_fileslist'
16 require_relative 'models/search_replace_db_2'
1617 require_relative 'models/headers'
1718 require_relative 'models/xml_rpc'
1819 require_relative 'models/version'
6262 @start_time = Time.now
6363 @start_memory = NS.start_memory
6464
65 output('started', url: target.url, effective_url: target.homepage_url)
65 output('started', url: target.url, ip: target.ip, effective_url: target.homepage_url)
6666 end
6767
6868 def after_scan
1010
1111 return unless /by interconnect/i.match?(target.head_and_get(path).body)
1212
13 NS::Model::InterestingFinding.new(target.url(path),
14 confidence: 100,
15 found_by: found_by,
16 references: references)
17 end
18
19 def references
20 { url: 'https://interconnectit.com/products/search-and-replace-for-wordpress-databases/' }
13 NS::Model::SearchReplaceDB2.new(target.url(path), confidence: 100, found_by: found_by)
2114 end
2215 end
2316 end
3434
3535 potential_urls << url
3636
37 return NS::Model::XMLRPC.new(url, confidence: 30,
38 found_by: 'Link Tag (Passive Detection)')
37 return NS::Model::XMLRPC.new(url, confidence: 30, found_by: 'Link Tag (Passive Detection)')
3938 end
4039 nil
4140 end
5150
5251 next unless /<methodResponse>/i.match?(res&.body)
5352
54 return NS::Model::XMLRPC.new(potential_url,
55 confidence: 100,
56 found_by: DIRECT_ACCESS)
53 return NS::Model::XMLRPC.new(potential_url, confidence: 100, found_by: DIRECT_ACCESS)
5754 end
5855 nil
5956 end
1616 end
1717
1818 def references
19 { url: ['http://www.acunetix.com/vulnerabilities/fantastico-fileslist/'] }
19 @references ||= { url: ['http://www.acunetix.com/vulnerabilities/fantastico-fileslist/'] }
2020 end
2121 end
2222 end
3333 x-webkit-csp x-xss-protection
3434 ]
3535 end
36
37 # @return [ String ]
38 def to_s
39 @to_s ||= 'Headers'
40 end
3641 end
3742 end
3843 end
0 # frozen_string_literal: true
1
2 module CMSScanner
3 module Model
4 # SearchReplaceDB2
5 class SearchReplaceDB2 < InterestingFinding
6 def references
7 @references ||= { url: ['https://interconnectit.com/products/search-and-replace-for-wordpress-databases/'] }
8 end
9 end
10 end
11 end
33 module Model
44 # XML RPC
55 class XMLRPC < InterestingFinding
6 # @return [ String ]
7 def to_s
8 @to_s ||= "XML-RPC seems to be enabled: #{url}"
9 end
10
611 # @return [ Browser ]
712 def browser
813 @browser ||= NS::Browser.instance
0 <%= info_icon %> URL: <%= @url %>
0 <%= info_icon %> URL: <%= @url %> [<%= @ip %>]
11 <% if @url != @effective_url -%>
22 <%= info_icon %> Effective URL: <%= @effective_url %>
33 <% end -%>
00 "start_time": <%= @start_time.to_i %>,
11 "start_memory": <%= @start_memory.to_i %>,
22 "target_url": <%= @url.to_s.to_json %>,
3 "target_ip": <%= @ip.to_s.to_json %>,
34 "effective_url": <%= @effective_url.to_s.to_json %>,
1919 s.require_paths = ['lib']
2020
2121 s.add_dependency 'get_process_mem', '~> 0.2.5'
22 s.add_dependency 'nokogiri', '~> 1.10.4'
22 s.add_dependency 'nokogiri', '~> 1.10.8'
2323 s.add_dependency 'opt_parse_validator', '~> 1.8.1'
24 s.add_dependency 'public_suffix', '>= 3.0', '< 4.1'
24 s.add_dependency 'public_suffix', '~> 4.0.3'
2525 s.add_dependency 'ruby-progressbar', '~> 1.10.0'
2626 s.add_dependency 'typhoeus', '~> 1.3.0'
2727 s.add_dependency 'xmlrpc', '~> 0.3'
3030 s.add_dependency 'sys-proctable', '~> 1.2.2' # Required by get_process_mem for Windows OS.
3131
3232 s.add_development_dependency 'bundler', '>= 1.6'
33 s.add_development_dependency 'coveralls', '~> 0.8.0'
3433 s.add_development_dependency 'rake', '~> 13.0'
3534 s.add_development_dependency 'rspec', '~> 3.9.0'
3635 s.add_development_dependency 'rspec-its', '~> 1.3.0'
37 s.add_development_dependency 'rubocop', '~> 0.78.0'
36 s.add_development_dependency 'rubocop', '~> 0.80.0'
3837 s.add_development_dependency 'rubocop-performance', '~> 1.5.0'
39 s.add_development_dependency 'simplecov', '~> 0.16.1'
40 s.add_development_dependency 'webmock', '~> 3.7.0'
38 s.add_development_dependency 'simplecov', '~> 0.18.2'
39 s.add_development_dependency 'simplecov-lcov', '~> 0.8.0'
40 s.add_development_dependency 'webmock', '~> 3.8.0'
4141 end
3737 Typhoeus::Request.new(url, request_params(params))
3838 end
3939
40 # @return [ Hash ]
41 def typhoeus_to_browser_opts
42 { connecttimeout: :connect_timeout, cache_ttl: :cache_ttl,
43 proxy: :proxy, timeout: :request_timeout, cookiejar: :cookie_jar,
44 cookiefile: :cookie_jar, cookie: :cookie_string }
45 end
46
47 # @return [ Hash ]
48 def default_request_params
49 params = {
50 headers: { 'User-Agent' => user_agent, 'Referer' => url }.merge(headers || {}),
51 accept_encoding: 'gzip, deflate',
52 method: :get
53 }
40 # @return [ Hash ] The request params used to connect tothe target as well as potential other systems such as API
41 def default_connect_request_params
42 params = {}
5443
5544 if disable_tls_checks
5645 # See http://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html
6049 params[:sslversion] = :tlsv1
6150 end
6251
63 typhoeus_to_browser_opts.each do |typhoeus_opt, browser_opt|
52 {
53 connecttimeout: :connect_timeout, cache_ttl: :cache_ttl,
54 proxy: :proxy, timeout: :request_timeout
55 }.each do |typhoeus_opt, browser_opt|
56 attr_value = public_send(browser_opt)
57 params[typhoeus_opt] = attr_value unless attr_value.nil?
58 end
59
60 params
61 end
62
63 # @return [ Hash ]
64 # The params are not cached (using @params ||= for example), so that they are set accordingly if updated
65 # by a controller/other piece of code
66 def default_request_params
67 params = default_connect_request_params.merge(
68 headers: { 'User-Agent' => user_agent, 'Referer' => url }.merge(headers || {}),
69 accept_encoding: 'gzip, deflate',
70 method: :get
71 )
72
73 { cookiejar: :cookie_jar, cookiefile: :cookie_jar, cookie: :cookie_string }.each do |typhoeus_opt, browser_opt|
6474 attr_value = public_send(browser_opt)
6575 params[typhoeus_opt] = attr_value unless attr_value.nil?
6676 end
2424 # @yield [ Addressable::URI, Nokogiri::XML::Element ] The in scope url and its associated tag
2525 #
2626 # @return [ Array<Addressable::URI> ] The in scope absolute URIs detected in the response's body
27 #
28 # @note It is highly recommended to use the xpath parameter to focus on the uris needed, as this method can be quite
29 # time consuming when there are a lof of uris to check
2730 def in_scope_uris(res, xpath = '//@href|//@src|//@data-src')
2831 found = []
2932
9191 # @yield [ Addressable::URI, Nokogiri::XML::Element ] The url and its associated tag
9292 #
9393 # @return [ Array<Addressable::URI> ] The absolute URIs detected in the response's body from the HTML tags
94 #
95 # @note It is highly recommended to use the xpath parameter to focus on the uris needed, as this method can be quite
96 # time consuming when there are a lof of uris to check
9497 def uris_from_page(page = nil, xpath = '//@href|//@src|//@data-src')
9598 page = NS::Browser.get(url(page)) unless page.is_a?(Typhoeus::Response)
9699 found = []
11
22 # Version
33 module CMSScanner
4 VERSION = '0.8.1'
4 VERSION = '0.8.4'
55 end
2929 return @uri.to_s unless path
3030
3131 @uri.join(Addressable::URI.encode(path).gsub('#', '%23')).to_s
32 end
33
34 # @return [ String ] The IP address of the target
35 def ip
36 @ip ||= IPSocket.getaddress(uri.host)
37 rescue SocketError
38 'Unknown'
3239 end
3340
3441 attr_writer :homepage_res
1515 require 'uri'
1616 require 'fileutils'
1717 require 'pathname'
18 require 'socket'
1819 require 'timeout'
1920 require 'xmlrpc/client'
2021 # Monkey Patches/Fixes
3434 let(:body) { File.read(fixtures.join('searchreplacedb2.php')) }
3535
3636 it 'returns the InterestingFinding object' do
37 expect(finder.aggressive).to eql CMSScanner::Model::InterestingFinding.new(
37 expect(finder.aggressive).to eql CMSScanner::Model::SearchReplaceDB2.new(
3838 file_url,
3939 confidence: 100,
4040 found_by: 'Search Replace Db2 (Aggressive Detection)'
77 let(:headers) { {} }
88
99 before { stub_request(:get, file.url).to_return(headers: headers) }
10
11 describe '#to_s' do
12 its(:to_s) { should eql 'Headers' }
13 end
1014
1115 describe '#known_headers' do
1216 it 'does not contains dupliactes' do
0 # frozen_string_literal: true
1
2 describe CMSScanner::Model::SearchReplaceDB2 do
3 subject(:file) { described_class.new(url) }
4 let(:url) { 'http://example.com/searchreplacedb2.php' }
5
6 describe '#references' do
7 its(:references) { should_not be_nil }
8 end
9
10 describe '#type' do
11 its(:type) { should eql 'search_replace_db2' }
12 end
13 end
66
77 describe '#type' do
88 its(:type) { should eql 'xmlrpc' }
9 end
10
11 describe '#to_s' do
12 its(:to_s) { should eql 'XML-RPC seems to be enabled: http://example.com/xmlrpc' }
913 end
1014
1115 describe '#method_call' do
1313 let(:opts) { { show_progression: true } }
1414
1515 it 'uses the default progress-bar output' do
16 expect(finder.progress_bar.send(:output)).to be_a ProgressBar::Outputs::Tty
16 expected_bar_class = ENV['GITHUB_ACTION'] ? ProgressBar::Outputs::NonTty : ProgressBar::Outputs::Tty
17
18 expect(finder.progress_bar.send(:output)).to be_a expected_bar_class
1719 end
1820 end
1921
6060 expect(web_site.url('/sub/file.txt')).to eql 'http://e.org/sub/file.txt'
6161 end
6262 end
63 end
64 end
65
66 describe '#ip' do
67 context 'when target host not known' do
68 let(:url) { 'http://lab.local' }
69
70 its(:ip) { should eql 'Unknown' }
71 end
72
73 context 'when target host known' do
74 before { expect(IPSocket).to receive(:getaddress).and_return('127.0.0.1') }
75
76 its(:ip) { should eql '127.0.0.1' }
6377 end
6478 end
6579
0 [+] URL: http://e.org/
0 [+] URL: http://e.org/ [127.0.0.1]
11 [+] Started: Thu Oct 30 12:02:01 2014
22
11 "start_time": 1414670521,
22 "start_memory": 10,
33 "target_url": "http://e.org/",
4 "target_ip": "127.0.0.1",
45 "effective_url": "http://e.org/"
56 }
0 [+] URL: http://e.org/
0 [+] URL: http://e.org/ [127.0.0.1]
11 [+] Effective URL: http://e.org/home
22 [+] Started: Thu Oct 30 12:02:01 2014
33
11 "start_time": 1414670521,
22 "start_memory": 10,
33 "target_url": "http://e.org/",
4 "target_ip": "127.0.0.1",
45 "effective_url": "http://e.org/home"
56 }
22 shared_examples 'App::Views::Core' do
33 let(:controller) { CMSScanner::Controller::Core.new }
44 let(:start) { Time.at(1_414_670_521).in_time_zone('Europe/London') }
5 let(:tpl_vars) { { url: target_url, start_time: start } }
5 let(:tpl_vars) { { url: target_url, ip: '127.0.0.1', start_time: start } }
66
77 describe 'version' do
88 let(:view) { 'version' }
11
22 $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
33
4 require 'simplecov' # Used filters are in /.simplecov
4 require 'simplecov' # More config is defined in ./.simplecov
55 require 'rspec/its'
66 require 'webmock/rspec'
77 require 'active_support/time'
8
9 if ENV['TRAVIS']
10 require 'coveralls'
11 SimpleCov.formatter = Coveralls::SimpleCov::Formatter
12 end
138
149 # See http://betterspecs.org/
1510 RSpec.configure do |config|