miketracy-wwmd 0.2.11

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.
Files changed (70) hide show
  1. data/History.txt +3 -0
  2. data/README +62 -0
  3. data/README.txt +62 -0
  4. data/Rakefile +34 -0
  5. data/examples/config_example.yaml +24 -0
  6. data/examples/wwmd_example.rb +73 -0
  7. data/lib/wwmd.rb +78 -0
  8. data/lib/wwmd/encoding.rb +40 -0
  9. data/lib/wwmd/form.rb +110 -0
  10. data/lib/wwmd/form_array.rb +273 -0
  11. data/lib/wwmd/guid.rb +155 -0
  12. data/lib/wwmd/hpricot_html2text.rb +76 -0
  13. data/lib/wwmd/mixins.rb +318 -0
  14. data/lib/wwmd/mixins_extends.rb +188 -0
  15. data/lib/wwmd/mixins_external.rb +18 -0
  16. data/lib/wwmd/nokogiri_html2text.rb +41 -0
  17. data/lib/wwmd/page.rb +414 -0
  18. data/lib/wwmd/page/auth.rb +183 -0
  19. data/lib/wwmd/page/config.rb +44 -0
  20. data/lib/wwmd/page/constants.rb +60 -0
  21. data/lib/wwmd/page/headers.rb +107 -0
  22. data/lib/wwmd/page/inputs.rb +47 -0
  23. data/lib/wwmd/page/irb_helpers.rb +90 -0
  24. data/lib/wwmd/page/scrape.rb +202 -0
  25. data/lib/wwmd/page/spider.rb +127 -0
  26. data/lib/wwmd/page/urlparse.rb +79 -0
  27. data/lib/wwmd/page/utils.rb +30 -0
  28. data/lib/wwmd/viewstate.rb +118 -0
  29. data/lib/wwmd/viewstate/viewstate_class_helpers.rb +35 -0
  30. data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +213 -0
  31. data/lib/wwmd/viewstate/viewstate_from_xml.rb +126 -0
  32. data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
  33. data/lib/wwmd/viewstate/viewstate_utils.rb +157 -0
  34. data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
  35. data/lib/wwmd/viewstate/vs_array.rb +36 -0
  36. data/lib/wwmd/viewstate/vs_binary_serialized.rb +28 -0
  37. data/lib/wwmd/viewstate/vs_hashtable.rb +40 -0
  38. data/lib/wwmd/viewstate/vs_hybrid_dict.rb +40 -0
  39. data/lib/wwmd/viewstate/vs_indexed_string.rb +6 -0
  40. data/lib/wwmd/viewstate/vs_indexed_string_ref.rb +22 -0
  41. data/lib/wwmd/viewstate/vs_int_enum.rb +25 -0
  42. data/lib/wwmd/viewstate/vs_list.rb +32 -0
  43. data/lib/wwmd/viewstate/vs_pair.rb +27 -0
  44. data/lib/wwmd/viewstate/vs_read_types.rb +11 -0
  45. data/lib/wwmd/viewstate/vs_read_value.rb +33 -0
  46. data/lib/wwmd/viewstate/vs_sparse_array.rb +56 -0
  47. data/lib/wwmd/viewstate/vs_string.rb +29 -0
  48. data/lib/wwmd/viewstate/vs_string_array.rb +37 -0
  49. data/lib/wwmd/viewstate/vs_string_formatted.rb +30 -0
  50. data/lib/wwmd/viewstate/vs_triplet.rb +29 -0
  51. data/lib/wwmd/viewstate/vs_type.rb +21 -0
  52. data/lib/wwmd/viewstate/vs_unit.rb +28 -0
  53. data/lib/wwmd/viewstate/vs_value.rb +33 -0
  54. data/spec/README +3 -0
  55. data/spec/form_array.spec +49 -0
  56. data/spec/spider_csrf_test.spec +28 -0
  57. data/spec/urlparse_test.spec +89 -0
  58. data/tasks/ann.rake +80 -0
  59. data/tasks/bones.rake +20 -0
  60. data/tasks/gem.rake +201 -0
  61. data/tasks/git.rake +40 -0
  62. data/tasks/notes.rake +27 -0
  63. data/tasks/post_load.rake +34 -0
  64. data/tasks/rdoc.rake +51 -0
  65. data/tasks/rubyforge.rake +55 -0
  66. data/tasks/setup.rb +292 -0
  67. data/tasks/spec.rake +54 -0
  68. data/tasks/test.rake +40 -0
  69. data/tasks/zentest.rake +36 -0
  70. metadata +164 -0
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ == 0.2.9 / 2009-05-05
2
+
3
+ * bonesify
data/README ADDED
@@ -0,0 +1,62 @@
1
+
2
+ <;'"}()[]>{ XSSFish says, "Swim wif me"
3
+
4
+ == DESCRIPTION:
5
+
6
+ WWMD was originally intended to provide a console helper tool for
7
+ conducting web application security assessments (which is something I
8
+ find myself doing alot of). I've spent alot of time and had alot of
9
+ success writing application specific fuzzers + scrapers to test with.
10
+ WWMD provides a base of useful code to help you work with web sites both
11
+ in IRB and by writing scripts that can be as generic or as application
12
+ specific as you choose.
13
+
14
+ There's alot of helpful stuff crammed in here and its usage has evolved
15
+ alot. It's not intended to replace, remove or be better than any of the
16
+ tools you currently use. In fact, WWMD works best *with* the tools you
17
+ currently use to get stuff done. You get convenience methods for
18
+ getting, scraping, spidering, decoding, decrypting and munging user
19
+ inputs, pages and web applications.
20
+
21
+ It doesn't try to be smart. That's up to you.
22
+
23
+ What's here is the basic framework for getting started. There's a raft
24
+ of cookbook scripts and examples that are coming soon so make sure you
25
+ check the wiki regularly.
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * rubygems
30
+ * ruby-debug
31
+ * curb
32
+ * nokogiri
33
+ * hpricot (for the time being)
34
+ * htmlentities
35
+
36
+ == LICENSE:
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) 2008
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60
+
61
+ ## Blah blah blah
62
+
data/README.txt ADDED
@@ -0,0 +1,62 @@
1
+
2
+ <;'"}()[]>{ XSSFish says, "Swim wif me"
3
+
4
+ == DESCRIPTION:
5
+
6
+ WWMD was originally intended to provide a console helper tool for
7
+ conducting web application security assessments (which is something I
8
+ find myself doing alot of). I've spent alot of time and had alot of
9
+ success writing application specific fuzzers + scrapers to test with.
10
+ WWMD provides a base of useful code to help you work with web sites both
11
+ in IRB and by writing scripts that can be as generic or as application
12
+ specific as you choose.
13
+
14
+ There's alot of helpful stuff crammed in here and its usage has evolved
15
+ alot. It's not intended to replace, remove or be better than any of the
16
+ tools you currently use. In fact, WWMD works best *with* the tools you
17
+ currently use to get stuff done. You get convenience methods for
18
+ getting, scraping, spidering, decoding, decrypting and munging user
19
+ inputs, pages and web applications.
20
+
21
+ It doesn't try to be smart. That's up to you.
22
+
23
+ What's here is the basic framework for getting started. There's a raft
24
+ of cookbook scripts and examples that are coming soon so make sure you
25
+ check the wiki regularly.
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * rubygems
30
+ * ruby-debug
31
+ * curb
32
+ * nokogiri
33
+ * hpricot (for the time being)
34
+ * htmlentities
35
+
36
+ == LICENSE:
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) 2008
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
60
+
61
+ ## Blah blah blah
62
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ begin
6
+ require 'bones'
7
+ Bones.setup
8
+ rescue LoadError
9
+ begin
10
+ load 'tasks/setup.rb'
11
+ rescue LoadError
12
+ raise RuntimeError, '### please install the "bones" gem ###'
13
+ end
14
+ end
15
+
16
+ ensure_in_path 'lib'
17
+ require 'wwmd'
18
+
19
+ task :default => 'spec:run'
20
+
21
+ PROJ.name = 'wwmd'
22
+ PROJ.authors = 'Michael L. Tracy'
23
+ PROJ.email = 'mtracy@matasano.com'
24
+ PROJ.url = 'http://github.com/miketracy/wwmd/tree/master'
25
+ PROJ.version = WWMD::VERSION
26
+ #PROJ.rubyforge.name = 'wwmd'
27
+
28
+ PROJ.spec.opts << '--color'
29
+
30
+ depend_on 'ruby-debug'
31
+ depend_on 'curb'
32
+ depend_on 'nokogiri'
33
+
34
+ # EOF
@@ -0,0 +1,24 @@
1
+ #---
2
+ :base_url: "http://www.example.com"
3
+ :header_file: "./HEADERS.default" # argv
4
+ :username: "username" # argv
5
+ :password: "password" # argv
6
+
7
+ # opts for spider (only spider local urls)
8
+ :spider_local_only: true
9
+
10
+ # opts for curl object
11
+ # set max_redirects and follow_location (follows 302s)
12
+ :follow_location: true
13
+ :max_redirects: 20
14
+
15
+ # --use_proxy=host:port overrides both of these settings
16
+ # to use a proxy (I use burp and so should you)
17
+ :use_proxy: false
18
+ :proxy_url: "localhost:8080"
19
+
20
+ # cookies (where are we going to save our cookies?)
21
+ :enable_cookies: true
22
+ :cookiejar: "./__cookiejar"
23
+
24
+ #+++
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'wwmd'
4
+ include WWMD
5
+
6
+ $stop = lambda { Debugger.breakpoint; Debugger.catchpoint }
7
+
8
+ module WWMD
9
+ class Page
10
+ # here we add directly to Page.login instead of creating an outside
11
+ # helper class. Normally we create a mixin script for this.
12
+ def login
13
+ self.get(self.opts[:base_url]) ;# GET the main page redirects to /login
14
+ form = self.get_form ;# get the login form
15
+ if form.nil? then ;# did we actually get a form?
16
+ puts "WARN: No login form on base page"
17
+ return (self.logged_in = false)
18
+ end
19
+ form.set("name",self.opts[:username]) ;# set login form variables from config
20
+ form.set("password",self.opts[:password])
21
+ self.url = self.action ;# set the url to submit to to the form action
22
+ self.submit(form) ;# submit the form
23
+
24
+ # perform some check to make sure we aren't still on the login page
25
+ # (this naively checks to make sure we don't have any password fields on the current page
26
+ self.logged_in = (self.search("//input[@type='password']").size == 0)
27
+ end
28
+ end
29
+ end
30
+
31
+ # parse options and load configuration file
32
+ inopts = WWMDConfig.parse_opts(ARGV)
33
+ conf = ARGV[0] || "./config_example.yaml"
34
+ opts = WWMDConfig.load_config(conf)
35
+ inopts.each_pair { |k,v| opts[k] = v }
36
+ $opts = opts
37
+
38
+ # create our Page object and name it page
39
+ page = Page.new(opts)
40
+ page.scrape.warn = false ;# don't complain about not overwriting scrape
41
+
42
+ # move our spider object up here
43
+ spider = page.spider
44
+
45
+ # output current configuration
46
+ puts "current configuration:\n"
47
+ page.opts.each_pair { |k,v|
48
+ if k == :password then
49
+ puts "#{k} :: ********"
50
+ else
51
+ puts "#{k} :: #{v}"
52
+ end
53
+ }
54
+ puts "\n"
55
+
56
+ # use the Helper method to login to the application
57
+ if page.opts[:use_auth] then
58
+ page.login
59
+ if page.logged_in? then
60
+ puts "logged in as #{opts[:username]}"
61
+ else
62
+ puts "WARN: could not log in" if !page.logged_in?
63
+ end
64
+ else
65
+ page.get opts[:base_url]
66
+ end
67
+
68
+ # report our current location and let's drop to irb with
69
+ # our whole context complete
70
+ puts "current location: #{page.current}"
71
+ puts "enter \"irb\" to go to the console"
72
+
73
+ $stop.call
data/lib/wwmd.rb ADDED
@@ -0,0 +1,78 @@
1
+ # third-party
2
+ require 'rubygems'
3
+ require 'ruby-debug'
4
+ require 'curb'
5
+ require 'yaml'
6
+ require 'fileutils'
7
+ require 'base64'
8
+ require 'optparse'
9
+ require 'digest'
10
+ require 'uri'
11
+ require 'htmlentities'
12
+ require 'nkf'
13
+ require 'rexml/document'
14
+
15
+ module WWMD
16
+
17
+ # :stopdoc:
18
+ VERSION = "0.2.11"
19
+ PARSER = :nokogiri # :nokogiri || :hpricot
20
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
21
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
22
+ # :startdoc:
23
+
24
+ # Returns the version string for the library.
25
+ #
26
+ def self.version
27
+ VERSION
28
+ end
29
+
30
+ # Returns the library path for the module. If any arguments are given,
31
+ # they will be joined to the end of the libray path using
32
+ # <tt>File.join</tt>.
33
+ #
34
+ def self.libpath( *args )
35
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
36
+ end
37
+
38
+ # Returns the lpath for the module. If any arguments are given,
39
+ # they will be joined to the end of the path using
40
+ # <tt>File.join</tt>.
41
+ #
42
+ def self.path( *args )
43
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
44
+ end
45
+
46
+ # Utility method used to require all files ending in .rb that lie in the
47
+ # directory below this file that has the same name as the filename passed
48
+ # in. Optionally, a specific _directory_ name can be passed in such that
49
+ # the _filename_ does not have to be equivalent to the directory.
50
+ #
51
+ def self.require_all_libs_relative_to( fname, dir = nil )
52
+ dir ||= ::File.basename(fname, '.*')
53
+ search_me = ::File.expand_path(
54
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
55
+
56
+ Dir.glob(search_me).sort.each do |rb|
57
+ next if rb =~ /_html2text/
58
+ require rb
59
+ end
60
+ end
61
+
62
+ end # module WWMD
63
+
64
+ WWMD.require_all_libs_relative_to(__FILE__)
65
+
66
+ # special case parser
67
+
68
+ if WWMD::PARSER == :nokogiri
69
+ require 'nokogiri'
70
+ WWMD::HDOC = Nokogiri::HTML
71
+ require 'wwmd/nokogiri_html2text'
72
+ else
73
+ require 'hpricot'
74
+ WWMD::HDOC = Hpricot
75
+ require 'wwmd/hpricot_html2text'
76
+ end
77
+
78
+ # EOF
@@ -0,0 +1,40 @@
1
+ =begin rdoc
2
+ Place methods to character encodings here
3
+ =end
4
+
5
+ module WWMD
6
+ # This is where character encodings should go as singletons
7
+ # to be used as mixins for the String class
8
+ class Encoding
9
+
10
+ # Helper for String.to_utf7 mixin
11
+ # (complete hack but it works)
12
+ #
13
+ # if all=true, encode all characters.
14
+ # if all.class=Regexp encode only characters in the passed
15
+ # regular expression else default to /[^0-9a-zA-Z]/
16
+ #
17
+ # used by:
18
+ # String.to_utf7
19
+ # String.to_utf7!
20
+ def self.to_utf7(str,all=nil)
21
+ if all.kind_of?(Regexp)
22
+ reg = all
23
+ elsif all.kind_of?(TrueClass)
24
+ reg = ESCAPE[:all]
25
+ else
26
+ reg = ESCAPE[:nalnum] || /[^a-zA-Z0-9]/
27
+ end
28
+ puts reg.inspect
29
+ ret = ''
30
+ str.each_byte do |b|
31
+ if b.chr.match(reg)
32
+ ret += "+" + Base64.encode64(b.chr.toutf16)[0..2] + "-"
33
+ else
34
+ ret += b.chr
35
+ end
36
+ end
37
+ return ret
38
+ end
39
+ end
40
+ end
data/lib/wwmd/form.rb ADDED
@@ -0,0 +1,110 @@
1
+ =begin rdoc
2
+ =end
3
+ module WWMD
4
+ # == original author of hpricot_form
5
+ #
6
+ # Chew Choon Keat <choonkeat at gmail>
7
+ # http://blog.yanime.org/
8
+ # 19 July 2006
9
+ #
10
+ # updated by mtracy at matasano.com for use with Nokogiri and WWMD
11
+ #
12
+ class Form
13
+ attr_accessor :hdoc
14
+ attr_accessor :fields
15
+ attr_accessor :formtag
16
+
17
+ def initialize(doc)
18
+ @hdoc = doc
19
+ @formtag = @hdoc.search("//form")
20
+ end
21
+
22
+ def method_missing(*args)
23
+ hdoc.send(*args)
24
+ end
25
+
26
+ alias_method :old_fields, :fields
27
+ def fields
28
+ if PARSER == :nokogiri
29
+ @fields ||= (hdoc.search(".//input[@name]",".//select[@name]",".//textarea")).map { |x| Field.new(x) }
30
+ else
31
+ @fields ||= (hdoc.search("//input[@name]") + hdoc.search("//select[@name]") + hdoc.search("//textarea")).map { |x| Field.new(x) }
32
+ end
33
+ end
34
+
35
+ def field_names
36
+ fields.map { |x| x.get_attribute("name") }
37
+ end
38
+
39
+ def action
40
+ return self.get_attribute("action")
41
+ end
42
+
43
+ def report
44
+ puts "action = #{self.action}"
45
+ self.fields.each { |field| puts field.to_text }
46
+ return nil
47
+ end
48
+
49
+ alias_method :show, :report
50
+
51
+ def to_form_array
52
+ FormArray.new(self.fields)
53
+ end
54
+
55
+ def to_array
56
+ self.to_form_array
57
+ end
58
+ end
59
+
60
+ class Field < Form
61
+ def value
62
+ self._value.nil? ? self.get_attribute("value") : self._value
63
+ end
64
+
65
+ alias_method :get_value, :value #:nodoc:
66
+ alias_method :fvalue, :value #:nodoc:
67
+
68
+ def fname
69
+ self.get_attribute('name')
70
+ end
71
+
72
+ def ftype
73
+ self.get_attribute('type')
74
+ end
75
+
76
+ def _value
77
+ # selection (array)
78
+ if PARSER == :nokogiri
79
+ ret = hdoc.search(".//option[@selected]").collect { |x| x.get_attribute("value") }
80
+ else
81
+ ret = hdoc.search("//option[@selected]").collect { |x| x.get_attribute("value") }
82
+ end
83
+ case ret.size
84
+ when 0
85
+ if name == "textarea"
86
+ if PARSER == :nokogiri
87
+ hdoc.text
88
+ else
89
+ hdoc.innerHTML
90
+ end
91
+ else
92
+ hdoc.get_attribute("value") if (hdoc.get_attribute("checked") || !hdoc.get_attribute("type") =~ /radio|checkbox/)
93
+ end
94
+ when 1
95
+ ret.first
96
+ else
97
+ ret
98
+ end
99
+ end
100
+
101
+ def to_arr
102
+ return [self.name, self.ftype, self.fname, self.fvalue]
103
+ end
104
+
105
+ def to_text
106
+ return "tag=#{self.name} type=#{self.ftype} name=#{self.fname} value=#{self.fvalue}"
107
+ end
108
+
109
+ end
110
+ end