Wednesday, March 10, 2010

Windows 7 Firewall, Limit SSH Access to Ireland only

I've cygwin SSHD running on one of my windows 7 machines. I've noticed connection attempts for places all over the world. I'd rather restrict access a bit, in case they are attacking an exploitable flaw, or one of my password are too weak ( I must set up key-only login auth)

Now that Windows 7 has a much improved firewall, I can now add rules that allow inbound access to port 22 to a limited set of remote IP addresses.

To limit it to Ireland only, for example, I looked up the full range of Irish IP addresses using this site: http://www.countryipblocks.net/

Then I ran the following from the command line (run as Administrator):

netsh advfirewall firewall add rule name="SSHD IN Ireland Only" dir=in localport=22 protocol=TCP action=allow remoteip=62.9.0.0/16,62.17.0.0/16,62.40.32.0/19,62.77.160.0/19,62.231.32.0/19,....

The full list of subnets is quite long, and I don't know what is the maximum number of entries allowed. Indeed, neither do I know the performance impact on networking in general, if any, of a large number of entries. If they've built the firewall properly, the impact should be negligible on unrelated connections.

Tuesday, February 23, 2010

DDOS, URLScan, Disable IIS Logging

We have had to deal with a distributed denial of service attack lately.

Without getting into the details of the attack itself, it turned out, at least initially, that the bots could be identified by a relatively small number of user-agent strings.

Googling the odder looking useragents showed us examples of similar attacks in the past using the same bot software. This indicated, as seems to be quite normal, that the infected machine are spoofing their IPs.

While our hosting provider was looking at the issue at a network level, made very difficult by the spoofed IPs, I tried an IIS host-level solution.

1.
I installed URLScan 3.1
http://www.iis.net/expand/UrlScan

2.
I then edited the site-wide URLScan.ini in C:\WINDOWS\system32\inetsrv\urlscan

Changing:
RuleList=
to
RuleList=DenyUserAgent

[DenyUserAgent]
DenyDataSection=AgentStrings
ScanHeaders=User-Agent

[AgentStrings]
Mozilla/5.0%20%28Win.....


where the AgentStrings lists the 'escaped' user-agent string that should be blocked.


3.
Given the volume of entries in the logs, I also had to disable both the logging done by URLScan, as well as IIS's own logging of blocked requests.


3a.
So I flipped the value of EnableLogging in URLScan.ini to '0'

3b.
And then executed the following two commands to disable logging of only the specific /Rejected-By-UrlScan pseudo-url in IIS logs:

CSCRIPT %SYSTEMDRIVE%\Inetpub\AdminScripts\adsutil.vbs CREATE W3SVC/1/ROOT/Rejected-By-UrlScan IIsWebFile
then
CSCRIPT %SYSTEMDRIVE%\Inetpub\AdminScripts\adsutil.vbs SET W3SVC/1/ROOT/Rejected-By-UrlScan/DontLog

4.
Restarted the 'World Wide Web Publishing Service'.

Note:
URLScan does a substring match of entries listed in a custom rule's DenyDataSection. This would make it possible to block attacks if, for example, the attacker had a typo in one of the request headers. So you dont need to just match a complete header string.

But it does not allow more complicated matching, e.g. using regular expressions. If you are looking for the flexibility of Apache's various modules and directives, URLScan is not the answer.


Conclusion:
This solution is only suitable for the most small-scale attacks. The attacker only has to update the user-agent strings. Or instead just increasing attack traffic would max-out the CPUs of the web servers, since it has to go through extra effort to parse the request headers. Increasing attack traffic could kill servers through maxing out the bandwidth available, or the connection limit. Host-based mitigation techniques like this are, in general, going to be ineffective against botnet attacks.

Friday, January 29, 2010

Encrypted Web.config on IIS 6.0, Win2k3

1.
created identity.aspx containing only the following:

<%@ Page Language="C#" %>
<%
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
%>

In a browser, saw that the identity was
NT AUTHORITY\NETWORK SERVICE


2.
cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727


3.
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"
Adding ACL for access to the RSA Key container...
The RSA key container was not found.
Failed!


4.
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pc "NetFrameworkConfigurationKey" -exp
Creating RSA Key container...
Succeeded!


5.
Tried step 3. again...

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"
Adding ACL for access to the RSA Key container...
Succeeded!


6.
I have two websites, on different ports, both on the root URL /, so to distinguish them when encrypting the connection strings, I uses the site ID ( Identifier field in IIS Manager Web Sites list),

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pe "connectionStrings" -app "/" -site 1
Encrypting configuration section...
Succeeded!

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pe "connectionStrings" -app "/" -site 219934440
Encrypting configuration section...
Succeeded!


7.
I verified in a text editor the Web.config sections had been changed, and also that the running application was still able to read the connection strings.


8.
I did the same for the machineKey:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pd "system.web/machineKey" -app "/" -site 219934440
Decrypting configuration section...
Succeeded!



9.
I tested decrypting the sections back to the originals:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pd "connectionStrings" -app "/" -site 1
Decrypting configuration section...
Succeeded!

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis -pd "connectionStrings" -app "/" -site 2054359653
Decrypting configuration section...
Succeeded!




All taken from:
http://msdn.microsoft.com/en-us/library/dtkwfdky.aspx
http://social.msdn.microsoft.com/Forums/en/clr/thread/087df87f-8fb5-4e54-a57b-0bbdbc544c4f
http://forums.asp.net/p/960412/1423554.aspx#1423554

Friday, January 22, 2010

Semi-Transparent Windows

Sometimes I work on the command line, or am editing some file in a text editor. But I want to look at one window while I type in another. Even with my two screens, windows must sometimes overlap, but when this is necessary a semi-transparent foreground window can be handy, so the window behind can still be read.

Yes, Aero in windows lets your windows' border be semi-transparent. But it's only a thin border, and you still cant read what's behind as the background is blurred. I really dont understand the usability advantage of this feature. Seems a bit useless to me.

There's also the 'Glasser' extension for Firefox that makes Firefox's toolbars transparent in a similar way. But that only adds a bit of consistency, without much of a benefit.

Slightly more useful, is 'Glass CMD for Vista' that makes cmd.exe semi-transparent, but again, the background is blurred so you cant read what is behind. There is also 'Glass Notepad'.

What about disabling blur? It is possible with a registry hack, or by replacing DLLs on Windows 7. Neither of theas seem like a very clean solution.

Then I found Glass2k. And it even works on Windows 7 x64! I just press Ctrl-Shift-[1 to 9] to vary the transparency. And there is no blur. Perfect.

Tuesday, November 24, 2009

Convert VB.Net to C#

Sometimes I see code snippets online written in VB.Net. Yes, its not hard too work out what the code it doing, but it is still slower than working with C# which I am much more familiar with.

I found this:
http://www.developerfusion.com/tools/convert/vb-to-csharp/

It translates between the two languages.

Friday, November 20, 2009

find .png files larget than 64k, and copy to a temp directory

find /cygdrive/c/ -size +64k -name '*.png' -print0 | xargs -0 -n1 -I % cp % /cygdrive/c/temp/images/png/

Wednesday, November 18, 2009

Recursive Methods, Stack Overflow, IIS & FXCop

Had some serious issues lately around crashing IIS. The logs indicated a Stack Overflow Exception, error code 0x800703E9.

But it wasn't obvious what caused this, since no recent changes seemed to be the culprit, and developers seemed to be unaware of any recursion in our code.

Unfortunately, there is far too much code to aimlessly search through.

I identified the following possible cases where we may have introduced recursion:

1. Intended recursion, a method directly calling itself somewhere
2. Possibly intended recursion, a method indirectly calling itself via another method.
3. Unintended recursion when an overloaded method calls itself instead of one of the other overloads because of too many or few arguments.
4. Unintended recursion because of a typo in a property getter or setter
5. Unintended recursion because of a missing (T) cast when calling 'static bool T.Equals( T x, T y)' inside an 'override bool Equals(object obj)'
6. .Net library classes throwing this exception.


More info:

1.
This is straight forward enough... a method somewhere has a flaw either in the logic that identifies stopping conditions causing infinite recursion, or the depth of recursion depends on the inputs, and the method is processing inputs larger than the developer considered.

2.
See above.


3.
Overloading, without being careful with the arguments can mean a method calling itself instead of the other overload, e.g.

public class X
{
public int A( int f)
{
// infinite recursion - developer should have
// written 'return A(f, 0);'
return A(f);
}

public int A( int f, int g)
{
return f + g;
}
}



4.
The following two properties cause infinite recursion. The first has a typo in the getter, the second has a typo in the setter. (the case is incorrect)

private string abc;
public string Abc
{
get { return this.Abc; }
set { this.abc = value; }
}

private string xyz;
public string Xyz
{
get { return this.xyz; }
set { this.Xyz = value; }
}


5.
It is common practice to implement public override bool Equals(object obj) in classes that are used in collections. It is also not uncommon to implement public static bool Equals(T a, T b) in the same classes too (e.g. the System.string class)

However, if the overridden method directly calls the static method without both of it's arguments cast to the correct type (T), then recursion could result, e.g.
public class T
{
public override bool Equals(object obj)
{
return T.Equals(this, obj);
}

public static bool Equals(T a, T b)
{
return true;
}

}


The above code will cause infinite recursion, since the first method is actually calling static bool object.Equals(object a, object b), not static bool T.Equals(T a, T b) which will then call bool T.Equals( object obj) on each argument.

To fix this, object obj must be cast to type T before calling the static method:
public class T
{
public override bool Equals(object obj)
{
return T.Equals(this, (T)obj);
}

public static bool Equals(T a, T b)
{
return true;
}

}



6.
Possibly Linq to SQL issue?
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=355026


But how to identify any methods like this in a large library of code? FXCop to the rescue.

This is my first time using FXCop, but I couldnt find any existing rules that would identify these cases, so I set about writing some custom rules ( Tutorial )

A. Identifying direct recursive methods ( covers cases 1, 3 & 4 above)

I based my custom rule on the "Callees" example class here, with the following 'Check' implementation:
public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method != null)
{
string unmangledName = method.GetUnmangledNameWithTypeParameters();

IList callees = Callees.CalleesFor(method);
foreach (Method c in callees)
{
if (string.Equals(c.FullName, method.FullName) && string.Equals(c.GetUnmangledNameWithTypeParameters(), unmangledName) )
{
Resolution res;
if (c.Name.Name.StartsWith("get_") || c.Name.Name.StartsWith("set_"))
{
res = this.GetResolution();
res = new Resolution(string.Format("Check property name typo. {0}", res.Format), new string[] { c.FullName } );
}
else
{
res = this.GetResolution(new string[] { c.FullName });
}
Problems.Add( new Problem(res) );
}
}
}
return this.Problems;
}



B. Identifying indirect recursive methods ( covers case 2 above)

Here's my implementation:
public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method != null)
{
//string unmangledName = method.GetUnmangledNameWithTypeParameters();
string fullName = method.FullName;
if (!string.IsNullOrEmpty(fullName) && !fullName.StartsWith("Microsoft.") && !fullName.StartsWith("System."))
{
List methodStack = new List();
methodStack.Add(fullName);

IList callees = Callees.CalleesFor(method);

TraverseCallees(methodStack, callees);
}
}
return this.Problems;
}


private void TraverseCallees(List methodStack, IList callees)
{
foreach (Method c in callees)
{
//string unmangledName = c.GetUnmangledNameWithTypeParameters();
string fullName = c.FullName;
if (!string.IsNullOrEmpty(fullName) && !fullName.StartsWith("Microsoft.") && !fullName.StartsWith("System."))
{
if (methodStack.Contains(fullName))
{
// only match against the head of the stack, since all methods will be processed as the head once
if (string.Equals(methodStack[0], fullName))
{
// only show indirect calls
if (methodStack.Count > 2)
{
StringBuilder callStackDescription = new StringBuilder();

//bool logStack = false;
foreach (string methodFullName in methodStack)
{
//if (!logStack && methodFullName.Equals(fullName))
//{
// logStack = true;
//}

//if (logStack)
//{
callStackDescription.AppendFormat("{0} -> ", methodFullName);
//}
}
callStackDescription.AppendFormat("{0}", fullName);

Resolution res = new Resolution(GetResolution().Format, new string[] { callStackDescription.ToString() });

Problems.Add(new Problem(res, c));
}
else
{
// ignore recursion, where it is a method directly calling itself
}
}
}
else
{
methodStack.Add(fullName);

IList nextCallees = Callees.CalleesFor(c);

TraverseCallees(methodStack, nextCallees);

methodStack.RemoveAt(methodStack.Count - 1);
}
}
}
}



C. Overridden T.Equals Calling Object.Equals ( covers case 5 above )

public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method != null)
{
string fullName = method.FullName;
if (!string.IsNullOrEmpty(fullName) && !fullName.StartsWith("Microsoft.") && !fullName.StartsWith("System."))
{
// check of our 'Equals' overrides the defualt 'object.Equals(object obj)', since that may be called by 'static object.Equals(object, object_'
if (string.Equals(method.OverriddenMethod == null ? null : method.OverriddenMethod.FullName, "System.Object.Equals(System.Object)"))
{
IList callees = Callees.CalleesFor(method);

foreach (Method c in callees)
{
if( c.IsStatic && string.Equals( c.FullName, "System.Object.Equals(System.Object,System.Object)") &&
c.Parameters.Count == 2 &&
string.Equals( c.Parameters[0].Type.FullName, "System.Object" ) &&
string.Equals( c.Parameters[1].Type.FullName, "System.Object" ))
//TODO: also check the the VALUE of one of the arguments is really of the same type as the parent caller method
{
Problems.Add(new Problem(GetResolution(), c));
}
}
}
}
}
return this.Problems;
}



Sure enough, my custom rules found new examples of cases 1 and 3. And I am aware of cases 4 & 5 happening in the past, although luckily they were fixed during development.