wwmd 0.2.20.3

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 (80) hide show
  1. data/History.txt +38 -0
  2. data/README.rdoc +87 -0
  3. data/Rakefile +33 -0
  4. data/examples/config_example.yaml +24 -0
  5. data/examples/wwmd_example.rb +73 -0
  6. data/lib/wwmd.rb +84 -0
  7. data/lib/wwmd/class_extensions.rb +4 -0
  8. data/lib/wwmd/class_extensions/extensions_base.rb +251 -0
  9. data/lib/wwmd/class_extensions/extensions_encoding.rb +79 -0
  10. data/lib/wwmd/class_extensions/extensions_external.rb +18 -0
  11. data/lib/wwmd/class_extensions/extensions_nilclass.rb +11 -0
  12. data/lib/wwmd/class_extensions/extensions_rbkb.rb +193 -0
  13. data/lib/wwmd/class_extensions/mixins_string_encoding.rb +40 -0
  14. data/lib/wwmd/guid.rb +155 -0
  15. data/lib/wwmd/page.rb +3 -0
  16. data/lib/wwmd/page/_fa.old +302 -0
  17. data/lib/wwmd/page/auth.rb +17 -0
  18. data/lib/wwmd/page/constants.rb +63 -0
  19. data/lib/wwmd/page/form.rb +99 -0
  20. data/lib/wwmd/page/form_array.rb +304 -0
  21. data/lib/wwmd/page/headers.rb +118 -0
  22. data/lib/wwmd/page/helpers.rb +41 -0
  23. data/lib/wwmd/page/html2text_hpricot.rb +76 -0
  24. data/lib/wwmd/page/html2text_nokogiri.rb +42 -0
  25. data/lib/wwmd/page/inputs.rb +47 -0
  26. data/lib/wwmd/page/irb_helpers.rb +114 -0
  27. data/lib/wwmd/page/page.rb +257 -0
  28. data/lib/wwmd/page/parsing_convenience.rb +98 -0
  29. data/lib/wwmd/page/reporting_helpers.rb +89 -0
  30. data/lib/wwmd/page/scrape.rb +196 -0
  31. data/lib/wwmd/page/spider.rb +127 -0
  32. data/lib/wwmd/urlparse.rb +125 -0
  33. data/lib/wwmd/viewstate.rb +17 -0
  34. data/lib/wwmd/viewstate/viewstate.rb +101 -0
  35. data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +217 -0
  36. data/lib/wwmd/viewstate/viewstate_from_xml.rb +129 -0
  37. data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
  38. data/lib/wwmd/viewstate/viewstate_utils.rb +164 -0
  39. data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
  40. data/lib/wwmd/viewstate/vs_stubs.rb +22 -0
  41. data/lib/wwmd/viewstate/vs_stubs/vs_array.rb +38 -0
  42. data/lib/wwmd/viewstate/vs_stubs/vs_binary_serialized.rb +30 -0
  43. data/lib/wwmd/viewstate/vs_stubs/vs_hashtable.rb +42 -0
  44. data/lib/wwmd/viewstate/vs_stubs/vs_hybrid_dict.rb +42 -0
  45. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string.rb +6 -0
  46. data/lib/wwmd/viewstate/vs_stubs/vs_indexed_string_ref.rb +24 -0
  47. data/lib/wwmd/viewstate/vs_stubs/vs_int_enum.rb +27 -0
  48. data/lib/wwmd/viewstate/vs_stubs/vs_list.rb +34 -0
  49. data/lib/wwmd/viewstate/vs_stubs/vs_pair.rb +29 -0
  50. data/lib/wwmd/viewstate/vs_stubs/vs_read_types.rb +11 -0
  51. data/lib/wwmd/viewstate/vs_stubs/vs_read_value.rb +35 -0
  52. data/lib/wwmd/viewstate/vs_stubs/vs_sparse_array.rb +58 -0
  53. data/lib/wwmd/viewstate/vs_stubs/vs_string.rb +33 -0
  54. data/lib/wwmd/viewstate/vs_stubs/vs_string_array.rb +39 -0
  55. data/lib/wwmd/viewstate/vs_stubs/vs_string_formatted.rb +32 -0
  56. data/lib/wwmd/viewstate/vs_stubs/vs_stub_helpers.rb +37 -0
  57. data/lib/wwmd/viewstate/vs_stubs/vs_triplet.rb +31 -0
  58. data/lib/wwmd/viewstate/vs_stubs/vs_type.rb +23 -0
  59. data/lib/wwmd/viewstate/vs_stubs/vs_unit.rb +30 -0
  60. data/lib/wwmd/viewstate/vs_stubs/vs_value.rb +35 -0
  61. data/lib/wwmd/wwmd_config.rb +52 -0
  62. data/lib/wwmd/wwmd_puts.rb +9 -0
  63. data/lib/wwmd/wwmd_utils.rb +28 -0
  64. data/spec/README +3 -0
  65. data/spec/form_array.spec +49 -0
  66. data/spec/spider_csrf_test.spec +28 -0
  67. data/spec/urlparse_test.spec +101 -0
  68. data/tasks/ann.rake +80 -0
  69. data/tasks/bones.rake +20 -0
  70. data/tasks/gem.rake +201 -0
  71. data/tasks/git.rake +40 -0
  72. data/tasks/notes.rake +27 -0
  73. data/tasks/post_load.rake +34 -0
  74. data/tasks/rdoc.rake +51 -0
  75. data/tasks/rubyforge.rake +55 -0
  76. data/tasks/setup.rb +292 -0
  77. data/tasks/spec.rake +54 -0
  78. data/tasks/test.rake +40 -0
  79. data/tasks/zentest.rake +36 -0
  80. metadata +222 -0
@@ -0,0 +1,304 @@
1
+ =begin rdoc
2
+ This is a weird kind of data structure for no other reason than
3
+ I wanted to keep the form inputs in order when they come in.
4
+
5
+ Accessing this either as a hash or an array (but => won't work)
6
+
7
+ Some of the methods in here are kept for backward compat before the refactor
8
+ and now everything in this array should be accessed with []= and []
9
+
10
+ Set :action and take a block. Page#submit_form should take this and do the
11
+ right thing.
12
+ =end
13
+
14
+ module WWMD
15
+ class FormArray < Array
16
+ attr_accessor :action
17
+ attr_accessor :type
18
+ attr_accessor :delimiter
19
+ attr_accessor :equals
20
+
21
+ def initialize(fields=nil,action=nil,&block)
22
+ set_fields(fields)
23
+ @delimiter = "&"
24
+ @equals = "="
25
+ @action = action
26
+ instance_eval(&block) if block_given?
27
+ end
28
+
29
+ def set_fields(fields=nil)
30
+ return nil if fields.nil?
31
+ # this first one is an array of field objects
32
+ if fields.class == Array
33
+ fields.each do |f|
34
+ name = f['name']
35
+ if self.name_exists(name)
36
+ if f['type'] == "hidden"
37
+ self.set name,f.get_value
38
+ elsif f['type'] == "checkbox" and f.to_html.grep(/checked/) != ''
39
+ self[name] = f.get_value
40
+ end
41
+ else
42
+ self << [ f['name'],f.get_value ]
43
+ end
44
+ end
45
+ elsif fields.class == Hash
46
+ fields.each_pair { |k,v| self[k] = v }
47
+ elsif fields.class == String
48
+ fields.split(@delimiter).each do |f|
49
+ k,v = f.split(@equals,2)
50
+ self[k] = v
51
+ end
52
+ end
53
+ end
54
+
55
+ # "deep enough" copy of this object to make it a real copy
56
+ # instead of references to the arrays that already exist
57
+ def clone
58
+ ret = self.class.new
59
+ self.each { |r| ret << r.clone }
60
+ ret.action = self.action
61
+ return ret
62
+ end
63
+
64
+ def clear
65
+ self.delete_if { |x| true }
66
+ end
67
+
68
+ # check if the passed name exists in the form
69
+ def include?(key)
70
+ self.map { |x| x.first }.flatten.include?(key)
71
+ end
72
+
73
+ alias_method :name_exists, :include?#:nodoc:
74
+ alias_method :name_exists?, :include?#:nodoc:
75
+ alias_method :has_key?, :include?#:nodoc:
76
+
77
+ # add key/value pairs to form
78
+ def add(key,value)
79
+ self << [key,value]
80
+ end
81
+
82
+ # key = Fixnum set value at index key
83
+ # key = String find key named string and set value
84
+ def set_value!(key,value)
85
+ if key.class == Fixnum
86
+ self[key][1] = value
87
+ return [self[key][0], value]
88
+ end
89
+ self.each_index do |i|
90
+ if self[i][0] == key
91
+ self[i] = [key,value]
92
+ end
93
+ end
94
+ return [key,value]
95
+ end
96
+
97
+ # get a value using its index
98
+ # override Array#[]
99
+ alias_method :old_get, :[]#:nodoc:
100
+ def [](*args)
101
+ if args.first.class == Fixnum
102
+ self.old_get(args.first)
103
+ else
104
+ self.get_value(args.first)
105
+ end
106
+ end
107
+
108
+ alias_method :old_set, :[]=#:nodoc:
109
+ # set a key using its index, array key or add using a new key i.e.:
110
+ # if setting:
111
+ # form = [['key','value'],['foo','bar']]
112
+ # form[0] = ["replacekey","newalue"]
113
+ # form["replacekey"] = "newervalue"
114
+ # if adding:
115
+ # form["newkey"] = "value"
116
+ #
117
+ def []=(*args)
118
+ key,value = args
119
+ if args.first.kind_of?(Fixnum)
120
+ return self.old_set(*args)
121
+ elsif self.has_key?(key)
122
+ return self.set_value(key,value)
123
+ else
124
+ return self.add(key,value)
125
+ end
126
+ end
127
+
128
+ alias_method :set_value, :set_value!
129
+ alias_method :set, :set_value!
130
+
131
+ def get_value(key)
132
+ if key.class == Fixnum
133
+ return self[key][1]
134
+ end
135
+ self.each_index do |i|
136
+ if self[i][0] == key
137
+ return self[i][1]
138
+ end
139
+ end
140
+ return nil
141
+ end
142
+
143
+ alias_method :get, :get_value
144
+
145
+ def keys
146
+ self.map { |k,v| k }
147
+ end
148
+
149
+ def setall!(value)
150
+ self.each_index { |i| self.set_value!(i,value) }
151
+ end
152
+
153
+ alias_method :setall, :setall!#:nodoc:
154
+ alias_method :set_all!, :setall!#:nodoc:
155
+ alias_method :set_all, :setall!#:nodoc:
156
+
157
+ # delete all key = value pairs from self where key = key
158
+ def delete_key(key)
159
+ self.reject! { |x,y| x == key }
160
+ end
161
+
162
+ alias_method :delete_keys!, :delete_key #:nodoc:
163
+ alias_method :delete_key!, :delete_key #:nodoc:
164
+
165
+ # escape form keys in place
166
+ def escape_keys!(reg=WWMD::ESCAPE[:url])
167
+ return nil if reg == :none
168
+ self.map! { |x,y| [x.escape(reg),y] }
169
+ end
170
+
171
+ # unescape form keys in place
172
+ def unescape_keys!(reg=WWMD::ESCAPE[:url])
173
+ return nil if reg == :none
174
+ self.map! { |x,y| [x.unescape,y] }
175
+ end
176
+
177
+ # escape form values in place
178
+ def escape_all!(reg=WWMD::ESCAPE[:url])
179
+ return nil if reg == :none
180
+ self.map! { |x,y| [x,y.escape(reg)] }
181
+ end
182
+
183
+ alias_method :escape_all, :escape_all!#:nodoc:
184
+
185
+ # unescape all form values in place
186
+ def unescape_all!
187
+ self.map! { |x,y| [x,y.unescape] }
188
+ end
189
+
190
+ alias_method :unescape_all, :unescape_all!#:nodoc:
191
+
192
+ # remove form elements with null values
193
+ def remove_nulls!
194
+ self.delete_if { |x| x[1].to_s.empty? || x[1].nil? }
195
+ end
196
+
197
+ alias_method :squeeze!, :remove_nulls!
198
+
199
+ # remove form elements with null keys (for housekeeping returns)
200
+ def remove_null_keys!
201
+ self.delete_if { |x,y| x.to_s.empty? || x.nil? }
202
+ end
203
+
204
+ alias_method :squeeze_keys!, :remove_null_keys!
205
+
206
+ ## viewstate
207
+
208
+ # clear viewstate variables
209
+ def clear_viewstate
210
+ self.each { |k,v|
211
+ self[k] = "" if k =~ /^__/
212
+ }
213
+ end
214
+
215
+ # remove viewstate variables
216
+ def rm_viewstate
217
+ # my least favorite ruby idiom
218
+ self.replace(self.map { |k,v| [k,v] if not k =~ /^__/ }.reject { |x| x.nil? })
219
+ end
220
+
221
+ alias_method :extend!, :add #:nodoc (this is here for backward compat)
222
+
223
+ # add viewstate stuff
224
+ def add_viewstate#:nodoc:
225
+ self.insert(0,[ "__VIEWSTATE","" ])
226
+ self.insert(0,[ "__EVENTARGUMENT","" ])
227
+ self.insert(0,[ "__EVENTTARGET","" ])
228
+ self.insert(0,[ "__EVENTVALIDATION","" ])
229
+ return nil
230
+ end
231
+
232
+ ## conversions
233
+
234
+ # convert form into a post parameters string
235
+ def to_post
236
+ ret = []
237
+ self.each do |i|
238
+ ret << i.join(@equals)
239
+ end
240
+ ret.join(@delimiter)
241
+ end
242
+
243
+ # convert form into a get parameters string
244
+ #
245
+ # pass me a base to get a full url to pass to Page.get
246
+ def to_get(base="")
247
+ return base if self.empty?
248
+ ret = []
249
+ self.each do |i|
250
+ ret << i.join(@equals)
251
+ end
252
+ ret = ret.join(@delimiter)
253
+ return base.to_s.clip + "?" + ret.to_s
254
+ end
255
+
256
+ ## parsing convenience
257
+
258
+ # dump a web page containing a csrf example of the current FormArray
259
+ def to_csrf(quot=nil,action=nil,unescval=false)
260
+ quot = "'" unless quot
261
+ action = self.action unless action
262
+ ret = ""
263
+ ret << "<html><body>\n"
264
+ ret << "<form method=#{quot}post#{quot} id=#{quot}wwmdtest#{quot} name=#{quot}wwmdtest#{quot} action=#{quot}#{action}#{quot}>\n"
265
+ self.each do |key,val|
266
+ val.gsub!(/\+/," ")
267
+ val = val.unescape.gsub(/'/) { %q[\'] } if unescval
268
+ ret << "<input name=#{quot}#{key.to_s.unescape}#{quot} type=#{quot}hidden#{quot} value=#{quot}#{val.to_s.unescape}#{quot} />\n"
269
+ end
270
+ ret << "</form>\n"
271
+ ret << "<script>document.wwmdtest.submit()</script>\n"
272
+ ret << "</body></html>\n"
273
+ return ret
274
+ end
275
+
276
+ # add markers for burp intruder to form
277
+ def burpify(all=true) #:nodoc:
278
+ ret = self.clone
279
+ ret.each_index do |i|
280
+ next if ret[i][0] =~ /^__/
281
+ # ret.set_value!(i,"#{ret.get_value(i)}" + "\302\247" + "\302\247")
282
+ if all
283
+ ret.set_value!(i,"\244" + "#{ret.get_value(i)}" + "\244")
284
+ else
285
+ ret.set_value!(i,"#{ret.get_value(i)}" + "\244" + "\244")
286
+ end
287
+ end
288
+ ret.to_post.pbcopy
289
+ return ret
290
+ end
291
+
292
+ # return md5 hash of sorted list of keys
293
+ def fingerprint
294
+ return (self.action.to_s + self.map { |k,v| k }.sort.to_s).md5
295
+ end
296
+ alias_method :fp, :fingerprint #:nodoc:
297
+
298
+ def from_array(arr)
299
+ self.clear
300
+ arr.each { |k,v| self[k] = v }
301
+ end
302
+
303
+ end
304
+ end
@@ -0,0 +1,118 @@
1
+ module WWMD
2
+ class Page
3
+
4
+ #:section: Header helper methods
5
+
6
+ def user_agent=(ua)
7
+ self.headers["User-Agent"] = ua
8
+ end
9
+
10
+ # clear header at <key>
11
+ def clear_header(key)
12
+ self.headers.delete_if { |k,v| k.upcase == key.upcase }
13
+ return nil
14
+ end
15
+
16
+ alias_method :delete_header, :clear_header#:nodoc:
17
+
18
+ # clear all headers
19
+ def clear_headers
20
+ self.headers.delete_if { |k,v| true }
21
+ "headers cleared"
22
+ end
23
+
24
+ # set headers from passed argument
25
+ # Nil: set headers from WWMD::DEFAULT_HEADERS
26
+ # Symbol: entry in WWMD::HEADERS to set from
27
+ # Hash: hash to set headers from
28
+ # String: filename (NOT IMPLEMENTED)
29
+ #
30
+ # if clear == true then headers will be cleared before setting
31
+ def set_headers(arg=nil,clear=false)
32
+ clear_headers if clear
33
+ if arg.nil?
34
+ begin
35
+ clear_headers
36
+ WWMD::DEFAULT_HEADERS.each { |k,v| self.headers[k] = v }
37
+ return "headers set from default"
38
+ rescue => e
39
+ putw "WARN: " + e
40
+ return false
41
+ end
42
+ elsif arg.class == Symbol
43
+ set_headers(WWMD::HEADERS[arg])
44
+ putw "headers set from #{arg}"
45
+ return true
46
+ elsif arg.class == Hash
47
+ arg.each { |k,v| self.headers[k] = v }
48
+ putw "headers set from hash"
49
+ return true
50
+ end
51
+ putw "error setting headers"
52
+ return false
53
+ end
54
+
55
+ # set headers back to default headers
56
+ def default_headers(arg=nil)
57
+ set_headers
58
+ end
59
+
60
+ alias_method :set_default, :default_headers
61
+
62
+ # set headers from text
63
+ def headers_from_array(arr)
64
+ clear_headers
65
+ arr = arr.split("\r\n\r\n").first if arr.class == String
66
+ arr.each do |line|
67
+ next if (line.empty? || line =~ /^(GET|POST)/)
68
+ k,v = line.split(":",2)
69
+ self.headers[k.strip] = v.strip
70
+ end
71
+ nil
72
+ end
73
+ #;
74
+
75
+ # set headers from paste
76
+ def headers_from_paste
77
+ headers_from_array(%x[pbpaste])
78
+ end
79
+
80
+ # set headers from file
81
+ def headers_from_file(fn)
82
+ clear_headers
83
+ headers_from_array(File.read(fn).split("\n"))
84
+ return "headers set from #{fn}"
85
+ end
86
+
87
+ # set headers to utf7 encoding post
88
+ def set_utf7_headers
89
+ self.headers["Content-Type"] = "application/x-www-form-urlencoded;charset=UTF-7"
90
+ return "headers set to utf7"
91
+ end
92
+
93
+ # set headers to ajax
94
+ def set_ajax_headers
95
+ self.headers["X-Requested-With"] = "XMLHttpRequest"
96
+ self.headers["X-Prototype-Version"] = "1.5.0"
97
+ return "headers set to ajax"
98
+ end
99
+
100
+ # set headers to SOAP request headers
101
+ def set_soap_headers
102
+ self.headers['Content-Type'] = "text/xml;charset=utf-8"
103
+ self.headers['SOAPAction'] = "\"\""
104
+ return "headers set to soap"
105
+ end
106
+
107
+ # get the current Cookie header
108
+ def get_cookie
109
+ self.headers["Cookie"]
110
+ end
111
+
112
+ # set the Cookie header
113
+ def set_cookie(cookie=nil)
114
+ self.headers["Cookie"] = cookie
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,41 @@
1
+ module WWMD
2
+ class Page
3
+ # copy and paste from burp request windows
4
+ # page object gets set with headers and url (not correct)
5
+ # returns [headers,form]
6
+ # form = page.from_paste
7
+
8
+ def from_input(req)
9
+ self.enable_cookies = false
10
+ return false if not req
11
+ h,b = req.chomp.split("\r\n\r\n",2)
12
+ oh = h
13
+ h = h.split("\r\n")
14
+ m,u,p = h.shift.split(" ")
15
+ return nil unless m =~ (/^(POST|GET)/)
16
+ self.url = self.base_url + u
17
+ self.headers_from_array(h)
18
+ self.body_data = b
19
+ self.set_data
20
+ form = b.to_form
21
+ form.action = @urlparse.parse(self.base_url, u).to_s
22
+ [oh,form]
23
+ end
24
+
25
+ def from_file(fn)
26
+ h = headers.clone
27
+ ret = from_input(File.read(fn))
28
+ headers.replace(h)
29
+ ret
30
+ end
31
+
32
+ def from_paste
33
+ from_input(%x[pbpaste])
34
+ end
35
+
36
+ def resp_paste
37
+ self.body_data = %x[pbpaste].split("\r\n\r\n",2)[1]
38
+ self.set_data
39
+ end
40
+ end
41
+ end