codesake 0.0.1 → 0.15.1

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.
@@ -1,3 +1,4 @@
1
1
  module Codesake
2
- VERSION = "0.0.1"
2
+ VERSION = "0.15.1"
3
+ CODENAME = "BluePint"
3
4
  end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe "codesake command line interface" do
4
+ before(:all) do
5
+ @cli = Codesake::Cli.new
6
+ end
7
+ it "has a parse method" do
8
+ @cli.should respond_to(:parse)
9
+ end
10
+
11
+ it "returns an empty has if no command line is given" do
12
+ @cli.parse(nil).should == {:vulnerabilities=>:all}
13
+ @cli.parse("").should == {:vulnerabilities=>:all}
14
+ end
15
+
16
+
17
+ it "understands --version flag" do
18
+ @cli.parse("--version").should == {:version=>true, :vulnerabilities=>:all}
19
+ end
20
+ it "understands --output flag" do
21
+ @cli.parse("-o file").should == {:output=>:file, :vulnerabilities=>:all}
22
+ @cli.parse("-o json").should == {:output=>:json, :vulnerabilities=>:all}
23
+ @cli.parse("-o db").should == {:output=>:db, :vulnerabilities=>:all}
24
+
25
+ end
26
+ it "understands --verbose flag" do
27
+ @cli.parse("--verbose").should == {:verbose=>true, :vulnerabilities=>:all}
28
+ @cli.parse("-V").should == {:verbose=>true, :vulnerabilities=>:all}
29
+ end
30
+
31
+ it "saves targets" do
32
+ @cli.parse("file1")
33
+ @cli.targets.should == [{:target=>"file1", :valid=>false}]
34
+ @cli.parse("file1 file2")
35
+ @cli.targets.should == [{:target=>"file1", :valid=>false}, {:target=>"file2", :valid=>false}]
36
+ @cli.parse("Gemfile")
37
+ @cli.targets.should == [{:target=>"Gemfile", :valid=>true}]
38
+ end
39
+
40
+ it "the target should be either a file or a directory" do
41
+ @cli.is_good_target?("Gemfile").should be_true
42
+ @cli.is_good_target?("file1").should be_false
43
+ end
44
+ it "must produce a non nil option Hash" do
45
+ @cli.parse("").should_not be_nil
46
+ @cli.parse("-nonsense").should_not be_nil
47
+ @cli.parse("-v -h").should_not be_nil
48
+ @cli.parse("-j drift").should_not be_nil
49
+ end
50
+
51
+ it "understand --keys flag" do
52
+ ret = {:keywords => ["a","b","c"], :vulnerabilities=>:all}
53
+ @cli.parse("-k a,b,c").should == ret
54
+ end
55
+
56
+ it "understand --all-vulnerabilities" do
57
+ ret = {:vulnerabilities=>:all}
58
+ @cli.parse("-A").should == ret
59
+ end
60
+ it "understand --confirmed-vulnerabilities" do
61
+ ret = {:vulnerabilities=>:confirmed}
62
+ @cli.parse("-C").should == ret
63
+ end
64
+
65
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ dummy_text = <<EOT
4
+ This is a text
5
+ This is a text
6
+ This is a text
7
+ This is a text
8
+ secret
9
+ This is a text
10
+ This is a text
11
+ This is a text
12
+ EOT
13
+
14
+ class Test
15
+ include Codesake::Utils::Files
16
+ include Codesake::Engine::Core
17
+ end
18
+
19
+ shared_examples_for Codesake::Engine::Core do
20
+ before(:all) do
21
+ @mock = Test.new
22
+ File.open("test_secrets.txt", "w") do |f|
23
+ f.puts(dummy_text)
24
+ end
25
+
26
+ @mock.filename="test_secrets.txt"
27
+ @mock.read_file
28
+
29
+ end
30
+
31
+ after(:all) do
32
+ File.delete("test_secrets.txt")
33
+ end
34
+
35
+ it "provide an analyse method" do
36
+ @mock.should respond_to(:analyse)
37
+ end
38
+
39
+ context "has an analyse method returning an empty array if the input is" do
40
+ it "null" do
41
+ @mock.analyse.class.should == Array
42
+ @mock.analyse.should be_empty
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ dummy_text = <<EOT
4
+ This is a text
5
+ This is a text
6
+ This is a text
7
+ This is a text
8
+ EOT
9
+
10
+ class Test
11
+ include Codesake::Utils::Files
12
+ end
13
+
14
+ shared_examples_for Codesake::Utils::Files do
15
+ before(:all) do
16
+ @mock = Test.new
17
+ File.open("test_utils.txt", "w") do |f|
18
+ f.puts(dummy_text)
19
+ end
20
+
21
+ end
22
+ after(:all) do
23
+ File.delete("test_utils.txt")
24
+ end
25
+
26
+ ## Reading the file
27
+
28
+ it "has a read_file method" do
29
+ @mock.should respond_to(:read_file)
30
+ end
31
+
32
+ it "complains if we request to read a non existing file" do
33
+ @mock.filename = "test"
34
+ @mock.read_file.should be_false
35
+ @mock.file_content.should be_empty
36
+ end
37
+
38
+ it "read an existing file" do
39
+ @mock.filename = "test_utils.txt"
40
+ @mock.read_file.should be_true
41
+ @mock.file_content.should_not be_empty
42
+ end
43
+
44
+
45
+ it "has a loc method" do
46
+ @mock.should respond_to(:loc)
47
+ end
48
+ it "has a lines method" do
49
+ @mock.should respond_to(:lines)
50
+ end
51
+
52
+ it "has a lines_of_comment method" do
53
+ @mock.should respond_to(:lines_of_comment)
54
+ end
55
+
56
+
57
+
58
+ end
59
+
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ jsp_content =<<EOS
4
+ <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
5
+ pageEncoding="ISO-8859-1"%>
6
+ <%@page import="com.codesake.test"%>
7
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
8
+ <html>
9
+ <head>
10
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
11
+ <link rel="stylesheet" type="text/CSS" href="<%=request.getContextPath()%>/css/style.css" />
12
+ <title>Hello World</title>
13
+
14
+ <script type="text/javascript">
15
+ function confirmSubmit(name) {
16
+ return alert("test here'"+ cacheName +"'");
17
+ }
18
+
19
+ </script>
20
+
21
+ </head>
22
+ <body>
23
+
24
+ <div id="header">
25
+ <h1>Hello World</h1>
26
+
27
+ <a href="<%=request.getContextPath()%>/jsp/link1.jsp">Link 1</a>
28
+ <a href="<%=request.getContextPath()%>/jsp/link2.jsp">Link 2</a>
29
+ <a href="<%=request.getContextPath()%>/jsp/link3.jsp">Link 3</a>
30
+ <a href="<%=request.getContextPath()%>/jsp/link4.jsp">Link 4</a>
31
+ <a href="<%=request.getContextPath()%>/servlet">servlet</a>
32
+ </div>
33
+
34
+ <%
35
+ String message = (String) request.getAttribute("message");
36
+ if(message != null)
37
+ {
38
+ %>
39
+ <h4 id="message"><%=message%></h4>
40
+ <% }
41
+ else
42
+ {
43
+ %>
44
+ <h4 id="message"></h4>
45
+ <% } %>
46
+ <div id="content">
47
+ <form action="<%=request.getContextPath()%>/postHandler" method="post">
48
+ <label for="message">message:</label>
49
+ <input type="text" name="message" id="message" size="40" value="<%=request.getLocalName()%>" />
50
+ <input type="submit" value="submit" onclick="javascript: return confirmSubmit('Clienti');" />
51
+ </form>
52
+ </div>
53
+ <%
54
+ Cookie c = new Cookie("name", "a_value")
55
+ Cookie cc = new Cookie("second", 12)
56
+ %>
57
+ </body>
58
+ EOS
59
+
60
+ describe Codesake::Engine::Jsp do
61
+ before(:all) do
62
+ File.open("test.jsp", "w") do |f|
63
+ f.write(jsp_content)
64
+ end
65
+ @jsp = Codesake::Engine::Jsp.new("test.jsp", {})
66
+ @jsp.analyse
67
+ end
68
+
69
+ after(:all) do
70
+ File.delete("test.jsp") if File.exists?("test.jsp")
71
+ end
72
+
73
+ it_behaves_like Codesake::Utils::Files
74
+ # it_behaves_like Codesake::Utils::Secrets
75
+ it_behaves_like Codesake::Engine::Core
76
+
77
+ it "takes a filename as input" do
78
+ @jsp.filename.should_not be_nil
79
+ @jsp.filename.should_not be_empty
80
+ end
81
+
82
+ it "analyses a jsp for imported packages" do
83
+ expected_result = [{:package=>"com.codesake.test", :line=>3}]
84
+ @jsp.imports.should == expected_result
85
+ end
86
+
87
+ it "analyses a jsp file for attack entrypoints" do
88
+ expected_result = [{:line=>32, :param=>"message", :var=>"message"}]
89
+ @jsp.attack_entrypoints.should == expected_result
90
+ end
91
+ it "analyses a jsp file for reflected variables" do
92
+ expected_result = [{:line=>8, :var=>"request.getContextPath()", :false_positive=>true},
93
+ {:line=>24, :var=>"request.getContextPath()", :false_positive=>true},
94
+ {:line=>25, :var=>"request.getContextPath()", :false_positive=>true},
95
+ {:line=>26, :var=>"request.getContextPath()", :false_positive=>true},
96
+ {:line=>27, :var=>"request.getContextPath()", :false_positive=>true},
97
+ {:line=>28, :var=>"request.getContextPath()", :false_positive=>true},
98
+ {:line=>36, :var=>"message", :false_positive=>false},
99
+ {:line=>44, :var=>"request.getContextPath()", :false_positive=>true},
100
+ {:line=>46, :var=>"request.getLocalName()", :false_positive=>true}
101
+ ]
102
+ @jsp.reflected_xss.should == expected_result
103
+ end
104
+
105
+ it "analyses a jsp file for cookies" do
106
+ expected_result = [{:line=>51, :name=>"name", :value=>"a_value", :var=>"c"}, {:line=>52, :name=>"second", :value=>"12", :var=>"cc"}]
107
+ @jsp.cookies.should == expected_result
108
+ end
109
+
110
+
111
+
112
+
113
+
114
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Codesake::Kernel do
4
+ before(:all) do
5
+ @kernel = Codesake::Kernel.instance
6
+ end
7
+
8
+ it "has a choose_engine method" do
9
+ @kernel.should respond_to(:choose_engine)
10
+ end
11
+
12
+ it "has a detect method" do
13
+ @kernel.should respond_to(:detect)
14
+ end
15
+
16
+ it "detects a text file from its extension" do
17
+ @kernel.detect("Gemfile").should == Codesake::Kernel::TEXT
18
+ @kernel.detect("foo.txt").should == Codesake::Kernel::TEXT
19
+ end
20
+
21
+ it "detects a jsp file from its extension" do
22
+ @kernel.detect("test.jsp").should == Codesake::Kernel::JSP
23
+ end
24
+
25
+
26
+ #
27
+ # TODO: I plan to add specialized engines for those languages before
28
+ # reaching 1.0 - 20121211
29
+ #
30
+
31
+ it "detects a java file from its extension"
32
+ it "detects a c file from its extension"
33
+ it "detects a shell script from its extension"
34
+ it "detects an html file from its extension"
35
+ it "detects an haml file from its extension"
36
+ it "detects a markdown file from its extension"
37
+ it "detects a ruby file from its extension"
38
+ it "detects a php file from its extension"
39
+ it "detects a js file from its extension"
40
+ it "detects a perl file from its extension"
41
+
42
+ # Engine choosing tests
43
+
44
+ it "chooses Codesake::Engine::Text for a text file" do
45
+ @kernel.choose_engine("a_text_file", {}).class.should == Codesake::Engine::Text
46
+ end
47
+
48
+ it "chooses Codesake::Engine::Jsp for a jsp file" do
49
+ @kernel.choose_engine("test.jsp", {}).class.should == Codesake::Engine::Jsp
50
+ end
51
+
52
+ it "chooses Codesake::Engine::Java for a java file"
53
+ it "chooses Codesake::Engine::Text for a c file"
54
+ it "chooses Codesake::Engine::Text for a shell script"
55
+ it "chooses Codesake::Engine::Text for a html file"
56
+ it "chooses Codesake::Engine::Text for a haml file"
57
+ it "chooses Codesake::Engine::Text for a markdown file"
58
+ it "chooses Codesake::Engine::Text for a ruby file"
59
+ it "chooses Codesake::Engine::Text for a php file"
60
+ it "chooses Codesake::Engine::Text for a js file"
61
+ it "chooses Codesake::Engine::Text for a perl file"
62
+
63
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ dummy_text = <<EOT
5
+ This is a text
6
+ This is a text
7
+ This is a text
8
+ This is a text
9
+ secret
10
+ This is a text
11
+ This is a text
12
+ This is a text
13
+ EOT
14
+
15
+ class Test
16
+ include Codesake::Utils::Files
17
+ include Codesake::Utils::Secrets
18
+ end
19
+
20
+
21
+ shared_examples_for Codesake::Utils::Secrets do
22
+ before(:all) do
23
+ @mock = Test.new
24
+ File.open("test_secrets.txt", "w") do |f|
25
+ f.puts(dummy_text)
26
+ end
27
+
28
+ @mock.filename="test_secrets.txt"
29
+ @mock.read_file
30
+ end
31
+ after(:all) do
32
+ File.delete("test_secrets.txt")
33
+ end
34
+
35
+ context "has a list of reserved words containing" do
36
+ it "password" do
37
+ @mock.reserved?("password").should be_true
38
+ end
39
+ it "username" do
40
+ @mock.reserved?("username").should be_true
41
+ end
42
+ it "login" do
43
+ @mock.reserved?("login").should be_true
44
+ end
45
+ it "fixme" do
46
+ @mock.reserved?("fixme").should be_true
47
+ end
48
+ it "xxx" do
49
+ @mock.reserved?("xxx").should be_true
50
+ end
51
+ it "fix" do
52
+ @mock.reserved?("fix").should be_true
53
+ end
54
+ end
55
+
56
+ it "let user add a reserver word" do
57
+ @mock.reserved?("foo").should be_false
58
+ @mock.add("foo")
59
+ @mock.reserved?("foo").should be_true
60
+
61
+ end
62
+ context "has a find method" do
63
+ it "that is public" do
64
+ @mock.should respond_to(:find_reserved_keywords)
65
+ end
66
+ it "returns an empty array if 'secret' is not a reserved word in the example source" do
67
+ @mock.secrets=["noodle", "compain", "foo"]
68
+ @mock.find_reserved_keywords.should be_empty
69
+ end
70
+ it "returns true if 'secret' is a reserved word in the example source" do
71
+ @mock.secrets=["secret"]
72
+ @mock.find_reserved_keywords.should == [{:line=>5, :matcher=>"secret"}]
73
+ end
74
+
75
+
76
+ end
77
+
78
+
79
+ end
@@ -1 +1,4 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
1
4
  require 'codesake'
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ lorem_ipsum = <<EOS
4
+ Lorem ipsum dolor sit amet, secret consectetuer adipiscing elit, sed diam nonummy nibh
5
+ euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim
6
+ ad minim veniam, quis nostrud secret exerci tation ullamcorper suscipit lobortis nisl
7
+ ut aliquip ex ea commodo consequat. Duis splople autem vel eum iriure dolor in
8
+ hendrerit in vulputate velit esse secret molestie consequat, vel illum dolore eu
9
+ feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui
10
+ blandit praesent luptatum zzril password delenit augue duis dolore te feugait nulla
11
+ facilisi.
12
+
13
+ Pellentesque at dolor non lectus sagittis semper. Donec quis mi. Duis eget
14
+ pede. Phasellus arcu tellus, ultricies id, consequat id, lobortis nec, diam.
15
+ Suspendisse sed nunc. Pellentesque id magna. Morbi interdum quam at est.
16
+ Maecenas eleifend mi in urna. Praesent et lectus ac nibh luctus viverra. In vel
17
+ dolor sed nibh sollicitudin tincidunt. Ut consequat nisi sit amet nibh. Nunc mi
18
+ tortor, tristique sit amet, rhoncus porta, malesuada elementum, nisi. Integer
19
+ vitae enim quis risus aliquet gravida. Curabitur vel lorem vel erat dapibus
20
+ lobortis. Donec dignissim tellus at arcu. Quisque molestie pulvinar sem.
21
+
22
+ Nulla magna neque, ullamcorper tempus, luctus eget, malesuada ut, velit. Morbi
23
+ felis. Praesent in purus at ipsum cursus posuere. Morbi bibendum facilisis
24
+ eros. Phasellus aliquam sapien in erat. Praesent venenatis diam dignissim dui.
25
+ Praesent risus erat, iaculis ac, dapibus sed, imperdiet ac, erat. Nullam sed
26
+ ipsum. Phasellus non dolor. Donec ut elit.
27
+ EOS
28
+
29
+ describe Codesake::Engine::Text do
30
+ before(:all) do
31
+ File.open("lorem.txt", "w") do |f|
32
+ f.write(lorem_ipsum)
33
+ end
34
+ @text = Codesake::Engine::Text.new("lorem.txt")
35
+ end
36
+ after(:all) do
37
+ File.delete("lorem.txt") if File.exists?("lorem.txt")
38
+ end
39
+
40
+ it_behaves_like Codesake::Utils::Files
41
+ it_behaves_like Codesake::Utils::Secrets
42
+ it_behaves_like Codesake::Engine::Core
43
+
44
+ it "takes a filename as input" do
45
+ @text.filename.should_not be_nil
46
+ @text.filename.should_not be_empty
47
+ end
48
+
49
+ context "has a is_txt? method" do
50
+ it "and this method is public" do
51
+ Codesake::Engine::Text.should respond_to(:is_txt?)
52
+ end
53
+ it "returns false if file extension is not .txt" do
54
+ Codesake::Engine::Text.is_txt?("text.jsp").should be_false
55
+ end
56
+ it "returns true if file extension is .txt" do
57
+ Codesake::Engine::Text.is_txt?("text.txt").should be_true
58
+ end
59
+ end
60
+
61
+ it "analyse the file for reserved words" do
62
+
63
+ # secret @1, 3, 5
64
+ # password @7
65
+ expected_result = [{:line=>1, :matcher=>"secret"}, {:line=>3, :matcher=>"secret"}, {:line=>5, :matcher=>"secret"}, {:line=>7, :matcher=>"password"}]
66
+ @text.analyse.should_not be_nil
67
+ @text.reserved_keywords.size.should == 4
68
+ @text.reserved_keywords.should == expected_result
69
+
70
+ end
71
+
72
+ end