casper-proxy 1.0.0
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.
- data/.gitignore +5 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/casper +39 -0
- data/casper.gemspec +24 -0
- data/lib/casper.rb +67 -0
- data/lib/casper/version.rb +16 -0
- data/spec/spec_helper.rb +1 -0
- metadata +97 -0
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3@casper
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Casper
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
casper is a transparent proxy designed to be used during a web application
|
6
|
+
penetration test during a manual target link discovery step.
|
7
|
+
|
8
|
+
Instead of just fireup a crawler, with casper you can have the link visited
|
9
|
+
during a normal user session.
|
10
|
+
|
11
|
+
This is ideal to understand the logic sequence steps and what's happening
|
12
|
+
behind the woods.
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Running casper it is very easy:
|
17
|
+
|
18
|
+
```
|
19
|
+
$ casper
|
20
|
+
|
21
|
+
[2012-06-27 08:52:47] INFO WEBrick 1.3.1
|
22
|
+
[2012-06-27 08:52:47] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin11.4.0]
|
23
|
+
[2012-06-27 08:52:47] INFO Casper::Proxy#start: pid=24323 port=8080
|
24
|
+
```
|
25
|
+
|
26
|
+
Now you can configure your browser to use http://localhost:8080 as proxy server
|
27
|
+
and watching all requests reaching the target.
|
28
|
+
|
29
|
+
If you don't want to be bothered by too much noise on screen, you can ask
|
30
|
+
casper only to trace requests for the url you're interested to:
|
31
|
+
|
32
|
+
```
|
33
|
+
$ casper -T theapptotest.com
|
34
|
+
```
|
35
|
+
|
36
|
+
## Talking to the proxy server
|
37
|
+
|
38
|
+
casper is configured to handle some signals and react accordingly:
|
39
|
+
|
40
|
+
* SIGINT: shutdown the server
|
41
|
+
* SIGINFO: the server will put an informational string about how many requests were collected and how many unique hosts were discovered
|
42
|
+
* SIGUSR1: the server will dump all the hosts you're browser communicated with
|
43
|
+
* SIGUSR2: the server will dump all logged urls
|
data/Rakefile
ADDED
data/bin/casper
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "casper"
|
3
|
+
require 'getoptlong'
|
4
|
+
|
5
|
+
opts = GetoptLong.new(
|
6
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
7
|
+
[ '--version', '-v', GetoptLong::NO_ARGUMENT ],
|
8
|
+
[ '--trace', '-T', GetoptLong::REQUIRED_ARGUMENT],
|
9
|
+
[ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ]
|
10
|
+
)
|
11
|
+
|
12
|
+
options = {:trace=>nil, :Port=>nil}
|
13
|
+
opts.each do |opt, arg|
|
14
|
+
case opt
|
15
|
+
when '--help'
|
16
|
+
puts "casper - HTTP transparent proxy v#{Casper::Version.version}"
|
17
|
+
printf "usage: casper [arguments]\n"
|
18
|
+
printf "\n\t-T domain: log all requests make to the domain specified as argument discarding other\n"
|
19
|
+
printf "\t-p port: bind the proxy at the specified port number\n"
|
20
|
+
printf "\t-h: show this help\n"
|
21
|
+
printf "\t-v: show casper version\n"
|
22
|
+
exit 0
|
23
|
+
when '--version'
|
24
|
+
puts "#{Casper::Version.version}"
|
25
|
+
exit 0
|
26
|
+
when '--trace'
|
27
|
+
options[:trace] = arg
|
28
|
+
when '--port'
|
29
|
+
options[:Port] = arg
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
server = Casper::Proxy.new(options)
|
35
|
+
trap("INT") { server.shutdown }
|
36
|
+
trap("INFO") { server.info }
|
37
|
+
trap("USR1") { server.dump }
|
38
|
+
trap("USR2") { server.get_urls }
|
39
|
+
server.start
|
data/casper.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "casper/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "casper-proxy"
|
7
|
+
s.version = Casper::Version.version
|
8
|
+
s.authors = ["Paolo Perego"]
|
9
|
+
s.email = ["thesp0nge@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A transparent HTTP proxy useful in the preliminary recognize step for a web application security assessment}
|
12
|
+
s.description = %q{A transparent HTTP proxy useful in the preliminary recognize step for a web application security assessment}
|
13
|
+
|
14
|
+
s.rubyforge_project = "casper"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
|
24
|
+
end
|
data/lib/casper.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "webrick"
|
2
|
+
require "webrick/httpproxy"
|
3
|
+
require "casper/version"
|
4
|
+
|
5
|
+
module Casper
|
6
|
+
class Proxy < WEBrick::HTTPProxyServer
|
7
|
+
attr_reader :req_count
|
8
|
+
attr_reader :hosts
|
9
|
+
|
10
|
+
def initialize(config={})
|
11
|
+
@req_count = 0
|
12
|
+
@hosts=[]
|
13
|
+
@urls=[]
|
14
|
+
@trace_domain = ""
|
15
|
+
@trace_domain = config[:trace] if config[:trace] and ! config[:trace].empty?
|
16
|
+
|
17
|
+
config[:Port] = 8080 if ! config[:Port]
|
18
|
+
config[:AccessLog] = []
|
19
|
+
config[:ProxyContentHandler] = Proc.new do |req, res|
|
20
|
+
log_requests(req, res)
|
21
|
+
end
|
22
|
+
|
23
|
+
super(config)
|
24
|
+
end
|
25
|
+
|
26
|
+
def info
|
27
|
+
$stdout.puts "[#{Time.now}] INFO #{@req_count} requests to #{@hosts.count} unique hosts"
|
28
|
+
end
|
29
|
+
|
30
|
+
def dump
|
31
|
+
$stdout.puts "Hosts we communicate with "
|
32
|
+
if (@hosts.count == 0)
|
33
|
+
$stdout.puts "None\n"
|
34
|
+
|
35
|
+
else
|
36
|
+
@hosts.each do |h|
|
37
|
+
$stdout.puts " >>> #{h}\n"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_urls
|
43
|
+
@urls.each do |u|
|
44
|
+
$stdout.puts "#{u}\n"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def log_requests(req, res)
|
50
|
+
if (@trace_domain == "") or ( ! req.request_line.index(@trace_domain).nil?)
|
51
|
+
$stdout.puts "[#{Time.now}] #{req.request_line.chomp} => #{res.status}\n"
|
52
|
+
$stdout.puts "---> #{req.body} #{req.request_method}" if req.request_method == "POST"
|
53
|
+
if @urls.index(req.request_line.chomp).nil?
|
54
|
+
@urls << req.request_line.chomp
|
55
|
+
end
|
56
|
+
if @hosts.index(req.host).nil?
|
57
|
+
@hosts << req.host
|
58
|
+
end
|
59
|
+
inc_req_count
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def inc_req_count
|
64
|
+
@req_count += 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Casper
|
2
|
+
module Version
|
3
|
+
MAJOR = 1
|
4
|
+
MINOR = 0
|
5
|
+
PATCH = 0
|
6
|
+
BUILD = ''
|
7
|
+
|
8
|
+
def self.version
|
9
|
+
if BUILD.empty?
|
10
|
+
return [MAJOR, MINOR, PATCH].compact.join('.')
|
11
|
+
else
|
12
|
+
return [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'casper'
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: casper-proxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paolo Perego
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: A transparent HTTP proxy useful in the preliminary recognize step for
|
47
|
+
a web application security assessment
|
48
|
+
email:
|
49
|
+
- thesp0nge@gmail.com
|
50
|
+
executables:
|
51
|
+
- casper
|
52
|
+
extensions: []
|
53
|
+
extra_rdoc_files: []
|
54
|
+
files:
|
55
|
+
- .gitignore
|
56
|
+
- .rvmrc
|
57
|
+
- Gemfile
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- bin/casper
|
61
|
+
- casper.gemspec
|
62
|
+
- lib/casper.rb
|
63
|
+
- lib/casper/version.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
homepage: ''
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
hash: -379329322285311904
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
hash: -379329322285311904
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project: casper
|
91
|
+
rubygems_version: 1.8.24
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: A transparent HTTP proxy useful in the preliminary recognize step for a web
|
95
|
+
application security assessment
|
96
|
+
test_files:
|
97
|
+
- spec/spec_helper.rb
|