This page looks best with JavaScript enabled

Arachni Security Scanner Source Code Analysis (Part 1)

 ·  ☕ 7 min read

Arachni is a web security vulnerability scanner built on the Ruby on Rails framework.

1. Ruby on Rails

Ruby on Rails, abbreviated ROR, is a web framework that consists of two parts: the Ruby language and the Rails framework. Ruby had always been popular in Japan, until 2004, when a 26-year-old Dane, David Heinemeier Hansson, proposed the web framework Rails. Only then did people around the world begin to appreciate the flexibility and efficiency of Ruby and Rails.

1.1 Ruby

The Japanese developer Matsumoto Yukihiro began work on the Ruby language in 1993. In December 1995 he released the first version of Ruby, Ruby 0.95.

Language characteristics:

  • A purely object-oriented language
  • An interpreted scripting language
  • Dynamic loading
  • Automatic memory management
  • Arbitrary-precision integers
  • Iterators and closures
  • An open-source project

1.2 Rails

Rails combines the rapid development of PHP with the well-structured nature of Java programs, making it a web development framework that fits real requirements and is more efficient.

Framework characteristics:

  • A full-stack MVC framework. It ships with tools for the Model, View, and Controller layers
  • Convention over XML configuration
  • A scaffolding system. It can automatically create CRUD operations and front-end views for a data table
  • High development efficiency, with less code

2. The Arachni-ui-web Directory Structure

Arachni-ui-web is one of Arachni’s front-end interfaces. The core part of Arachni is under the system/ruby/lib/ruby/gems/2.2.0/gems/arachni-1.5.1 directory.

2.1 The bin Directory

This holds user-facing execution scripts, providing basic startup and operation commands.

2.2 The system Directory

This includes the Ruby runtime environment, dependency packages, the project’s source code, the log directory, the user home directory, and so on. You could say that system contains everything the project needs.

system/arachni-ui-web is the project’s source directory. Within it:

  • The app directory. The project’s main directory, where most of the project code lives
  • The app/assets directory. Contains front-end resources: javascript, css, images
  • The app/controllers directory. Contains all the controllers. In Rails, a controller generally refers to a resource in the REST architecture. Controllers implement various actions used to respond to web requests. This is the C layer of the MVC architecture
  • The app/helper directory. Used to store helper methods, which are generally used in the view layer to organize logic code used by views
  • The app/mailers directory. Used for code related to sending mail
  • The app/models directory. Used for the various models mapped to the database. Data operations and business logic code should all go here. The M layer of the MVC architecture
  • The app/views directory. Used for view-layer templates. The controller renders these templates and finally generates the pages users can access. The V layer of the MVC architecture
  • The bin directory. Rails commands, as well as the bundle and rake commands
  • The config directory. Configuration for how the project runs, the database, and so on
  • The db directory. The current database schema, as well as database migrations
  • The features directory. Data files
  • The lib directory. Project extension packages
  • The log directory. System log files
  • The public directory. Public resources, including static files and linked resources
  • The script directory. Scripts for running or cleaning up the project
  • The spec directory. Test files for the RSpec tool
  • The tmp directory. Temporary files
  • The vendor directory. Third-party code, plugins, and so on

Other important files:

  • config/routes.rb.
    Specifies all the project’s routing configuration — that is, all the rules for sending and receiving web requests are specified here
  • db/seeds.rb.
    Initializes the database

3. Arachni XSS

The security testing code is mainly stored under arachni-1.5.1/components/checks/

Arachni’s principle for detecting XSS is to randomly generate an ID or specify a special string as the injected XSS vector. If that ID or string is found in the page content, then an XSS vulnerability exists.

The basic execution flow of the functions is: first assemble the XSS vector (tag_name, strings, options), then run( ) to execute, and finally look for evidence (find_included_payload, check_and_log, find_proof).

  • xss.rb.

Directly injects HTML with <> markup, and can also inject encoded XSS vectors.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    def self.tag_name
        "#{shortname}_#{random_seed}"
    end

    def self.tag
        "<#{tag_name}/>"
    end

    def self.strings
        @strings ||= [
            # Straight injection.
            tag,

            # Go for an error.
            "()\"&%1'-;#{tag}'",

            # Break out of HTML comments and text areas.
            "</textarea>-->#{tag}<!--<textarea>"
        ].map{ |p| [p, Form.encode( p ) ]}.flatten.uniq
    end
  • xss_dom.rb.

Detects DOM-based XSS attacks. DOM XSS uses something like document.body.innerHTML to dynamically inject XSS into the page.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    prefer :xss

    def self.tag_name
        "#{shortname}_#{random_seed}"
    end

    def self.tag
        "<#{tag_name}/>"
    end

    def self.strings
        @strings ||= [
            # Straight injection.
            tag,

            # Break out of HTML comments and text areas.
            "</textarea>-->#{tag}<!--<textarea>"
        ]
    end
  • xss_dom_script_context.rb.

Detects XSS DOM vulnerabilities, where the injected content is JavaScript code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    prefer :xss_script_context
    def self.seed
        'window.top._%s_taint_tracer.log_execution_flow_sink()'
    end

    def self.strings
        @strings ||= [
            "javascript:#{seed}//",
            "1;#{seed}//",
            "';#{seed}//",
            "\";#{seed}//",
            "*/;#{seed}/*"
        ]
    end
  • xss_event.rb.

Event- and attribute-based XSS. The types are ‘onload’, ‘onunload’, ‘onblur’, ‘onchange’, ‘onfocus’, ‘onreset’, ‘onselect’, ‘onsubmit’, ‘onabort’, ‘onkeydown’, ‘onkeypress’, ‘onkeyup’, ‘onclick’, ‘ondblclick’, ‘onmousedown’, ‘onmousemove’, ‘onmouseout’, ‘onmouseover’, ‘onmouseup’, ‘src’.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    def self.attribute_name
        'arachni_xss_in_element_event'
    end

    def self.strings
        @strings ||= [
            ";#{attribute_name}=#{random_seed}//",
            "\";#{attribute_name}=#{random_seed}//",
            "';#{attribute_name}=#{random_seed}//"
        ].map { |s| [ " script:#{s}", " #{s}" ] }.flatten
    end
  • xss_path.rb.

Assembles a URL to test for reflected XSS.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    def self.tag
        @tag ||= 'my_tag_' + random_seed
    end

    def self.string
        @string ||= '<' + tag + '/>'
    end

    def self.requests
        @requests ||= [
            [ string, {} ],
            [ '>"\'>' + string, {} ],

            [ '', { string => '' } ],
            [ '', { '>"\'>' + string => '' } ],

            [ '', { '' => string } ],
            [ '', { '' => '>"\'>' + string } ]
        ]
    end
  • xss_script_context.rb.

Uses the script tag to inject JavaScript.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    def self.seed
        'window.top._%s_taint_tracer.log_execution_flow_sink()'
    end

    def self.strings
        return @strings if @strings

        @strings ||= [ "javascript:#{seed}" ]

        ['\'', '"', ''].each do |quote|
            [ "%q;#{seed}%q", "%q;#{seed};%q" ].each do |payload|
                @strings << payload.gsub( '%q', quote )
            end
        end

        [ "1;#{seed}%q", "1;\n#{seed}%q" ].each do |payload|
            ['', ';'].each do |s|
                @strings << payload.gsub( '%q', s )
            end
        end

        @strings = @strings.map { |s| [ s, "#{s}//" ] }.flatten
        @strings << "*/;\n#{seed}/*"

        # In case they're placed as assoc array values.
        @strings << seed
        @strings << "\",x:#{seed},y:\""
        @strings << "',x:#{seed},y:'"

        @strings << "</script><script>#{seed}</script>"
    end
  • xss_tag.rb.
    Uses HTML tag attributes to execute XSS.
1
2
3
4
5
    ATTRIBUTE_NAME = 'arachni_xss_in_tag'
    def self.strings
        @strings ||= ['', '\'', '"'].
            map { |q| "#{q} #{ATTRIBUTE_NAME}=#{q}#{random_seed}#{q} blah=#{q}" }
    end
  • xxe.rb.

XML External Entity Injection, abbreviated XXE, occurs when an application parses XML input without prohibiting the loading of external entities.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    def self.options
        @options ||= {
            format:        [Format::STRAIGHT],
            signatures:    FILE_SIGNATURES_PER_PLATFORM.select { |k, _| payloads.include? k },
            each_mutation: proc do |mutation|
                mutation.platforms.pick( payloads ).map do |platform, payloads|
                    payloads.map do |payload|
                        m = mutation.dup

                        m.transform_xml do |xml|
                            xml.sub( m.affected_input_value, "&#{ENTITY};" )
                        end

                        m.audit_options[:platform] = platform
                        m.source = "<!DOCTYPE #{ENTITY} [ <!ENTITY #{ENTITY} SYSTEM \"#{payload}\"> ]>\n#{m.source}"
                        m
                    end
                end
            end
        }
    end

Tips:
If you start Arachni on Windows and encounter the prompt:

find: ‘/C’: No such file or directory
find: ‘/I’: No such file or directory

This happens because Cygwin is installed locally, which overrides the find command that ships with Windows. You need to replace find on line 17 of the setenv.bat file in the Arachni\system folder with “%windir%\system32\FIND.exe”.

4. References


微信公众号
WRITTEN BY
微信公众号