A Better Telnet for Windows

console telnet in semi-transparent console2 powershell sessionThere’s no really nice way to say it: the telnet client in Windows is a little strange at best. I mostly use telnet to debug text-based TCP services. The Microsoft telnet implementation isn’t very good for this. I have used a PowerShell script to fill the gap by piping stdin and stdout to the console but sometimes I actually want telnet. I don’t want to go on a tirade about its problems here but telnet doesn’t work the way I want. What I really want is the telnet from GNU inetutils but compiled for Win32 with no extra runtime requirements. I don’t want to have to install Cygwin or MSys or SUA in order to get telnet.

I looked into this a little bit and it seems like inetutils has a lot of dependencies that make it hard to compile to run directly on Win32 without any POSIX layer. I also found an abandoned project on SourceForge called Console Telnet for Win32 which is under GPL, supports ANSI color codes and seems to have quite good VT100 emulation. The last code drop is from October 2000 and was originally written for old versions of Visual C++ or Borland C++, but it looked promising.

I spent a little time fixing up headers and a few functions here and there to get the code to compile with Visual Studio 2010. It works and it works pretty much like the GNU inetutils version of telnet except that it is annoyingly chatty about printing out info about its configuration on every connection so I put the chatty stuff behind an #IFDEF CHATTY and compiled without that CHATTY symbol defined which pretty much gave me what I wanted. It works by piping stdin/stdout to the TCP connection and doesn’t do any crazy erasing of your entire console scrollback buffer the way that Microsoft’s telnet does. It also doesn’t crash Console2.

I haven’t done extensive testing but everything seems to be working on my computer. I watched as much of Star Wars as I could stand at towel.blinkenlights.nl (“telnet towel.blinkenlights.nl”) and I’ve passed a bunch of HTML GET queries and responses through it.

Get the Code and Binary

Here’s the source code and compiled binary. You need to have telnet.exe, telnet.cfg and telnet.ini together in a directory for it to run correctly.

Advertisements

Chrome MSI Works Great with AppLocker

Google has released a version of the Chrome installer packaged as an MSI rather than using the ClickOnce installer. The major difference is that the MSI creates a global installation under %ProgramFiles(x86)%. Transparent updates continue by default, managed by the Google Chrome Update Service (gupdate). Gupdate also updates Google Apps Sync for Outlook if it is installed. The key advantage of an MSI package is that it is compatible with managed deployment using Active Directory and Google has provided a set of policy templates to allow managing Chrome via Group Policy in the same way that Internet Explorer is managed.

Because all of the code is installed in %ProgramFiles(x86)%, Chrome is fully compatible with the default AppLocker EXE and DLL rules even though the bundled Flash DLL is not signed. “Chrome Enterprise” runs fine with the default rule set and no special publisher rules at all.

Chrome MSI download here.

Policy templates here.

via Chromium Blog.

More Granular Options for CWDIllegalInDllSearch Needed

I’m starting to see a class of issues where plugins rely on their libraries loading from the current working directory (CWD). To me this implies that the 0xffffffff option to completely disable loading from the CWD is not viable for most people in the near term but the 2 option of disabling network locations leaves open luring attacks based on removable storage like USB thumb drives or an attack that relies on an evil DLL that an attacker manages to place in an unprotected directory in the user’s profile somewhere.

I would like to see additional options to CWDIllegalInDllSearch. We need something between blocking loading of DLLs from CWD when CWD is a network location and blocking all loading from CWD at all. I want to be able to allow loading from CWD if CWD is a trusted location on my local computer in order to maintain compatibility with existing software that relies on this behavior but disable loading from CWD from any untrusted location.

A trusted location would be something that requires Administrator privilege to write into. That means the system folders and the “Program Files” folders.

I hope that Microsoft will realize the need for additional granularity and add some more options to CWDIllegalInDllSearch. The following would cover all the bases, I think:

  • 1 = disable CWD in LoadLibrary() search for WebDAV
  • 2 = disable CWD in LoadlLibrary() search for all networked location
  • 3 = option 2 and disable CWD in LoadLibrary() search for removable storage locations
  • 4 = disable CWD in LoadLibrary() anywhere except for “Program Files”
  • 0xffffffff = disable CWD in LoadLibrary() search
    WARNING: Note that options 3 and 4 are hypothetical. Setting CWDIllegalInDllSearch to 3 or 4 is currently equivalent to setting CWDIllegalInDllSearch to 0 and will enable the very insecure DLL loading behavior we are trying to eliminate.

My hypothetical CWDIllegalInDllSearch = 4 should provide equivalent security to CWDIllegalInDllSearch = 0xffffffff because anything in Program Files is trusted by definition. But it provides a backwards compatibility cushion for applications that require loading libraries from CWD.

There are two classes of applications that I can imagine which have a legitimate reason to load DLLs outside of Program Files and system.

  • Some kind of run-from-network corporate app
  • The latest generation of apps designed to run with least-privilege that install themselves into the current user’s profile or the all user’s profile like Chrome and WebEx but I’m not worried about these apps.

My feeling is that the corporate system administrators can handle provisioning rules such that their apps can run or virtualize them and the new apps that are installing themselves into unorthodox locations can fend for themselves. I think there is real utility in a CWD is OK in “Program Files” only mode and I hope that Microsoft will release an update to KB2264107 to give it to us.

Mozilla Compatible Silverlight 4 Plugin Requires Loading DLLs from CWD

chrome-silverlight-agcore-missingI visited a site yesterday in Chrome that tried to load Silverlight to provide a video player. I have KB2264107 installed and have globally disabled loading of DLLs from the current working directory in order to mitigate luring attacks against apps that use the default insecure DLL loading behavior of LoadLibrary(). Just like the Java plugin for Mozilla, Chrome generated a big fat bonk dialog trying to load the DLLs that the Silverlight plugin uses. The specific missing file is agcore.dll, which is found in “C:\Program Files (x86)\Microsoft Silverlight\4.0.50524.0” on my system.

I tried creating a symlink to agcore,dll so that agcore.dll is in the same directory as Chrome.exe, which fixes the bonk but Silverlight doesn’t work. I just end up with a black box where the movie player should be. I also tried adding the Silverlight directory to $env:path which removed the bonk but, instead, I got the “Install Microsoft Silverlight” button. I tried various combinations of symlinking DLLs and messing with the $env:path but I didn’t arrive at a combination that can actually work.

The only solution that I found is to dial the CWDIllegalInDllSearch value for Chrome and Firefox to 2 (DLLs not allowed to load from CWD if CWD is any remote, network location) instead of 0xffffffff (it also works to change this globally). I then have to hope that Firefox and Chrome are careful about how they are using CWD. I hope they are setting CWD just for loading the installed plugins in “Prgram Files” but cannot be lured into loading some evil DLL from a spurious location when doing something like opening an HTML document on a USB stick.


PS> Get-ItemProperty chrome.exe, firefox.exe | select pspath,cwdillegalindllsearch | fl


PSPath                : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVer
                        sion\Image File Execution Options\chrome.exe
CWDIllegalInDllSearch : 2

PSPath                : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVer
                        sion\Image File Execution Options\firefox.exe
CWDIllegalInDllSearch : 2




Java Built with Unsupported Old Compilers

When I turned off DLL loading from the current working directory to defeat DLL pre-loading luring attacks, one of the things I discovered was that the Java plug-in was broken in Firefox and Chrome. This problem of Java finding its C library is not new at all. The tubes are choked with posts and bug reports about getting various things that are dependent on Java to work when msvcr71.dll can’t be found. The new CWDIllegalInDllSearch = 0xFFFFFFFF option just exacerbates an existing deployment problem.

PS> cd 'C:\Program Files (x86)\Java\jre6\bin\new_plugin'
PS> dumpbin /dependents .\npjp2.dll
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file .\npjp2.dll

File Type: DLL

  Image has the following dependencies:

    USER32.dll
    GDI32.dll
    ADVAPI32.dll
    MSVCR71.dll
    KERNEL32.dll
    ole32.dll

  Summary

        6000 .data
        3000 .rdata
        1000 .reloc
        7000 .rsrc
        4000 .text

The root of the Mozilla-compatible browser Java plugin problem is npj2.dll which is dynamically linked to msvcr71.dll. Because it is a plugin, the DLL loading is done by Windows on behalf of the executable and  (Chrome or Firefox) rather than the plugin. The new_plugin directory includes msvcr71.dll which probably helped if a browser changed its CWD to the new_plugin directory when loading npj2.dll but with searching CWD out of the picture it doesn’t.

Java simply doesn’t do a good job of loading its C runtime correctly on Windows. It’s not a new problem. I don’t understand why don’t just change a switch on the complier to /MT instead of /MD and statically link the C runtime into jpjp2.dll. That would make the whole problem go away.

There are also some other oddities here. There are 2 different C runtimes used in the 32-bit version of Java 6 for Windows. For some reason they are redistributing msvcr71.dll (C runtime from Visual Studio .NET 2003) and also msvcrt.dll which is supposed to be the name of the private C runtime used by Windows components. However, the msvcrt.dll in the Java directory is actually the C runtime from Visual Studio 6 or possibly a very old Platform SDK.

By implication Oracle/Sun is using the C/C++ optimizing compiler from Visual Studio 6 (1998) and Visual Studio .NET 2003 to build the 32-bit version of Java. Holy cow those are 5 and 3 versions back from the current compilers and between 12 and 7 years old. I’m pretty sure that Visual Studio 6 is no longer supported and unfortunately both predate the side-by-side C runtime distribution system that starts with Visual Studio 2005.

The x64 version of Java is even stranger. It links against a Microsoft  x64 C runtime library called msvcrt.dll. Again this is the name reserved for the private Windows platform C runtime but this msvcrt.dll has file version 6.10.2207.0 either from a very old version of the Windows Platform SDK that provided x64 compilation support prior to Visual Studio 2005 or from a tool chain that was available by request (and is no longer available) for Visual Studio 2003.

It seems like the Java team has made a bit of a fetish of using really old compilers for the Microsoft platforms. I can understand that there is a risk of breaking stuff when upgrading a tool chain but this has been taken a bit to the extreme by the Java build team. There is a cost to testing a huge platform like Java when building with a new tool chain. Sun was cash-constrained and, although popular, Java SE didn’t really make them any money directly.

Good News for Java 7 (Probably)

It looks like the problem is being addressed. OpenJDK 7 builds, it looks like Oracle is upgrading to the C/C++ compiler from Visual Studio 2010.

BEGIN WARNING: At this time (Spring/Summer 2010) JDK 7 is starting a transition to use the newest VS2010 Microsoft compilers. These build instructions are updated to show where we are going. We have a QA process to go through before official builds actually use VS2010. So for now, official builds are still using VS2003. No other compilers are known to build the entire JDK, including non-open portions. So for now you should be able to build with either VS2003 or VS2010. We do not guarantee that VS2008 will work, although there is sufficient makefile support to make at least basic JDK builds plausible. Visual Studio 2010 Express compilers are now able to build all the open source repositories, but this is 32 bit only. To build 64 bit Windows binaries use the the 7.1 Windows SDK.END WARNING.

The 32-bit OpenJDK Windows build requires Microsoft Visual Studio C++ 2010 (VS2010) Professional Edition or Express compiler. The compiler and other tools are expected to reside in the location defined by the variable VS100COMNTOOLS which is set by the Microsoft Visual Studio installer.

So maybe in 2011 Java will have its C runtime library sorted out by virtue of having a supported global mechanism to register the Visual Studio 2010 C runtime.

Java Browser Plugin for Mozilla Vulnerable to DLL Preloading Attack

chrome-java-bonkThe “Next Generation Java Plug-in 1.6.0_21 for Mozilla browsers” 32-bit version for Windows uses CWD to load its C runtime library (msvcr71.dll). If you have globally disabled loading libraries from the current working directory (CWD) by globally setting CWDIllegalInDllSearch to 0xfffffff, you will get a bonk like the one shown at the right. Firefox also fails to load the JVM but it doesn’t give any feedback about why it isn’t working.

Note that this is not a general problem with Java. Java desktop applications like Eclipse work and the Java ActiveX plugin for IE works. The problem is specific to the NSAPI plugin and this indicates that the Java plugin for Google Chrome and Mozilla Firefox is one of the applications that is vulnerable to a DLL preloading luring attack. Specifically, when a Java applet is loaded, the JVM will cause the browser to load msvcr71.dll from whatever is the current working directory for the browser.

The error can be fixed by dialing back your global CWDIllegalInDllSearch to 2 or create an exception for chrome and firefox. However, I would rather not open those programs to attack from a USB drive.

The first location that Windows uses to search for a DLL is the directory containing the binary executable. Placing a copy of msvcr71.dll in the same directory with Firefox and Chrome fixes the problem. The problem with that is if Java services the msvcr71.dll with a newer version, then Chrome and Firefox will cause the JRE to load the wrong C runtime causing bad things to maybe happen. Another option is to create a symbolic link (which requires Vista or later).

Incidentally, the mklink command is not a standalone utility, it is a built-in to the cmd.exe shell. If you want to use mklink via powershell, you need a function to invoke cmd.exe.

function mklink { & "$env:systemroot\system32\cmd.exe" /c mklink $args }

Running mklink requires Administrator privilege.

PS> cd C:\Users\breiter\appdata\Local\Google\Chrome\Application
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS> cd 'C:\users\breiter\AppData\Local\Google\Chrome SxS\Application'
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS> cd 'C:\Program Files (x86)\Mozilla Firefox'
PS> mklink msvcr71.dll 'C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll'
symbolic link created for msvcr71.dll <<===>> C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
PS>

With the symlink fix in place, the Java version test page loads correctly in Chrome with no bonks with loading libraries from CWD disabled.

chrome-java-crt-symlink

Microsoft Should Formally Deprecate CWD from LoadLibrary Search

Microsoft recently released security security advisory 2269637, “Insecure Library Loading Could Allow Remote Code Execution”. The gist is that the search behavior of LoadLibrary() includes the current working directory, which is not the same as the directory containing the binary executable. Typically the current working directory (CWD) is set at launch time by Windows shell shortcut (LNK) or implicitly by invoking a document with a file association. The CWD can be anywhere on a supported local or remote file system, including Windows network (SMB/CIFS) shares and WebDAV.

Most applications must load code from libraries (DLLs) in order to run. The CWD is not a trusted secure location like Program Files or System32 but for reasons of backwards compatibility with pre-Windows NT forms of Windows, CWD is searched when loading DLLs. This makes the default behavior of LoadLibrary() dangerous and many, many Windows applications are vulnerable to luring attacks as a result.

Sample Luring Attack Scenario

  • Click on a link to an MP3 in an email or web page
  • File association causes popular MP3 player to load
  • CWD is set to the remote location of the MP3 player
  • Attacker has placed a malicious DLL that the popular MP3 player loads in the same location as the MP3
  • MP3 player loads malicious DLL
  • Malicious DLL loads the real DLL so MP3 player won’t crash
  • Popular MP3 player is owned an executing evil code

    Unfortunate Default Behavior

    Your application doesn’t have to search CWD but it is the default for reasons of backwards compatibility. Developers can turn this behavior off but it is the default and you a) have to know that you need to turn it off and b) know how to turn it off.

Patch Optionally Introduces New Behavior

KB2264107 is a patch that allows you to set registry keys to change the circumstances under which CWD is considered. The simplest option is to create a new DWORD value of the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager key called CWDIllegalInDllSearch and set it to 0xffffffff. chrome-load-dll-cwd-errorThis globally disables the use of CWD for loading libraries.

My first thought was this would be fine. I’m running Windows 7 x64 with no legacy 16-bit apps. It should work fine and for me it did. The second computer I tried this on had a problem where Google Chrome 5 was unable to find avutil-50.dll. Chrome keeps its DLLs in a version-numbered subdirectory of the one containing Chrome.exe. This isn’t a part of the normal DLL search path and it seems like Chrome 5 is working around this by setting CWD to the directory which contains the DLLs before calling LoadLibrary(). Chrome 6 beta doesn’t do this which is why I didn’t notice the problem.

To fix this you can either dial the global CWDIllegalInDllSearch down to 2 which indicates CWD is allowed to be searched only if it is a local folder. Better, is to create a KEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\chrome.exe key with a CWDIllegalInDllSearch DWORD value of 2 (and remember to delete this when Chrome 6 goes stable).

I had a similar problem with the Apple Update program failing when it tried to install the latest version of QuickTime.

Developers Should Disable Loading DLLs from CWD

depI was really stunned to realize that Chrome was using this CWD load behavior. They probably didn’t realize the implications and it is insidious because it is the default. I think all developers and testers should install KB2264107 and globally disable loading from CWD. (Yes this is a PITA and it might break stuff on your box but you can suck it up and white list apps that are broken.) If your apps are broken by this then you need to fix them.

Microsoft should encourage this by formally deprecating loading DLLs from CWD with Windows 7 SP1. They need to roll it out like they did DEP. There needs to be Group Policy settings and a GUI for manipulating these registry keys along the lines of the DEP compatibility with radio buttons like “Turn on loading libraries from CWD” and “Turn off loading libraries from CWD except for those I select". With Windows 7 SP1, the default is to leave CWD turned on. By the time Windows 8 rolls around, the default is to disable CWD.

KB2264107 is Insufficient

The hotfix should probably actually provide some protection by globally disabling some form of CWD loading. Right now all it does is create the potential for you to make some registry changes which is definitely not OK for the average user. At a minimum they need to disable CWD over WebDAV (CWDIllegalInDllSearch=1) and probably all network shares (CWDIllegalInDllSearch=2). I’m curious why there is no setting to disable CWD on removable media like USB keys without cranking CWDIllegalInDllSearch all the way to 0xffffffff and disabling CWD globally.

Microsoft needs to provide a GUI and a Group Policy for managing the keys for disabling loading libraries from CWD. The Group Policy option is critical for Enterprise so that they can keep legacy apps running which can’t be modified. They also need to make it clear that loading from CWD is going to be deprecated very soon and will no longer be the default behavior in the next version of Windows.

Microsoft should also provide guidance that any app which depends on loading libraries from CWD is vulnerable. In particular, legacy line of business apps which cannot be made to run without loading libraries from CWD should not be allowed to run on a computer with network access because such apps will be juicy targets for spear phishing. In a lot of cases it should be possible to fix apps that load libraries from CWD by just moving the DLLs into the same directory as the EXE. If the app can’t be fixed, it needs to be sandboxed from the network.

%d bloggers like this: