Skip to content

Commit 80f21b5

Browse files
committed
Fix rapid7#4227 by improving parsing of nested elements
1 parent 0c7d2af commit 80f21b5

File tree

1 file changed

+45
-49
lines changed

1 file changed

+45
-49
lines changed

lib/rex/parser/openvas_nokogiri.rb

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ def start_element(name=nil,attrs=[])
1515
attrs = normalize_attrs(attrs)
1616
block = @block
1717
@state[:current_tag][name] = true
18+
19+
unless @text.nil?
20+
@state[:text_backup] = @text
21+
@text = nil
22+
end
23+
1824
case name
1925
when "host"
2026
@state[:has_text] = true
@@ -29,93 +35,85 @@ def end_element(name=nil)
2935
return if not in_tag("result")
3036
@state[:has_text] = true
3137
@state[:vuln_name] = @text.strip if @text
32-
@text = nil
3338
when "description"
3439
@state[:has_text] = true
3540
@state[:vuln_desc] = @text.strip if @text
36-
@text = nil
3741
when "bid"
38-
return if not in_tag("result")
39-
return if not in_tag("nvt")
42+
return unless in_tag("result")
43+
return unless in_tag("nvt")
4044
@state[:has_text] = true
4145
@state[:bid] = @text.strip if @text
42-
@text = nil
4346
when "cve"
44-
return if not in_tag("result")
45-
return if not in_tag("nvt")
47+
return unless in_tag("result")
48+
return unless in_tag("nvt")
4649
@state[:has_text] = true
4750
@state[:cves] = @text.strip if @text
48-
@text = nil
4951
when "risk_factor"
50-
return if not in_tag("result")
51-
return if not in_tag("nvt")
52-
52+
return unless in_tag("result")
53+
return unless in_tag("nvt")
5354
#we do this to clean out the buffer so to speak
5455
#if we don't set text to nil now, the text will show up later
5556
@state[:has_text] = true
56-
@text = nil
5757
when "cvss_base"
58-
return if not in_tag("result")
59-
return if not in_tag("nvt")
58+
return unless in_tag("result")
59+
return unless in_tag("nvt")
6060
@state[:has_text] = true
61-
@text = nil
6261
when "subnet"
6362
@state[:has_text] = true
64-
@text = nil
6563
when "result"
66-
return if not in_tag("results")
67-
record_vuln
64+
record_vuln if in_tag("results")
6865
when "threat"
69-
return if not in_tag("ports")
70-
return if not in_tag("port")
71-
@state[:has_text] = true
72-
73-
if not @text.index('(')
74-
@state[:name] = nil
75-
@state[:port] = nil
76-
@state[:proto] = nil
77-
@text = nil
78-
return
79-
end
80-
81-
@state[:name] = @text.split(' ')[0] if @text
82-
@state[:port] = @text.split('(')[1].split('/')[0] if @text
83-
@state[:proto] = @text.split('(')[1].split('/')[1].split(')')[0] if @text
84-
85-
@text = nil
66+
@state[:has_text] = true if in_tag("ports") && in_tag("port")
8667
when "host"
8768
if in_tag('result')
8869
@state[:has_text] = true
8970
@state[:host] = @text.strip if @text
90-
@text = nil
91-
elsif in_tag('ports')
92-
return if not in_tag('port')
71+
elsif in_tag('ports') && in_tag('port')
9372
@state[:has_text] = true
9473
@state[:host] = @text.strip if @text
95-
@text = nil
9674
end
9775
when "port"
9876
if in_tag('result')
9977
@state[:has_text] = true
100-
if not @text.index('(')
78+
if @text && @text.index('(')
79+
@state[:proto] = @text.split('(')[1].split('/')[1].gsub(/\)/, '')
80+
@state[:port] = @text.split('(')[1].split('/')[0].gsub(/\)/, '')
81+
elsif @text && @text.index('/')
82+
@state[:proto] = @text.split('/')[1].strip
83+
@state[:port] = @text.split('/')[0].strip
84+
else
85+
@state[:proto] = nil
86+
@state[:port] = nil
87+
end
88+
89+
if @state[:port] && @state[:port] == 'general'
10190
@state[:proto] = nil
10291
@state[:port] = nil
103-
@text = nil
104-
return
10592
end
106-
@state[:proto] = @text.split('(')[0].strip if @text
107-
@state[:port] = @text.split('(')[1].split('/')[0].gsub(/\)/, '') if @text
108-
@text = nil
10993
elsif in_tag('ports')
110-
record_service
94+
if @text && @text.index('(')
95+
@state[:name] = @text.split(' ')[0]
96+
@state[:port] = @text.split('(')[1].split('/')[0]
97+
@state[:proto] = @text.split('(')[1].split('/')[1].split(')')[0]
98+
record_service unless @state[:name].nil?
99+
elsif @text && @text.index('/')
100+
@state[:port] = @text.split('/')[0]
101+
@state[:proto] = @text.split('/')[1]
102+
record_service unless @state[:port] == 'general'
103+
end
111104
end
112105
when "name"
113106
return if not in_tag("result")
114107
@state[:has_text] = true
115-
@text = nil
108+
end
109+
110+
if @state[:text_backup]
111+
@text = @state[:text_backup]
112+
@state[:text_backup] = nil
116113
else
117114
@text = nil
118115
end
116+
119117
@state[:current_tag].delete name
120118
end
121119

@@ -153,8 +151,6 @@ def record_vuln
153151
end
154152

155153
def record_service
156-
return if not @state[:name]
157-
158154
service_info = {}
159155
service_info[:host] = @state[:host]
160156
service_info[:name] = @state[:name]

0 commit comments

Comments
 (0)