arachni源码学习记录
2021-02-07 14:58:27 Author: mp.weixin.qq.com(查看原文) 阅读量:89 收藏

有人问我w13scan和arachni的区别,之前没接触过,正好放假有空就看看这个扫描器。

Arachni是一个包含很多特性、模块化的、高性能的Ruby框架,目的是帮助渗透测试人员和管理者评估现代web应用程序的安全。Arachni是免费、源代码开源的,它支持所有主流操作系统

它是 ruby写的,地址是 https://www.arachni-scanner.com/ 它是可以基于webui来进行扫描操作。

扫描报告

不过我更关心的是它的扫描逻辑和payload,里面有不少模块值得w13scan学习,所以记录一下。

指纹识别

w13scan也有指纹识别的模块,路径是 W13SCAN/fingprints,也是收集自各个扫描器的,所以看arachni的指纹识别模块,只选取w13scan中没有的(现在没有,写完这篇记录之后就有了 = = )。

指纹都在 system/gems/gems/arachni-1.5.1/components/fingerprinters

用于识别框架,语言,操作系统和服务。

aspx_mvc 指纹识别

system/gems/gems/arachni-1.5.1/components/fingerprinters/frameworks/aspx_mvc.rb

言简意赅,从body,header,cookie中判断值。

ruby rack

symfony

asp

aspx

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. module Arachni

  8. module Platform::Fingerprinters

  9. # Identifies ASPX resources.

  10. #

  11. # @author Tasos "Zapotek" Laskos <[email protected]>

  12. # @version 0.1.1

  13. class ASPX < Platform::Fingerprinter

  14. EXTENSION = 'aspx'

  15. SESSION_COOKIE = 'asp.net_sessionid'

  16. X_POWERED_BY = 'asp.net'

  17. VIEWSTATE = '__viewstate'

  18. HEADER_FIELDS = %w(x-aspnet-version x-aspnetmvc-version)

  19. def run

  20. if extension == EXTENSION ||

  21. # Session ID in URL, like:

  22. # http://blah.com/(S(yn5cby55lgzstcen0ng2b4iq))/stuff.aspx

  23. uri.path =~ /\/\(s\([a-z0-9]+\)\)\//i

  24. return update_platforms

  25. end

  26. # Naive but enough, I think.

  27. if html? && page.body =~ /input.*#{VIEWSTATE}/i

  28. return update_platforms

  29. end

  30. if server_or_powered_by_include?( X_POWERED_BY ) ||

  31. (headers.keys & HEADER_FIELDS).any?

  32. return update_platforms

  33. end

  34. if cookies.include?( SESSION_COOKIE )

  35. update_platforms

  36. end

  37. end

  38. def update_platforms

  39. platforms << :asp << :aspx << :windows

  40. end

  41. end

  42. end

  43. end

路径抓取

如何从网页中取出更多路径,以后写爬虫的时候可能用得着,文件路径在 system/gems/gems/arachni-1.5.1/components/path_extractors

可以看出路径抓取直接操作的dom,这种方式获取的比较准确吧。

a href

从a标签获取

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # Extracts paths from anchor elements.

  8. #

  9. # @author Tasos "Zapotek" Laskos <[email protected]>

  10. class Arachni::Parser::Extractors::Anchors < Arachni::Parser::Extractors::Base

  11. def run

  12. return [] if !check_for?( 'href' )

  13. document.nodes_by_name( 'a' ).map { |a| a['href'] }

  14. end

  15. end

area href

  1. class Arachni::Parser::Extractors::Areas < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'area' ) || !check_for?( 'href' )

  4. document.nodes_by_name( 'area' ).map { |a| a['href'] }

  5. end

  6. end

网页注释

用正则从网页注释中获取url

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # Extract paths from HTML comments.

  8. #

  9. # @author Tasos "Zapotek" Laskos <[email protected]>

  10. class Arachni::Parser::Extractors::Comments < Arachni::Parser::Extractors::Base

  11. def run

  12. return [] if !check_for?( '<!--' )

  13. document.nodes_by_class( Arachni::Parser::Nodes::Comment ).map do |comment|

  14. comment.value.scan( /(^|\s)(\/[\/a-zA-Z0-9%._-]+)/ )

  15. end.flatten.select { |s| s.start_with? '/' }

  16. end

  17. end

data_url

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # Extracts paths from `data-url` attributes.

  8. #

  9. # @author Tasos "Zapotek" Laskos <[email protected]>

  10. class Arachni::Parser::Extractors::DataURL < Arachni::Parser::Extractors::Base

  11. def run

  12. return [] if !html || !check_for?( 'data-url' )

  13. html.scan( /data-url\s*=\s*['"]?(.*?)?['"]?[\s>]/ )

  14. end

  15. end

form action

  1. class Arachni::Parser::Extractors::Forms < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'action' )

  4. document.nodes_by_name( 'form' ).map { |f| f['action'] }

  5. end

  6. end

iframe src

  1. class Arachni::Parser::Extractors::Frames < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'frame' )

  4. document.nodes_by_names( ['frame', 'iframe'] ).map { |n| n['src'] }

  5. end

  6. end

link href

  1. class Arachni::Parser::Extractors::Links < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'link' )

  4. document.nodes_by_name( 'link' ).map { |l| l['href'] }

  5. end

  6. end

meta refresh

  1. class Arachni::Parser::Extractors::MetaRefresh < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'http-equiv' )

  4. document.nodes_by_attribute_name_and_value( 'http-equiv', 'refresh' ).

  5. map do |url|

  6. begin

  7. _, url = url['content'].split( ';', 2 )

  8. next if !url

  9. unquote( url.split( '=', 2 ).last.strip )

  10. rescue

  11. next

  12. end

  13. end

  14. end

  15. def unquote( str )

  16. [ '\'', '"' ].each do |q|

  17. return str[1...-1] if str.start_with?( q ) && str.end_with?( q )

  18. end

  19. str

  20. end

  21. end

script 中提取url

  1. class Arachni::Parser::Extractors::Scripts < Arachni::Parser::Extractors::Base

  2. def run

  3. return [] if !check_for?( 'script' )

  4. document.nodes_by_name( 'script' ).map do |s|

  5. [s['src']].flatten.compact | from_text( s.text.to_s )

  6. end

  7. end

  8. def from_text( text )

  9. text.scan( /[\/a-zA-Z0-9%._-]+/ ).

  10. select do |s|

  11. # String looks like a path, but don't get fooled by comments.

  12. s.include?( '.' ) && s.include?( '/' ) &&

  13. !s.include?( '*' ) && !s.start_with?( '//' ) &&

  14. # Require absolute paths, otherwise we may get caught in

  15. # a loop, this context isn't the most reliable for extracting

  16. # real paths.

  17. s.start_with?( '/' )

  18. end

  19. end

  20. end

扫描插件

基于时间的代码注入

代码注入

  1. class Arachni::Checks::CodeInjection < Arachni::Check::Base

  2. def self.rand1

  3. @rand1 ||= '28763'

  4. end

  5. def self.rand2

  6. @rand2 ||= '4196403'

  7. end

  8. def self.options

  9. @options ||= {

  10. signatures: (rand1.to_i * rand2.to_i).to_s,

  11. format: [Format::STRAIGHT]

  12. }

  13. end

  14. def self.code_strings

  15. # code strings to be injected to the webapp

  16. @code_strings ||= {

  17. php: "print #{rand1}*#{rand2};",

  18. perl: "print #{rand1}*#{rand2};",

  19. python: "print #{rand1}*#{rand2}",

  20. asp: "Response.Write\x28#{rand1}*#{rand2}\x29"

  21. }

  22. end

  23. def self.payloads

  24. return @payloads if @payloads

  25. @payloads = {}

  26. code_strings.each do |platform, payload|

  27. @payloads[platform] = [ ';%s', "\";%s#", "';%s#" ].

  28. map { |var| var % payload } | [payload]

  29. end

  30. @payloads

  31. end

  32. def run

  33. audit( self.class.payloads, self.class.options )

  34. end

  35. def self.info

  36. {

  37. name: 'Code injection',

  38. description: %q{

  39. Injects code snippets and assess whether or not execution was successful.

  40. },

  41. elements: ELEMENTS_WITH_INPUTS,

  42. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  43. version: '0.2.5',

  44. platforms: payloads.keys,

  45. issue: {

  46. name: %q{Code injection},

  47. description: %q{

  48. A modern web application will be reliant on several different programming languages.

  49. These languages can be broken up in two flavours. These are client-side languages

  50. (such as those that run in the browser -- like JavaScript) and server-side

  51. languages (which are executed by the server -- like ASP, PHP, JSP, etc.) to form

  52. the dynamic pages (client-side code) that are then sent to the client.

  53. Because all server-side code should be executed by the server, it should only ever

  54. come from a trusted source.

  55. Code injection occurs when the server takes untrusted code (ie. from the client)

  56. and executes it.

  57. Cyber-criminals will abuse this weakness to execute arbitrary code on the server,

  58. which could result in complete server compromise.

  59. Arachni was able to inject specific server-side code and have the executed output

  60. from the code contained within the server response. This indicates that proper input

  61. sanitisation is not occurring.

  62. },

  63. references: {

  64. 'PHP' => 'http://php.net/manual/en/function.eval.php',

  65. 'Perl' => 'http://perldoc.perl.org/functions/eval.html',

  66. 'Python' => 'http://docs.python.org/py3k/library/functions.html#eval',

  67. 'ASP' => 'http://www.aspdev.org/asp/asp-eval-execute/',

  68. },

  69. tags: %w(code injection regexp),

  70. cwe: 94,

  71. severity: Severity::HIGH,

  72. remedy_guidance: %q{

  73. It is recommended that untrusted input is never processed as server-side code.

  74. To validate input, the application should ensure that the supplied value contains

  75. only the data that are required to perform the relevant action.

  76. For example, where a username is required, then no non-alpha characters should not

  77. be accepted.

  78. }

  79. }

  80. }

  81. end

  82. end

ldap注入

  1. class Arachni::Checks::LdapInjection < Arachni::Check::Base

  2. def self.error_strings

  3. @errors ||= read_file( 'errors.txt' )

  4. end

  5. def run

  6. # This string will hopefully force the webapp to output LDAP error messages.

  7. audit( '#^($!@$)(()))******',

  8. format: [Format::APPEND],

  9. signatures: self.class.error_strings

  10. )

  11. end

  12. def self.info

  13. {

  14. name: 'LDAPInjection',

  15. description: %q{

  16. It tries to force the web application to return LDAP error messages, in order to

  17. discover failures in user input validation.

  18. },

  19. elements: ELEMENTS_WITH_INPUTS,

  20. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  21. version: '0.1.4',

  22. issue: {

  23. name: %q{LDAP Injection},

  24. description: %q{

  25. Lightweight Directory Access Protocol (LDAP) is used by web applications to access

  26. and maintain directory information services.

  27. One of the most common uses for LDAP is to provide a Single-Sign-On (SSO) service

  28. that will allow clients to authenticate with a web site without any interaction

  29. (assuming their credentials have been validated by the SSO provider).

  30. LDAP injection occurs when untrusted data is used by the web application to query

  31. the LDAP directory without prior sanitisation.

  32. This is a serious security risk, as it could allow cyber-criminals the ability

  33. to query, modify, or remove anything from the LDAP tree. It could also allow other

  34. advanced injection techniques that perform other more serious attacks.

  35. Arachni was able to detect a page that is vulnerable to LDAP injection based on

  36. known error messages.

  37. },

  38. tags: %w(ldap injection regexp),

  39. references: {

  40. 'WASC' => 'http://projects.webappsec.org/w/page/13246947/LDAP-Injection',

  41. 'OWASP' => 'https://www.owasp.org/index.php/LDAP_injection'

  42. },

  43. cwe: 90,

  44. severity: Severity::HIGH,

  45. remedy_guidance: %q{

  46. It is recommended that untrusted data is never used to form a LDAP query.

  47. To validate data, the application should ensure that the supplied value contains

  48. only the characters that are required to perform the required action. For example,

  49. where a username is required, then no non-alphanumeric characters should be accepted.

  50. If this is not possible, special characters should be escaped so they are treated

  51. accordingly. The following characters should be escaped with a `\`:

  52. * `&`

  53. * `!`

  54. * `|`

  55. * `=`

  56. * `<`

  57. * `>`

  58. * `,`

  59. * `+`

  60. * `-`

  61. * `"`

  62. * `'`

  63. * `;`

  64. Additional character filtering must be applied to:

  65. * `(`

  66. * `)`

  67. * `\`

  68. * `/`

  69. * `*`

  70. * `NULL`

  71. These characters require ASCII escaping.

  72. }

  73. }

  74. }

  75. end

  76. end

errors.txt

  1. supplied argument is not a valid ldap

  2. javax.naming.NameNotFoundException

  3. javax.naming.directory.InvalidSearchFilterException

  4. LDAPException

  5. com.sun.jndi.ldap

  6. Search: Bad search filter

  7. Protocol error occurred

  8. Size limit has exceeded

  9. An inappropriate matching occurred

  10. A constraint violation occurred

  11. The syntax is invalid

  12. Object does not exist

  13. The alias is invalid

  14. The distinguished name has an invalid syntax

  15. The server does not handle directory requests

  16. There was a naming violation

  17. There was an object class violation

  18. Results returned are too large

  19. Unknown error occurred

  20. Local error occurred

  21. The search filter is incorrect

  22. The search filter is invalid

  23. The search filter cannot be recognized

  24. Invalid DN syntax

  25. No Such Object

  26. IPWorksASP.LDAP

  27. Module Products.LDAPMultiPlugins

No Sql 注入(差分法)

  1. class Arachni::Checks::NoSqlInjectionDifferential < Arachni::Check::Base

  2. def self.options

  3. return @options if @options

  4. pairs = []

  5. [ '\'', '"', '' ].each do |q|

  6. {

  7. '%q;return true;var foo=%q' => '%q;return false;var foo=%q',

  8. '1%q||this%q' => '1%q||!this%q'

  9. }.each do |s_true, s_false|

  10. pairs << { s_true.gsub( '%q', q ) => s_false.gsub( '%q', q ) }

  11. end

  12. end

  13. @options = { false: '-1839', pairs: pairs }

  14. end

  15. def run

  16. audit_differential self.class.options

  17. end

  18. def self.info

  19. {

  20. name: 'Blind NoSQL Injection (differential analysis)',

  21. description: %q{

  22. It uses differential analysis to determine how different inputs affect the behavior

  23. of the web application and checks if the displayed behavior is consistent with

  24. that of a vulnerable application.

  25. },

  26. elements: [ Element::Link, Element::Form, Element::Cookie ],

  27. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  28. version: '0.1.2',

  29. platforms: [ :nosql ],

  30. issue: {

  31. name: %q{Blind NoSQL Injection (differential analysis)},

  32. description: %q{

  33. A NoSQL injection occurs when a value originating from the client's request is

  34. used within a NoSQL call without prior sanitisation.

  35. This can allow cyber-criminals to execute arbitrary NoSQL code and thus steal data,

  36. or use the additional functionality of the database server to take control of

  37. further server components.

  38. Arachni discovered that the affected page and parameter are vulnerable. This

  39. injection was detected as Arachni was able to inject specific NoSQL queries that

  40. if vulnerable result in the responses for each injection being different. This is

  41. known as a blind NoSQL injection vulnerability.

  42. },

  43. tags: %w(nosql blind differential injection database),

  44. references: {

  45. 'OWASP' => 'https://www.owasp.org/index.php/Testing_for_NoSQL_injection'

  46. },

  47. cwe: 89,

  48. severity: Severity::HIGH,

  49. remedy_guidance: %q{

  50. The most effective remediation against NoSQL injection attacks is to ensure that

  51. NoSQL API calls are not constructed via string concatenation that includes

  52. unsanitized data.

  53. Sanitization is best achieved using existing escaping libraries.

  54. }

  55. }

  56. }

  57. end

  58. end

No SQL注入(报错)

主要看payload,报错

  1. Uncaught exception 'MongoCursorException'

响应头拆分

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # HTTP Response Splitting check.

  8. #

  9. # @author Tasos "Zapotek" Laskos <[email protected]>

  10. # @version 0.2.3

  11. #

  12. # @see http://cwe.mitre.org/data/definitions/20.html

  13. # @see https://www.owasp.org/index.php/HTTP_Response_Splitting

  14. # @see http://www.securiteam.com/securityreviews/5WP0E2KFGK.html

  15. class Arachni::Checks::ResponseSplitting < Arachni::Check::Base

  16. def run

  17. header_name = "X-CRLF-Safe-#{random_seed}"

  18. # the header to inject...

  19. # what we will check for in the response header

  20. # is the existence of the "x-crlf-safe" field.

  21. # if we find it it means that the attack was successful

  22. # thus site is vulnerable.

  23. header = "\r\n#{header_name}: no"

  24. # try to inject the headers into all vectors

  25. # and pass a block that will check for a positive result

  26. audit(

  27. header,

  28. submit: {

  29. follow_location: false,

  30. response_max_size: 0

  31. }

  32. ) do |response, element|

  33. next if response.headers[header_name].to_s.downcase != 'no'

  34. log(

  35. vector: element,

  36. response: response,

  37. proof: response.headers_string[/#{header_name}.*$/i]

  38. )

  39. end

  40. end

  41. def self.info

  42. {

  43. name: 'Response Splitting',

  44. description: %q{

  45. Injects arbitrary and checks if any of them end up in the response header.

  46. },

  47. elements: ELEMENTS_WITH_INPUTS,

  48. author: 'Tasos "Zapotek" Laskos <[email protected]> ',

  49. version: '0.2.3',

  50. issue: {

  51. name: %q{Response Splitting},

  52. description: %q{

  53. HTTP response splitting occurs when untrusted data is inserted into the response

  54. headers without any sanitisation.

  55. If successful, this allows cyber-criminals to essentially split the HTTP response

  56. in two.

  57. This is abused by cyber-criminals injecting CR (Carriage Return -- `/r`)

  58. and LF (Line Feed -- `\n`) characters which will then form the split. If the CR

  59. or LF characters are not processed by the server then it cannot be exploited.

  60. Along with these characters, cyber-criminals can then construct their own

  61. arbitrary response headers and body which would then form the second response.

  62. The second response is entirely under their control, allowing for a number of

  63. other attacks.

  64. },

  65. references: {

  66. 'SecuriTeam' => 'http://www.securiteam.com/securityreviews/5WP0E2KFGK.html',

  67. 'OWASP' => 'https://www.owasp.org/index.php/HTTP_Response_Splitting'

  68. },

  69. tags: %w(response splitting injection header),

  70. cwe: 20,

  71. severity: Severity::HIGH,

  72. remedy_guidance: %q{

  73. It is recommended that untrusted data is never used to form the contents of the

  74. response header.

  75. Where any untrusted source is required to be used in the response headers, it is

  76. important to ensure that any hazardous characters (`/r`, `/n` and potentially

  77. others) are sanitised prior to being used.

  78. This is especially important when setting cookie values, redirecting, etc..

  79. },

  80. }

  81. }

  82. end

  83. end

xpath注入

  1. class Arachni::Checks::XpathInjection < Arachni::Check::Base

  2. def self.error_strings

  3. @error_strings ||= read_file( 'errors.txt' )

  4. end

  5. # These will hopefully cause the webapp to output XPath error messages.

  6. def self.payloads

  7. @payloads ||= %w('" ]]]]]]]]] <!--)

  8. end

  9. def self.options

  10. @options ||= { format: [Format::APPEND], signatures: error_strings }

  11. end

  12. def run

  13. audit self.class.payloads, self.class.options

  14. end

  15. def self.info

  16. {

  17. name: 'XPath Injection',

  18. description: %q{XPath injection check},

  19. elements: ELEMENTS_WITH_INPUTS,

  20. author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',

  21. version: '0.1.6',

  22. issue: {

  23. name: %q{XPath Injection},

  24. description: %q{

  25. XML Path Language (XPath) queries are used by web applications for selecting

  26. nodes from XML documents.

  27. Once selected, the value of these nodes can then be used by the application.

  28. A simple example for the use of XML documents is to store user information. As

  29. part of the authentication process, the application will perform an XPath query

  30. to confirm the login credentials and retrieve that user's information to use in

  31. the following request.

  32. XPath injection occurs where untrusted data is used to build XPath queries.

  33. Cyber-criminals may abuse this injection vulnerability to bypass authentication,

  34. query other user's information, or, if the XML document contains privileged user

  35. credentials, allow the cyber-criminal to escalate their privileges.

  36. Arachni injected special XPath query characters into the page and based on the

  37. responses from the server, has determined that the page is vulnerable to XPath injection.

  38. },

  39. references: {

  40. 'OWASP' => 'https://www.owasp.org/index.php/XPATH_Injection',

  41. 'WASC' => 'http://projects.webappsec.org/w/page/13247005/XPath%20Injection'

  42. },

  43. tags: %w(xpath database error injection regexp),

  44. cwe: 91,

  45. severity: Severity::HIGH,

  46. remedy_guidance: %q{

  47. The preferred way to protect against XPath injection is to utilise parameterized

  48. (also known as prepared) XPath queries.

  49. When utilising this method of querying the XML document any value supplied by the

  50. client will be handled as a string rather than part of the XPath query.

  51. An alternative to parameterized queries it to use precompiled XPath queries.

  52. Precompiled XPath queries are not generated dynamically and will therefor never

  53. process user supplied input as XPath.

  54. }

  55. }

  56. }

  57. end

  58. end

errors.txt

  1. xmlXPathEval: evaluation failed

  2. SimpleXMLElement::xpath()

  3. XPathException

  4. MS.Internal.Xml.

  5. Unknown error in XPath

  6. org.apache.xpath.XPath

  7. A closing bracket expected in

  8. An operand in Union Expression does not produce a node-set

  9. Cannot convert expression to a number

  10. Document Axis does not allow any context Location Steps

  11. Empty Path Expression

  12. Empty Relative Location Path

  13. Empty Union Expression

  14. Expected ')' in

  15. Expected node test or name specification after axis operator

  16. Incompatible XPath key

  17. Incorrect Variable Binding

  18. libxml2 library function failed

  19. xmlsec library function

  20. error '80004005'

  21. A document must contain exactly one root element.

  22. Expression must evaluate to a node-set.

  23. Expected token ']'

  24. <p>msxml4.dll</font>

  25. <p>msxml3.dll</font>

XXE

  1. class Arachni::Checks::Xxe < Arachni::Check::Base

  2. ENTITY = 'xxe_entity'

  3. def self.options

  4. @options ||= {

  5. format: [Format::STRAIGHT],

  6. signatures: FILE_SIGNATURES_PER_PLATFORM.select { |k, _| payloads.include? k },

  7. each_mutation: proc do |mutation|

  8. mutation.platforms.pick( payloads ).map do |platform, payloads|

  9. payloads.map do |payload|

  10. m = mutation.dup

  11. m.transform_xml do |xml|

  12. xml.sub( m.affected_input_value, "&#{ENTITY};" )

  13. end

  14. m.audit_options[:platform] = platform

  15. m.source = "<!DOCTYPE #{ENTITY} [ <!ENTITY #{ENTITY} SYSTEM \"#{payload}\"> ]>\n#{m.source}"

  16. m

  17. end

  18. end

  19. end

  20. }

  21. end

  22. def self.payloads

  23. @payloads ||= {

  24. unix: [

  25. '/proc/self/environ',

  26. '/etc/passwd'

  27. ],

  28. windows: [

  29. '%SYSTEMDRIVE%\boot.ini',

  30. '%WINDIR%\win.ini'

  31. ]

  32. }

  33. end

  34. def run

  35. # We can't inject entities because they're going to get sanitized,

  36. # instead we inject a placeholder which we can later replace via a

  37. # regular text substitution.

  38. audit random_seed, self.class.options

  39. end

  40. def self.info

  41. {

  42. name: 'XML External Entity',

  43. description: %q{

  44. Injects a custom External Entity into XML documents prior to submitting them and

  45. determines the existence of a vulnerability by checking whether that entity was

  46. processed based on the resulting HTTP response.

  47. },

  48. elements: [Element::XML],

  49. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  50. version: '0.1.2',

  51. platforms: options[:signatures].keys,

  52. issue: {

  53. name: %q{XML External Entity},

  54. description: %q{

  55. An XML External Entity attack is a type of attack against an application that

  56. parses XML input.

  57. This attack occurs when XML input containing a reference to an external entity is

  58. processed by a weakly configured XML parser.

  59. This attack may lead to the disclosure of confidential data, denial of service,

  60. port scanning from the perspective of the machine where the parser is located,

  61. and other system impacts.

  62. },

  63. references: {

  64. 'OWASP' => 'https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing'

  65. },

  66. cwe: 611,

  67. severity: Severity::HIGH,

  68. remedy_guidance: %q{

  69. Since the whole XML document is communicated from an untrusted client, it's not

  70. usually possible to selectively validate or escape tainted data within the system

  71. identifier in the DTD.

  72. Therefore, the XML processor should be configured to use a local static DTD and

  73. disallow any declared DTD included in the XML document.

  74. }

  75. }

  76. }

  77. end

  78. end

目录遍历

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # Tries to force directory listings.

  8. #

  9. # Can't take credit for this one, it's Michal's (lcamtuf's) method from Skipfish.

  10. #

  11. # @author Tasos "Zapotek" Laskos <[email protected]>

  12. class Arachni::Checks::DirectoryListing < Arachni::Check::Base

  13. # The compared pages must be at least 75% different

  14. DIFF_THRESHOLD = 0.75

  15. def self.dirs

  16. @dirs ||= [ "\\.#{random_seed}\\", "\\.\\", ".#{random_seed}/", "./" ]

  17. end

  18. def run

  19. return if page.code != 200

  20. path = get_path( page.url )

  21. parsed_path = uri_parse( path ).path

  22. return if parsed_path == '/' || audited?( parsed_path )

  23. @harvested = []

  24. dirs = [ page.url ] | self.class.dirs.map { |dir| path + dir } | [ path ]

  25. dirs.each_with_index do |url, i|

  26. http.get( url ) do |res|

  27. next if !res

  28. @harvested[i] = res

  29. check_and_log( path ) if done_harvesting?

  30. end

  31. end

  32. end

  33. def done_harvesting?

  34. return false if @harvested.size != 6

  35. @harvested.each { |res| return false if !res }

  36. true

  37. end

  38. def check_and_log( path )

  39. audited( path )

  40. # If we have a 403 Forbidden it means that we successfully

  41. # built a pah which would force a directory listing *but*

  42. # the web server kicked our asses...so let's run away like

  43. # little girls...

  44. @harvested.each { |res| return if !res.ok? || res.code == 403 }

  45. if !File.basename( @harvested[0].url, '?*' ).empty? &&

  46. same_page?( @harvested[0], @harvested[5] )

  47. return

  48. end

  49. if same_page?( @harvested[1], @harvested[0] ) ||

  50. same_page?( @harvested[1], @harvested[2] ) ||

  51. same_page?( @harvested[3], @harvested[0] ) ||

  52. same_page?( @harvested[3], @harvested[4] ) ||

  53. @harvested[5].code != 200 || @harvested[5].body.empty?

  54. return

  55. end

  56. log vector: Element::Server.new( @harvested[5].url ), response: @harvested[5]

  57. end

  58. def same_page?( res1, res2 )

  59. res1.code == res2.code && res1.body.diff_ratio( res2.body ) <= DIFF_THRESHOLD

  60. end

  61. def self.info

  62. {

  63. name: 'Directory listing',

  64. description: %q{Tries to force directory listings.},

  65. elements: [ Element::Server ],

  66. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  67. version: '0.1.7',

  68. exempt_platforms: Arachni::Platform::Manager::FRAMEWORKS,

  69. issue: {

  70. name: %q{Directory listing},

  71. description: %q{

  72. Web servers permitting directory listing are typically used for sharing files.

  73. Directory listing allows the client to view a simple list of all the files and

  74. folders hosted on the web server. The client is then able to traverse each

  75. directory and download the files.

  76. Cyber-criminals will utilise the presence of directory listing to discover

  77. sensitive files, download protected content, or even just learn how the web

  78. application is structured.

  79. Arachni discovered that the affected page permits directory listing.

  80. },

  81. references: {

  82. 'WASC' => 'http://projects.webappsec.org/w/page/13246922/Directory%20Indexing'

  83. },

  84. tags: %w(path directory listing index),

  85. cwe: 548,

  86. severity: Severity::LOW,

  87. remedy_guidance: %q{

  88. Unless the web server is being utilised to share static and non-sensitive files,

  89. enabling directory listing is considered a poor security practice

  90. This can typically be done with a simple configuration change on the server. The

  91. steps to disable the directory listing will differ depending on the type of server

  92. being used (IIS, Apache, etc.).

  93. If directory listing is required, and permitted, then steps should be taken to

  94. ensure that the risk of such a configuration is reduced.

  95. These can include:

  96. 1. Requiring authentication to access affected pages.

  97. 2. Adding the affected path to the `robots.txt` file to prevent the directory

  98. contents being searchable via search engines.

  99. 3. Ensuring that sensitive files are not stored within the web or document root.

  100. 4. Removing any files that are not required for the application to function.

  101. }

  102. }

  103. }

  104. end

  105. end

HTTP PUT

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # HTTP PUT recon check.

  8. #

  9. # @author Tasos "Zapotek" Laskos <[email protected]>

  10. class Arachni::Checks::HttpPut < Arachni::Check::Base

  11. def self.substring

  12. @substring ||= 'PUT' + random_seed

  13. end

  14. def self.body

  15. @body ||= 'Created by Arachni. ' + substring

  16. end

  17. def run

  18. path = "#{get_path( page.url )}Arachni-#{random_seed}"

  19. return if audited?( path )

  20. audited( path )

  21. http.request( path, method: :put, body: self.class.body ) do |res|

  22. next if res.code != 201

  23. http.get( path ) do |c_res|

  24. check_and_log( c_res, res )

  25. # Try to DELETE the PUT file.

  26. http.request( path, method: :delete ){}

  27. end

  28. end

  29. end

  30. def check_and_log( response, put_response )

  31. return if !response.body.to_s.include?( self.class.substring )

  32. log(

  33. vector: Element::Server.new( response.url ),

  34. response: put_response,

  35. proof: put_response.status_line

  36. )

  37. end

  38. def self.info

  39. {

  40. name: 'HTTP PUT',

  41. description: %q{Checks if uploading files is possible using the HTTP PUT method.},

  42. elements: [ Element::Server ],

  43. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  44. version: '0.2.3',

  45. issue: {

  46. name: %q{Publicly writable directory},

  47. description: %q{

  48. There are various methods in which a file (or files) may be uploaded to a

  49. webserver. One method that can be used is the HTTP `PUT` method. The `PUT`

  50. method is mainly used during development of applications and allows developers to

  51. upload (or put) files on the server within the web root.

  52. By nature of the design, the `PUT` method typically does not provide any filtering

  53. and therefore allows sever side executable code (PHP, ASP, etc) to be uploaded to

  54. the server.

  55. Cyber-criminals will search for servers supporting the `PUT` method with the

  56. intention of modifying existing pages, or uploading web shells to take control

  57. of the server.

  58. Arachni has discovered that the affected path allows clients to use the `PUT`

  59. method. During this test, Arachni has `PUT` a file on the server within the web

  60. root and successfully performed a `GET` request to its location and verified the

  61. contents.

  62. },

  63. references: {

  64. 'W3' => 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html'

  65. },

  66. tags: %w(http methods put server),

  67. cwe: 650,

  68. severity: Severity::HIGH,

  69. remedy_guidance: %q{

  70. Where possible the HTTP `PUT` method should be globally disabled.

  71. This can typically be done with a simple configuration change on the server.

  72. The steps to disable the `PUT` method will differ depending on the type of server

  73. being used (IIS, Apache, etc.).

  74. For cases where the `PUT` method is required to meet application functionality,

  75. such as REST style web services, strict limitations should be implemented to

  76. ensure that only secure (SSL/TLS enabled) and authorised clients are permitted

  77. to use the `PUT` method.

  78. Additionally, the server's file system permissions should also enforce strict limitations.

  79. }

  80. }

  81. }

  82. end

  83. end

发现有趣内容

会记录所有非200和非400的响应

  1. def self.acceptable

  2. [ 102, 200, 201, 202, 203, 206, 207, 208, 226, 300, 301, 302,

  3. 303, 305, 306, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409,

  4. 410, 411, 412, 413, 414, 415, 416, 417, 418, 420, 422, 423, 424, 425, 426, 428,

  5. 429, 431, 444, 449, 450, 451, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508,

  6. 509, 510, 511, 598, 599

  7. ]

  8. end

会将这个内容记录下来。

本地欺骗绕过

对于访问为403或404的页面,可以修改一下请求头的ip尝试绕过

  1. class Arachni::Checks::OriginSpoofAccessRestrictionBypass < Arachni::Check::Base

  2. HEADERS = [

  3. 'X-Forwarded-For',

  4. 'X-Originating-IP',

  5. 'X-Remote-IP',

  6. 'X-Remote-Addr'

  7. ]

  8. ADDRESS = '127.0.0.1'

  9. def self.http_options

  10. @http_options ||= {

  11. headers: HEADERS.inject({}) { |h, header| h.merge( header => ADDRESS ) }

  12. }

  13. end

  14. def run

  15. return if ![401, 403].include?( page.code )

  16. http.get( page.url, self.class.http_options, &method(:check_and_log) )

  17. end

  18. def check_and_log( response )

  19. return if response.code != 200

  20. log(

  21. vector: Element::Server.new( response.url ),

  22. response: response,

  23. proof: response.status_line

  24. )

  25. print_ok "Request was accepted: #{response.url}"

  26. end

  27. def self.info

  28. {

  29. name: 'Origin Spoof Access Restriction Bypass',

  30. description: %q{Retries denied requests with a spoofed origin header

  31. to trick the web application into thinking that the request originated

  32. from localhost and checks whether the restrictions was bypassed.},

  33. elements: [ Element::Server ],

  34. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  35. version: '0.1',

  36. issue: {

  37. name: %q{Access restriction bypass via origin spoof},

  38. description: %q{

  39. Origin headers are utilised by proxies and/or load balancers to track the

  40. originating IP address of the client.

  41. As the request progresses through a proxy, the origin header is added to the

  42. existing headers, and the value of the client's IP is then set within this header.

  43. Occasionally, poorly implemented access restrictions are based off of the

  44. originating IP address alone.

  45. For example, any public IP address may be forced to authenticate, while an

  46. internal IP address may not.

  47. Because this header can also be set by the client, it allows cyber-criminals to

  48. spoof their IP address and potentially gain access to restricted pages.

  49. Arachni discovered a resource that it did not have permission to access, but been

  50. granted access after spoofing the address of localhost (127.0.0.1), thus bypassing

  51. any requirement to authenticate.

  52. },

  53. tags: %w(access restriction server bypass),

  54. severity: Severity::HIGH,

  55. remedy_guidance: %q{

  56. Remediation actions may be vastly different depending on the framework being used,

  57. and how the application has been coded. However, the origin header should never

  58. be used to validate a client's access as it is trivial to change.

  59. }

  60. }

  61. }

  62. end

  63. end

webdav

  1. =begin

  2. Copyright 2010-2017 Sarosys LLC <http://www.sarosys.com>

  3. This file is part of the Arachni Framework project and is subject to

  4. redistribution and commercial restrictions. Please see the Arachni Framework

  5. web site for more information on licensing and terms of use.

  6. =end

  7. # WebDAV detection recon check.

  8. #

  9. # It doesn't check for a functional DAV implementation but uses the

  10. # OPTIONS HTTP method to see if 'PROPFIND' is allowed.

  11. #

  12. # @author Tasos "Zapotek" Laskos <[email protected]>

  13. #

  14. # @see http://en.wikipedia.org/wiki/WebDAV

  15. # @see http://www.webdav.org/specs/rfc4918.html

  16. class Arachni::Checks::Webdav < Arachni::Check::Base

  17. def self.dav_method

  18. @check ||= 'PROPFIND'

  19. end

  20. def self.found?

  21. @found ||= false

  22. end

  23. def self.found

  24. @found = true

  25. end

  26. def run

  27. path = get_path( page.url )

  28. return if self.class.found? || audited?( path )

  29. http.request( path, method: :options ) { |response| check_and_log( response ) }

  30. audited( path )

  31. end

  32. def check_and_log( response )

  33. begin

  34. allowed = response.headers['Allow'].split( ',' ).map { |method| method.strip }

  35. return if !allowed.include?( self.class.dav_method )

  36. rescue

  37. return

  38. end

  39. self.class.found

  40. log(

  41. proof: response.headers['Allow'],

  42. vector: Element::Server.new( response.url ),

  43. response: response

  44. )

  45. print_ok "Enabled for: #{response.url}"

  46. end

  47. def self.info

  48. {

  49. name: 'WebDAV',

  50. description: %q{Checks for WebDAV enabled directories.},

  51. elements: [ Element::Server ],

  52. author: 'Tasos "Zapotek" Laskos <[email protected]>',

  53. version: '0.1.5',

  54. issue: {

  55. name: %q{WebDAV},

  56. description: %q{

  57. Web Distributed Authoring and Versioning (WebDAV) is a facility that enables

  58. basic file management (reading and writing) to a web server. It essentially allows

  59. the webserver to be mounted by the client as a traditional file system allowing

  60. users a very simplistic means to access it as they would any other medium or

  61. network share.

  62. If discovered, attackers will attempt to harvest information from the WebDAV

  63. enabled directories, or even upload malicious files that could then be used to

  64. compromise the server.

  65. Arachni discovered that the affected page allows WebDAV access. This was discovered

  66. as the server allowed several specific methods that are specific to WebDAV (`PROPFIND`,

  67. `PROPPATCH`, etc.), however, further testing should be conducted on the WebDAV

  68. component specifically as Arachni does support this feature.

  69. },

  70. references: {

  71. 'WebDAV.org' => 'http://www.webdav.org/specs/rfc4918.html',

  72. 'Wikipedia' => 'http://en.wikipedia.org/wiki/WebDAV',

  73. },

  74. tags: %w(webdav options methods server),

  75. severity: Severity::INFORMATIONAL,

  76. remedy_guidance: %q{

  77. Identification of the requirement to run a WebDAV server should be considered.

  78. If it is not required then it should be disabled. However, if it is required to

  79. meet the application functionality, then it should be protected by SSL/TLS as

  80. well as the implementation of a strong authentication mechanism.

  81. }

  82. }

  83. }

  84. end

  85. end

Ps:代码格式在粘贴的时候可能有损坏,可以点击查看全文在我博客看完整的内容。


文章来源: http://mp.weixin.qq.com/s?__biz=MzU2NzcwNTY3Mg==&mid=2247483929&idx=1&sn=a4b5f05257383dbfd3d31a7523dac698&chksm=fc986b3ecbefe2289b046f20cbc52afd8401499a3c1f86f22666da4ed278c53e6527c286e87f#rd
如有侵权请联系:admin#unsafe.sh