Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Thursday, June 23, 2022

PetitPotam Defenses

Protection against coerced authentication on domain controllers:



Print Spooler:


Disable the service via group policy on all DC's

EFS RPC attack:



Create the two RPC filters by putting this in a text file (source):

rpc
filter
add rule layer=um actiontype=block
add condition field=if_uuid matchtype=equal data=c681d488-d850-11d0-8c52-00c04fd90f7e
add filter
add rule layer=um actiontype=block
add condition field=if_uuid matchtype=equal data=df1941c5-fe89-4e79-bf10-463657acf44d
add filter
quit


Save the file and use "netsh -f filename.txt" to apply it


DFS RPC attack:



Create one RPC filter by putting this in a text file (source)

rpc
filter
add rule layer=um actiontype=block
add condition field=if_uuid matchtype=equal data=4fc742e0-4a10-11cf-8273-00aa004ae673
add filter
quit


Save the file and use "netsh -f filename.txt" to apply it

This dfs filter has some impact on creation of new dfs namespaces. Otherwise it doesn't seem to cause other issues that I can tell.


Certificate Authority hardening:


Follow the MS guidance on hardening the CA against NTLM relay. Essentially you configure the web interfaces to allow kerberos only with extended protection. If possible, disable NTLM auth completely on the server. Beyond that, limiting access to client certificates and not allowing user supplied SAN's on them should be done.

Thursday, March 7, 2019

Restricted windows logon for kids - browser kiosk

Whenever kids seem to want to use the computer for homework or studying, they quickly drift off into other activities and develop super senses to hear the coming of a parent in order to click all the non-study related content away.  So I looked into possible ways to restrict to specific sites or apps.  Lets assume we're looking at restricting kids to only access Khan Academy for study courses, videos and exercises.  With mobile devices, some have kids modes, where you can restrict the interface to only a few specific applications.  I know the ASUS zen interface has this option under settings->advanced for android devices.  But if the kid doesn't have such a device, but does have a windows machine, you can do some work to limit what can be done on it.

The following is a rough template for setting up windows 10 home with a restrictive logon.  Other windows OS's may work well with most of these steps.  I'm not going to dumb it down into all the specifics of how to do everything with screenshots.  If anything gets confusing, google it.

1) Create a new child account in the family.  Configure it as you wish in terms of time restrictions and application restrictions, but ensure the chrome web browser is an allowed application.  As an added restriction to internet access, you can set up allowed websites in the Microsoft family website.  Leaving this blank will block everything, at least for use within internet explorer.  For family management to work properly, you need to ensure diagnostics is turned on.

2) install chrome, if you haven't done that already.

3) Log on as the new child and open up chrome.

4) Install the extension xTab and configure it for a maximum of one tab.  This will prevent any open in new tab and tab switching. You can add any other security extensions that you want for additional privacy and security (ex: adblock, privacy badger, etc).

5) Switch users to an administrator/parent account

6)  Create an html file somewhere on your machine, let's call it home.html.  This file needs to be accessible to the child account, however for best practice, it should be in a folder that the child does not have write access to.  Lets say you create a folder name c:\shared, and set permissions on it to allow the child read and execute permissions. 

If you want to have more than one site available, then add additional a href lines pointing to those sites.

7)  Create a batch file in this shared folder as well.  Lets call it chrome.bat.  Put this in the content

@echo off cd \"Program files (x86)\Google\Chrome\Application\" start /wait chrome --kiosk --chrome-frame --allow-file-access-from-file file:///C:/shared/home.html shutdown /l

This batch file runs chrome in kiosk mode and holds chrome in the foreground before running the "shutdown" command with the logoff option.  This will cause the account to logoff as soon as chrome is closed with "alt-f4"

8)  Switch back to the child account's logon.

9) open task scheduler from the start menu, and go to Task Scheduler Library.

10) right click that and select "Create task".  Give it a name.  Go to the triggers tab, click new.  At the "Begin the task" pull down, select "At log on".  If the "specific user" option is available, make sure to select only the child account.  Leave everything else as default and click ok.  On the actions tab, click the browse button, and navigate to c:\shared\chrome.bat.  Click ok.  Go to the conditions tab and uncheck all the power options.  Go to the settings tab and uncheck "stop the task if it runs longer than".  Click ok to save the task.

11)  Open up registry editor.  Go to HKey current user -> Software->Microsoft -> Windows NT-> currentversion -> winlogon.  If there is no value called "Shell", create a new REG_SZ value with the name "Shell" and value of "rundll32".  This will prevent the default windows explorer interface when the user logs on.  There will be no start menu, desktop or task bar.

12) In the child's chrome instance, go to settings, set "show home button" to enable, and set the home button value as "file:///C:/shared/home".  This will allow the child to use "alt-home" to get back to your custom html file in case you have more than one site listed.  It will save a lot of going backwards to get back to the original start page.

13) Switch back to your parent/administrator account.  Open registry editor.  Go to HKEY local machine -> Software -> Microsoft -> Windows -> CurrentVersion -> Policies -> System.  Look for a registry key called "DisableTaskMgr".  If that is present, set the value to 1.  If it is not present, create a new REG_DWORD with that name and set the value to 1.  This will disable the task manager option from the ctrl-alt-del menu.


That should complete the set up.  Logoff of the child account and log back on.  You should get a chrome window opening automatically, with most of the buttons and menu options missing.  Keep in mind that the browser can still get to any site is linked from any of your listed where's that you give them. So if they can get to a search engine, they can get anywhere.  You can find addition chrome extensions that block specific sites. So, those can be used to limit certain pages. YouTube blocks by these extensions can allow embedded video and still prevent direct YouTube access by right click to view on youtube. That is another potential way to break out of this limited mode.

Thursday, July 21, 2016

"SSLv3 Information Disclosure Vulnerability" - Dell Openmanage

If you have vulnerability scanners flagging systems for SSLv3 related vulnerabilities, check your Dell OMSA version. Versions earlier than 8.x are configured with weaker protocols, as seem in the server.xml in \program files\dell\sysmgt\apache-tomcat\conf

OMSA 8.x

<Connector compression="force" SSLEnabled="true" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>

--------------

OMSA 7.x

<-- <Connector port="1311" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> --> <Connector compression="force" SSLEnabled="true" address="*" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" ciphers="SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"/>



You can test SSLv3 connections with openssl.

Server with OMSA 8.3

C:\>openssl s_client -connect OMSA8server-ssl3 Loading 'screen' into random state - done CONNECTED(00000230) 12252:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:./ssl/s3_pkt.c:284:

Server with OMSA 7.3

C:\>openssl s_client -connect OMSA7Server:1311 -ssl3
Loading 'screen' into random state - done
CONNECTED(00000230)
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify return:1
*snip*
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : SSLv3
Cipher : EDH-RSA-DES-CBC3-SHA
Session-ID: 57901ECD7AE62B7F65EFA4160F2106E5ED39AB0BC5E53FEA6AD8359F7DC01AAB


Session-ID-ctx:
Master-Key: B37B02F7037C019E471A564F56629C1FBF45967F120DF631A15DCA048202CD2F069C9628116DAA00BB93466EDF5FA2E8
Key-Arg : None
Start Time: 1469062860
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

"TLS/SSL RC4 Cipher Suites Information Disclosure Vulnerability" Dell OpenManage

If you have vulnerability scanners flagging systems for RC4 related vulnerabilities, check your Dell OMSA version. Versions earlier than 8.x are configured with weaker protocols, as seem in the server.xml in \program files\dell\sysmgt\apache-tomcat\conf

OMSA 8.x

<Connector compression="force" SSLEnabled="true" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>

--------------

OMSA 7.x

<-- <Connector port="1311" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> --> <Connector compression="force" SSLEnabled="true" address="*" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" ciphers="SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"/>



You can test cipher's with openssl. The example below is RC4-MD5. The format of available cipher commands in openssl is different than the tomcat configurations above. You can run "openssl ciphers" to get the list.

Server with OMSA 8.3

C:\>openssl s_client -connect OMSA8Server:1311 -cipher RC4-MD5
Loading 'screen' into random state - done
CONNECTED(00000234)
11868:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:./ssl/s23_lib.c:188:


Server with OMSA 7.3

C:\>openssl s_client -connect OMSA7Server:1311 -cipher RC4-MD5
Loading 'screen' into random state - done
CONNECTED(00000230)
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify return:1
---
Certificate chain
0 s:/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
i:/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
---
Server certificate
-----BEGIN CERTIFICATE-----
***
-----END CERTIFICATE-----
subject=/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
issuer=/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
---
No client certificate CA names sent
---
SSL handshake has read 1044 bytes and written 359 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID: 57901EA40CB03FB263CDC30D1B77107D9B872C0BB8D9DF655981A3AA3DA67C94


Session-ID-ctx:
Master-Key: 707E2C192E1ED22E22684CBEF9B1EC139F6EA00456AFE5B6E473242064006D9C86F3D85E0CBAEC39697D82CE65F6BA4D
Key-Arg : None
Start Time: 1469062820
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---

Wednesday, March 12, 2014

Parsing DNS Debug logs (microsoft)

I have played around a few times with methods of parsing the ugly data lines that come with Microsoft DNS Server's DNS debug log. Due to the differences in types of queries, there is no fixed number of "columns" defined by spaces. Since this is the delimiter, it causes issues in parsing. Besides that, there is the messed up hostnames in the query values that replace the periods with a parenthesis and length of chars in the following value. As logs can get quite large, trying to parse these with powershell can have mixed results. Sometimes it works ok, other times you watch the process grow to several GB of memory utilization and nothing is happening. So, to find a better way, I thought I would dust off the old Unix Shells by Example book and use some gnuwin32 versions of grep, awk and sed to take care of this file. In order to get down to the raw information that I care about, I'm looking at queries received by the server, the source IP, type of record being searched, and the hostname being looked up. To get this I came up with this to transform to csv output:


   grep.exe Rcv c:\temp\dns.log |grep " Q " | gawk -v OFS="," "{print $8,$14,$15}"| sed -n "s/([0-9]*)/./gp"|sed -n "s/\,\./,/gp"|sed -n "s/\.$//gp"

The $8,$14,$15 numbers represent text columns and you may need to adjust this based on output. Also the number of columns may be inconsistent as the data that shows up between the brackets is not always consistent in the log. You can use notepad++ to do a regex find/replace using \[.*\] to clear this out first. Once columns are aligned this output can be dumped to the script, but if you try to put a redirector to dump to text, it will do it, however it seems grep will give you an infinite loop of errors.  So to work around that, you can split this up into two commands.

First use grep:
   grep.exe Rcv c:\temp\dns.log |grep " Q " > temp.txt

Then:
   gawk -v OFS="," "{print $8,$14,$15}" temp.txt | sed -n "s/([0-9]*)/./gp" | sed -n "s/\,\./,/gp" | sed -n "s/\.$//gp" >output.csv


If you want to add the name of the dns server, you can put an extra sed command right before the output rediection
   sed -n "s/^/%computername%,/gp"
if you run it locally, otherwise put in text or some other defined variable there


Additionally you can play with the output, such as looking for source IP's
   awk -v FS="," "{print $1}" output.csv|sort |uniq -c
To get a list of unique client IP's and number of queries


Don't try to run this in powershell. Run in cmd or as a bat file, collect the csv and then you can import to powershell to play around with grouping or whatever you might want to do to see client behavior or records being queried.  If your file is large (I was testing with 200MB), you still won't want to try import-csv in powershell or your machine will grind to a halt.

You can use powershell to try to convert your source IP addresses to hostnames with reverse dns. Copy the text, dump to a variable, split by new-line, run through a foreach loop with: [net.dns]::GetHostByAddress($_).hostname

Additional reference and tools:
1) Gnuwin32 utilities, *nix tools for windows:  http://gnuwin32.sourceforge.net
2) Parsing logs other DNS logs  http://isc.sans.edu/diary/A+Poor+Man%27s+DNS+Anomaly+Detection+Script/13918
3) Reasons why this can be important: https://media.defcon.org/DEF%20CON%2021/DEF%20CON%2021%20video%20and%20slides/DEF%20CON%2021%20Hacking%20Conference%20Presentation%20By%20Robert%20Stucke%20-%20DNS%20May%20Be%20Hazardous%20to%20Your%20Health%20-%20Video%20and%20Slides.m4v

Monday, January 14, 2013

Delegating WMI security remotely with powershell

A while back, I was working on a script for checking domain controller security event logs which needed to be handed off to a team that was not part of the Domain Admins group.  While they had permissions to access the security event logs through user rights in GPO, trying to read the event log through an MMC remotely is ridiculously slow.  A good solution was to use WMI with a tight filter for event ID's and a brief time window for the specific event.  The problem was, none of this team had WMI access.  So to go about fixing a few hundred domain controllers, I started poking around at WMI permissions.  You can edit this through the MMC->Component Services console.  But doing this via RDP on such a large scale is not an option.  There are some script examples in VB, such as this one.  But, being a powershell guy, I wanted to use some existing code and wrap in the additional lines to update the security.  So, what I did was created the permissions that I wanted on one specific machine (similar to the above article), and use powershell to pull the security descriptor.  The example below is delegating the common root\CimV2 namespace which contains the event log event classes.


#Collect your security descriptor

$sd = gwmi -namespace "root\cimv2" -Class __SystemSecurity -ComputerName $FixedMachine
$sdhelper = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$binarySD = @($null)
[void]$sd.PsBase.InvokeMethod("GetSD",$binarySD)

#At this point you can loop through a list of machines and push out the updated permissions.
$sdlocal = gwmi -Namespace "root\cimv2" -Class __SystemSecurity  -computername $remotemachine
$sdhelper2 = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
[Void]$sdlocal.psbase.invokemethod("SetSD",$binarySD)



For more details on the various types of permissions, you can reference this technet article.  For remote read-only, you can go with "remote enable", and "enable account".


Thursday, July 28, 2011

Strange source of lockouts seen on the ISA server

A few times in our environment we have seen user account lockouts showing up on the ISA servers. These are configured to require authentication in order to allow proxying. In this type of case 90% of the time, the problem will be at the user's workstation. There can be several causes, and it is typically internet enabled applications that don't support windows authentication against proxies. When they receive a request to authenticate, some applications are really stupid and think they are authenticating against their remote service's servers, sending whatever 3rd party username/password combination to your proxy server. If the user name is the same as you domain user ID, you get locked out (have seen this with Skype). Others may allow user's to provide their username and password, and later on after the domain account password is changed, users forgot they where they typed it in. In rare cases, there are applications that find their way into caching domain credentials, but not always keeping up to date with them. The case I will present here is the later, and the details are incomplete.

When you see the proxy server locking out a user, when checking their machine, first look at every obvious internet enabled application. Sometimes you can obviously find something and update it or remove it. If you are still not sure, I recommend installing microsoft netmon 3.3 or higher on the workstation and running it for a while until the next bad password attempt shows up. The advantage of this network capture software is that it can provide the process name or process ID of the application that is doing the communication. Look for the HTTP requests and typically you will want to look for plain text authentication attempts as your culprit. Use this filter:

HTTP.Request.HeaderFields.ProxyAuthorization AND HTTP.Request.HeaderFields.ProxyAuthorization.Authorization.BasicAuthorization.Scheme == "Basic"

In the case I am bringing up, the process name was not provided and the ID was 4. PID 4 is system processes/system services. The packet capture showed plain text authentication using the user's previous domain password. Since it is a system process, we looked at the system services and came up with Akamai NetSession Interface service. This is something that installs as a download manager or similar software that Adobe is bundling with some of its downloads. I didn't get into a deep dive inspection of the machine to see where it manages to cache this plain text password, but this sounds like a good security project for someone to look at. If the software is grabbing domain credentials at some point, it would be nice to know the controls around it. In any case, this issue has come up several times in our environment with the same service. Disabling or removing fixes the problem. The problem may only come up in certain versions or due to some specific use case as we have only seen this a handful of times although there are over a hundred machines with the service.

I hope this information is helpful in troubleshooting this type of authentication failure and lockout source. For additional information on account lockouts, you can visit my account lockout tracking general practice page.

Wednesday, January 5, 2011

DES encryption, Kerberos and 2008 Server

When dealing with Windows 2008 servers as domain controllers, mixed with legacy applications, you may run in to a problem with encryption support. Older software and platforms may be set to use DES encryption. This has been disabled by default on newer Microsoft OS's including 2008R2 and Windows 7. There are ways to get the support turned back on, though for security reasons this is not recommended. DES uses a weaker key than the other available methods, and most systems should support the windows standard of RC4-HMAC.

Identification of DES usage in your environment:

1) Netmon. Using the older Microsoft version of netmon, you can monitor your domain controllers and look for kerberos traffic that is using encryption other than RC4-HMAC. To do this, run a capture and create a display filter as follows:

AND
|---Kerberos: Encryption type (Etype[0]) <> 0x17
|---Protocol == KERBEROS
|---Any <--> Any

This will show all Kerberos traffic that is not using the standard. This may also find other types such as AES if you are using the latest and greatest. Since there are several types of DES encryption formats for Kerberos, this filter method is the simplest, but you can also create a multiple set of OR statements on that Etype value. Refer to the RFC's to get the values of each.

2) Kinit: If you are already seeing problems with kerberos authentication for certain applications, you can use kinit with debugging options to request a ticket for that service. This can show you if you are getting a bad Encryption type error. Here is one example using java and a keytab:

java -Dsun.security.krb5.debug=true -Dsun.security.krb5.krb5debug=all sun.security.krb5.internal.tools.Kinit -k -t HTTP.keytab HTTP/myservice@MYDOMAIN


-result snip-
Found unsupported keytype (23) for
HTTP/myservice@MYDOMAIN
-/result snip-


3) Searching for DES enabled AD accounts:
Ldap filter: (&(|(objectcategory=user)(objectcategory=computer))(userAccountControl:1.2.840.113556.1.4.804:=2097152))

This will find all DES enabled computer and user accounts in your search scope. You can search the serviceprincipalname attribute to see what applications may be using DES.

4) Kerberos event log events on the DC's



5) Errors in application logs.  ETYPE not supported and similar.  Some logs will show types of encryption configured.  Check java versions (1.4.x and earlier don't support RC4-HMAC).  Check krb5.ini and krb5.conf files for encryption type configurations.

Fixing the problem

There are two ways to go about getting around this problem during an upgrade. First, you can try to identify all of the uses of DES and get rid of them, or you can enabled DES support.

To get rid of DES usage, look for capability in the application for RC4-HMAC or other support encryption standard. Check the application, check the versions of java it uses, etc. If it is java, anything 1.5 and higher supports RC4. Check all the krb5.conf files to ensure any supplied enctype values allow for RC4-HMAC


[libdefaults]
default_tkt_enctypes = rc4-hmac
default_tgs_enctypes = rc4-hmac
permitted_enctypes = rc4-hmac

Do your testing and push the appropriate application owners to do what they can to get away from DES. If keytab's are in use, ensure they are recreated with the appropriate encryption.

If you have applications that cannot get rid of DES, you can look at the steps required to enable DES support on the OS. There are two parts to this. First you will need to patch your 2008 domain controllers with KB978055. This gives the DC the ability to issue DES tickets. If your clients are windows 7 or 2008R2 server themselves, they will need to have some configuration changes. This can be done by a registry fix, or pushed by group policy. Refer to this article for that. When changing the client settings, be careful that you allow all of the required encryption types. If you use a GPO to turn on DES, and don't specify anything else, your machine will only use DES.

UPDATE (2/11/2012): After having the above patch fail to install with an error that it is not applicable, it seems that the patch was rolled into Windows 2008R2 service pack 1. So if you have the service pack installed, you should be fine on the domain controller side.


UPDATE (10/2/2012):  Apparently not all versions of service pack 1 would have this fix.  General distribution release versions of the SP won't have it.  You can check http://support.microsoft.com/?id=2425227 and http://support.microsoft.com/?id=2029058 to get hotfixes for updating the KDC service.  Also ensure that your group policy allowed encryption types include the Future encryption types.  Don't ask why, but for some reason in my testing having everything but that causes DES to fail in some case, while checking it causes it to suddenly work.

Wednesday, November 24, 2010

GPO software restrictions

There is a feature in group policy called software restriction policies which allows you to try to block users from running certain specified applications (black listing), or provide a list of applications which are allowed while blocking all others by default(white listing). There are several types of rules you can create:

Hash Rule: Crypto hash of the binary file
Certificate: A software publisher certificate that was used to digitally sign the file
Path: The file path or registry path to the file
Zone: What internet zone is used.

These types of rules can help to guard against predictable malware or certain versions of applications. The problem is that they are frequently very easy to get around.

Hash Rule (avoiding blacklist)
Lets assume our block rule covers txdns.

C:\Users\nl\Downloads>md5sum txdns.exe
f59a3d8e94f0f61130874fd794c38aa7 *txdns.exe

Using a hash rule to block something like this requires some considerations. First, every version and every patch level will have a unique hash. For applications that are frequently updating, you will never be able to keep up with them. If you have a file that has limited versions and no further development, it is still trivial to bypass this. Most files will have some text strings inside the executable. If we open txdns.exe with a hex editor, and immediately we see a string "This program cannot be run in DOS mode". We can change the T in This to lower case without effecting the program.

C:\Users\nl\Downloads>md5sum txdns.exe
42e19fdaeda1a12f21af5512396f37b9 *txdns.exe

Here we can see our hash is radically different than the original. A GPO administrator can't get around this with their blacklists. So what would blacklisting a hash be useful for? There may be a rare case where you encounter a specific and non mutating virus/malware that is in your organization. If you can throw up a hash rule and have systems update group policy, you can help to reduce the spread by this type of policy.

Certificate rules

It would be a bit rare to blacklist something that is signed. Many exe files won't be signed. If they are, and you have a specific one to block, you can look in the file properties to see the signature, and extract the certificate. Load this into a rule to block the software. This may work for something like Stuxnet that is reported to be signed by several stolen certs. Certificate rules would be primarily used in white listing mode, but again many exe's are not signed, or they may be signed with many certs. If you go looking through Microsoft software and downloads you will find either no signing or multiple certs used. Trying to keep up with external vendors' signed applications would take a lot of effort. If you were white listing a limited number of apps for a smaller set of machines, then this may be a useful method for one rule of your whole GPO.

Path rules

Getting path rules to work well in a blacklisting scenario would require a well locked down system to start with. Targeting a specific file using a standard install path would be pointless as the application could be moved or installed to a non standard location. If a user did not have access to create files and folders outside of their own home directory, you could blacklist everything in their profile to prevent execution of all code and scripts. Path rules allow for wildcards. So if you specify c:\documents and settings\*, no executable files can be run in this folder or any subfolders. This also includes attempts to access these files/folders using 8.3 format directory names. In the main policy settings, you can specify the extensions of files to protect against. You can try renaming the extension of a file such as file.exe to file.1 and trying to run it from cmd.exe. This will attempt to execute the file, but the system still sees it as the appropriate file type and blocks it. So, in general, if you need your systems to be extremely locked down, path rules can be a powerful addition.


The software restriction policy mechanism is being replaced by applocker, which is available in windows 7. It is possible to use both in policies, but only the newer OS's can process the applocker rules. I have yet to look at applocker, and I hope it is a step in the right direction for security and manageability.

Friday, October 29, 2010

Personal firewalls

It has been a while since I messed around with firewall rules, and apparently I should get back into it. Recently I had to rebuild one of the home computers to put Windows on it. Initially (pre antivirus install), I shut down all the non-essential windows vista default services that I could think of and left the basic Microsoft provided firewall running. To check for any obvious opening, I ran a basic nmap Syn scan


Starting Nmap 4.75 ( http://nmap.org ) at 2010-10-24 14:46
Initiating ARP Ping Scan at 14:46
Scanning 192.168.2.3 [1 port] Completed ARP Ping Scan at 14:46, 0.01s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:46
Completed Parallel DNS resolution of 1 host. at 14:46, 0.02s elapsed
Initiating SYN Stealth Scan at 14:46 Scanning 192.168.2.3 [1000 ports]
Completed SYN Stealth Scan at 14:47, 21.88s elapsed (1000 total ports)
Host 192.168.2.3 appears to be up ... good.
All 1000 scanned ports on 192.168.2.3 are filtered MAC Address: 00:23:AE:1B:1F:6E (Unknown)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 22.08 seconds
Raw packets sent: 2001 (88.042KB) | Rcvd: 2 (98B)


Looks ok to me. So after buying antivirus (customer wanted Kaspersky), we got the Kaspersky Internet Security 2011 suite. It looked interesting for features, and the firewall component took over for windows firewall. Using the standard config, I ran the scan again afterwards.


Starting Nmap 4.75 ( http://nmap.org ) at 2010-10-24 14:20
Initiating ARP Ping Scan at 14:20 Scanning 192.168.2.3 [1 port]
Completed ARP Ping Scan at 14:20, 0.11s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:20
Completed Parallel DNS resolution of 1 host. at 14:20, 2.52s elapsed
Initiating SYN Stealth Scan at 14:20 Scanning 192.168.2.3 [1000 ports]
Discovered open port 49156/tcp on 192.168.2.3
Discovered open port 49153/tcp on 192.168.2.3
Increasing send delay for 192.168.2.3 from 0 to 5 due to 53 out of 176 dropped probes since last increase.
Increasing send delay for 192.168.2.3 from 5 to 10 due to max_successful_tryno increase to 4 Discovered open port 49155/tcp on 192.168.2.3
Increasing send delay for 192.168.2.3 from 10 to 20 due to 12 out of 39 dropped probes since last increase.
Discovered open port 49152/tcp on 192.168.2.3
Increasing send delay for 192.168.2.3 from 20 to 40 due to 14 out of 45 dropped probes since last increase.
Discovered open port 139/tcp on 192.168.2.3
Discovered open port 135/tcp on 192.168.2.3
Discovered open port 49154/tcp on 192.168.2.3
Discovered open port 1110/tcp on 192.168.2.3
Completed SYN Stealth Scan at 14:20, 38.70s elapsed (1000 total ports) Host 192.168.2.3 appears to be up ... good.
Interesting ports on 192.168.2.3:
Not shown: 992 closed ports
PORT STATE SERVICE
135/tcp open msrpc
139/tcp open netbios-ssn
1110/tcp open nfsd-status
49152/tcp open unknown
49153/tcp open unknown
49154/tcp open unknown
49155/tcp open unknown
49156/tcp open unknown
MAC Address: 00:23:AE:1B:1F:6E (Unknown)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 41.58 seconds
Raw packets sent: 1154 (50.774KB) | Rcvd: 1009 (40.612KB) dfkj123:/home


Well that's interesting. Basically the suite sees several zones. Anything on your local network, it seems to be happy with. So if you're on some public wifi spot, you're screwed. Also, most common Microsoft and commercial apps get whitelisted and all hosts (internet wide) are allowed full access. Seriously? Trying to shut all that down and fix it to something sane was looking like a near impossible task, so for simplicity I actually had to disable that and fall back to Microsoft. I hope their AV component doesn't act as badly.

Friday, September 24, 2010

Remedy Password Obfuscation

Recently I was checking around for possible sites that were sending plaintext passwords in the clear. One such application I tested was BMC remedy 7.x. Although it doesn't send completely clear passwords, it might as well. Here is the javascript code on the login form for password handling prior to a POST operation.

function getScrambledPassword(pwd) {
   var cipher = ['k', 's', 'z', 'h', 'x', 'b', 'p', 'j', 'v', 'c', 'g', 'f', 'q', 'n', 't', 'm'];
   var result="";
   if (pwd == null)
       pwd = "";
   pwd = encodeURIComponent(pwd);
   //alert("encoded password: " + pwd);
   for(var i=0;i < pwd.length;i++) 
       var cc="pwd.charCodeAt(i);
       result += cipher[Math.floor(cc/16)] + cipher[cc%16];
   }
   return result
}


The login page uses this function to "Scramble" the password using a fixed set of constants in the array. If you search around google for remedy pages "inurl:arsys inurl:login.jsp", you will find the same set of ciphers on every page you check. Some sites have https pages, while others do not. In case, the scrambled password above uses a simple operation to convert to numeric values, and creates to characters for every one character of original password. Lets assume our password is "Password". When you post the form, the value sent is bkpsjhjhjjpmjzpx. Since we have 2 characters of cipher text for each one of non-cipher, lets take the first letter: bk

From the calculations, first we have a divide by 16 which equals 5 according to our array. X/16 = 5 -> 5*16 = X = 80. This is rounded down, so we have a original value of anything from 80 to (80 + 16 -1 = 95). Now the second value k is a 0. This is a modulus of the original number and 16. This value is added to our first character to get the original. 80 + 0 = 80, which our handy ASCII table says is a P.

Keep going with the remaining characters and you get the full original password. So, always use https. If you can come up with a better authentication method, do it.

Monday, August 9, 2010

The ISATAP/WPAD query patch (WINS and DNS)

While working on my powershell netbios name library, I came across the bulletin for blocking by default, all replies for WPAD and ISATAP to Windows WINS and DNS servers. Given that you can register arbitrary DNS host records and wins records without any validation that your source machine has that name, this is a good thing. The problem that this bulletin didn't think to address is the netbios node types of the client machines. Typically clients will be configured as hybrid nodes, which means that if they have netbios enabled, and DNS does not resolve a name for them, they will attempt name resolution with WINS, followed by a IP directed broadcast to their subnet looking for that name. I noticed in netmon captures, that machines are certainly looking for ISATAP and WPAD with great frequency. Some cases show broadcasted queries with FQDN formats of these entries as well. This should be related to the period being a special character in netbios names. I suspect that at some point in the search list suffixes being appended, the resolver passes a DNS format name to netbios resolution and it goes out on the wire like that.




In any case, the fact that these requests are being broadcast out, leaves the original issue open as a security problem. It would be quite trivial to have a malicious machine responding to clients and offering to be their web proxy. Inject some browser exploit of your choice and start pwning machines.

As WINS and netbios is getting quite old, if you really really still need WINS on your network, why not switch your clients to P-Nodes, so they don't broadcast?

Friday, July 30, 2010

Dynamic DNS without the [DNS]

I have been poking around at Microsoft name resolution system investigations that became a side project of computer account security research. I was looking at the ability of computer systems to use the DNS protocol to register names other than their own to see if any additional records could be created for a specific host name. The findings there are that hosts can register names other than their own, but if there is a record already present for the name they are trying to register, and that computer account (or user account) doesn't have rights to update, then it fails. This is good from a security perspective, but shows some limitations for usability and advance configurations provided from a level closer to the user or machine.

In the process, I took a deeper look at Active Directory integrated DNS zones to see how everything is represented. First off, DNS zones can be found in several different locations inside of Active directory. This is based on their replication scopes. For those not too familiar with AD and AD DNS, briefly, the advantages of Active Directory DNS is that it is made highly available through the fact that it is stored in the Active directory database, and all changes are replicated as part of standard AD replication. This allows records to be updated with small updates instead of larger zone file transfers that work on a scheduled timeout period. Additionally, in secure dynamic updates, updates are authenticated through Kerberos and the records are owned by the updater.

Back to replication... There are 4 options for Dns zone replication scopes in AD. This is Legacy, Domain, Forest, and application partition. Here is some information about each:

1) Legacy. This zone will be stored in the standard domain partition, under the Cn=Microsoft DNS,CN=System organizational unit in the dc=yourdomain,dc=com partition. A zone will appear as a container icon, and is of the class dnsZone. The problem with this type of zone is although it is only available in the scope of its own domain, it is part of the domain's system contain and will replicate as part of the global catalog to other domains. So you waste space and replication traffic sending information to other domain controllers that cannot use this information.

2) Domain. This zone is stored in a separate partition DC=DomainDnsZones,dc=yourdomain,dc=com. This partition is only available on domain controllers that are running the DNS service. So, replication is limited to only where the records are needed, and it only stays in that one domain.

3) Forest. This zone is stored in a separate partition DC=ForestDnsZones,dc=yourdomain,dc=com. This partition will replicate to all dns servers in the forest. It is only hosted on domain controllers with dns installed.

4) Application. If you create your own custom application partitions, you can use them to store DNS. Also you can chose where the application partitions replicate. For DNS, this may be useful if you want specific zones only located in DC's in a certain city, but it requires more manual work to manage it.

If you look inside adsiedit at the dnsZone containers in these partitions, you will see dnsNode objects for records. The object will be named DC=. Example, if you have the zone mycompany.com. The record www.mycompany.com will have the name DC=www. Inside each of these objects is a dnsRecord attribute. This is multivalued, so if www.mycompany.com had several records for 3 different host machines, you will see 3 dnsRecord values. The dnsRecord itself is all in hex. The type of Record (A, CNAME, SRV, etc) is all within the hex, along with the values, timestamps, ttl, etc. (Hopefully I will get back on track to decoding these on of these days)

The interesting point to all of this is that we are looking at the records in LDAP. Typically records are generated through the DNS service using authentication from a workstation. The DHCPClient service registers the hostnames of the machine, and uses the computer account to own the record. When you look at the permissions of the dnsZone object's in LDAP, authenticated users has Create All Child Objects rights. This gives any user or computer the ability to go and create their own records outside of the whole DNS protcol, and built in methods. So, if you needed to create additional dnsRecords on a dnsNode object that you own, you can do that. If you want to dynamically create CNAME, SRV or other records, you can. If you want to dynamically create a DNS record that can't be scavenged, no problems.

Someday I hope to work out a basic tool or script for some of this, but presently I'm still too lazy to finish up my nbtns powershell library for doing all of the netbios name and WINS protocol functions through powershell.

The DNS tunneling possibilities to this are interesting, if you have AD DNS exposed to the outside world.

Wednesday, July 14, 2010

Finding account lockout source (general practice)

A lot of escalations come my way regarding difficult account lockout issues, and repeat lockout events. Over time, I took some of the methodology I used in tracking down the root source of the failed logon and put it into an auto tracker script. This runs quite quickly using WMI's WIN32_NtlogEvent class with a very tight filter for the timegenerated attribute. When providing and upper and lower limit, searching event logs can be done very quickly on remote machines. This is important as in most cases you may traverse through 2 or 3 machines to get to the originating machine.

When starting to track down a lockout source, either manually or through automated practice, you will check the bad password timestamps for all domain controllers [this is an ldap query to all writable domain controllers so it can be slow. Alternatively a much faster approach is to read the metadata of that attribute on the PDC only to get the time and source]. You can do this with ldap queries to each one, or use the microsoft lockoutstatus tool. Ldap queries will allow you to script it. The key point here is that the PDC will always have the most recent bad password time, even if the events are not located on that machine. So for automation purposes, I simplified the process by ignoring the PDC. You could always find the most recent reported event and compare it to see if the PDC is more recent by at least a few seconds to see if the PDC is where you should look. It is also important to note that you are assuming the last bad password time that you are looking at is related to the problem and is not something else like the user mistyping a password. This may require several runs of an automated script to see if you get different sources.

From the bad password time stamp, you can go to the security log for that domain controller, filtering for failure audits and check the event text or InsertionStrings to get the source machine or source IP. Different event ID's have different information. Some failed logons will not show up in the log, or may have a blank source. In this case it is important to have netlogon debugging enabled so you can check the netlogon.log, as it may contain more details for the source. In netlogon, you want to look at the entry in parenthesis that shows via XXXXXX. Ensure the code in the line is a failure, and not success, so you don't chase the wrong entries. For automating, it is helpful to have some code that decodes the various security event hex codes and integer values to plain text for display purposes (my code).

When looking at sources in the event log, you need to carefully check source IP and source workstation if both are present. Sometimes they differ, and the source workstation may be the machine you are already on. Sometimes it is best to use the IP as a preferred value for source. Go to the source machine and look at the security logs there for additional information. When you get down to workstations and member servers, you may get process id's and port information that can help narrow down to a process. Checking logon type codes can be a dead giveaway for scheduled tasks and services with bad cached passwords.  On some occasions you will not see a source machine in the security log.  If this is the case, you will want to enabled netlogon debugging (from command prompt use: nltest /dbflag:0x2080ffff.  Some logon events will show up there, and you can get further source information from the events.  Just search the text files in c:\windows\debug\netlogon* for the user name and look for other machine names in any event that doesn't have a 0x0 status.

You can look at my high level overview for how I wrote my tracking script. For security events, I had to identify some standards between each event ID's I wanted to work with and use insertionstrings to provide a standardized generic PSObject that can be provided by parsing the available information.



Some useful commands to find uses of an account on a local machine (open powershell as administrator, set the target account name without domain)

$targetaccount = "johndoe"

write-host "`n checking services"
gwmi win32_service |select name,startname | where {$_.startname -match $targetaccount}

write-host "`n checking processes"
gwmi win32_process |select name,@{name="ownerdomain"; exp={$_.getowner().domain}},@{name="owneruser" ; expr={$_.getowner().user}}  | where {$_.owneruser -match $targetaccount}

write-host "`n dumping any IIS appPools"
c:\windows\system32\inetsrv\appcmd.exe list apppool /text:* |where {$_ -match "APPPOOL\.NAME|userName"}

write-host "`n checking remote desktop connections"
qwinsta

write-host "`n checking scheduled tasks"
schtasks /query /v -fo CSV | where {$_ -match $targetaccount}

write-host "`n checking mapped network drives for currently logged on user"
dir hkcu:\network

Friday, May 21, 2010

Creating infinite semi-anonymous accounts in Active Directory as a standard user

I have been looking at computer accounts on and off over the last few months for various security risks associated with them, and found a few interesting things. One of which is a default configuration for active directory that allows users to join a limited number of computers to a domain without having any specific delegated rights to do so.

Note: if the domain has been modified to drop the quota of allowed joined computers to zero, and a few other methods can block this, so it will only work in a Active Directory environment where low level customizations have not been done. In all versions of windows 2000 - 2008RC2, by default, users have a quota of 10 computers accounts which is controlled by the ms-DS-MachineAccountQuota attribute in the Domain's top level object. If you are an AD administrator, go set this to zero right now.

There are a few interesting points to this. When I say that a user has rights to join a machine, they cannot directly create a computer account in active directory using management tools as they don't have the rights. However, the act of joining a machine to the domain works (obviously), or you can just use netdom to create the computer account without joining any real machine. You may be saying, so what, its just a computer object. If you read my previous post about accounts that can't be locked out (computer accounts), you will also see the default permissions on computer objects give excessive rights to the creator/owner of the object. This allows for some continued problems.

When the end user creates a computer object, I refer to it as being capable of being a semi-anonymous generic account. The reason for semi-anonymous is that the user is the owner of the object and they don't have permissions to change the permissions, also there is an attribute mS-DS-CreatorSID which will be filled in with the creating user's SID. To create a layer between one of these computer accounts and a user object, if you have Admin rights to a machine you can schedule tasks to run under the BUILTIN\System context. In this case, the computer running the task will own the computer object. If a machine has multiple administrators, this creates a deniability layer between the user and the computer object. Otherwise, you could always try social engineering, or some other method to get someone that does have the rights to remove some of the traces of ownership, or grant you rights to the object so you can make it anonymous (not counting backups, systems that record object changes, and forensics that may get the original owner information).

To have a fully anonymous computer account, you can create your first level account, modify some attributes in that, log in with the computer account, and create more computer accounts that are now no longer tied to the original human user account object. (As mentioned early, every user has a 10 machine quota by default. Computer accounts are users, and can have 10 of their own, making the infinite generic accounts possible). This is where the bad default permissions on computer objects comes in. The create/owner has rights to edit the UserAccountControl attribute and set the password to the account. Using a helpful tool called admod (joeware), you can set the password and change the UserAccountControl values to allow interactive logons.

Putting it together, lets assume we have a domain called CompSecTest.2k3.local.


C:\Documents and Settings\nathan>netdom add maliciousAccount /domain:compsectest.2k3.local
The command completed successfully.

C:\Documents and Settings\nathan\Desktop>admod -b "cn=maliciousAccount,cn=computers,dc=compsectest,dc=2k3,dc=local" "unicodepwd::Password1" -optenc

AdMod V01.13.00cpp Joe Richards (joe@joeware.net) April 2010

DN Count: 1
Using server: DC2K3-1.compsectest.2k3.local:389
Directory: Windows Server 2003

Modifying specified objects...
DN: cn=maliciousAccount,cn=computers,dc=compsectest,dc=2k3,dc=local...

The command completed successfully

###SET UAC to 512 to act like a normal user and bypass interactive logon restrictions

C:\Documents and Settings\nathan\Desktop>admod -b "cn=malicious,cn=computers,dc=compsectest,dc=2k3,dc=local" "useraccountcontrol::512"

AdMod V01.13.00cpp Joe Richards (joe@joeware.net) April 2010

DN Count: 1
Using server: DC2K3-1.compsectest.2k3.local:389
Directory: Windows Server 2003

Modifying specified objects...
DN: cn=malicious,cn=computers,dc=compsectest,dc=2k3,dc=local...

The command completed successfully


C:\Documents and Settings\nathan\Desktop>runas /user:compsectest1\maliciousAccount$ cmd
Enter the password for compsectest1\MaliciousAccount$:
Attempting to start cmd as user "compsectest1\MaliciousAccount$" ...


C:\WINDOWS\system32>whoami
compsectest1\maliciousAccount$


C:\WINDOWS\system32>netdom add malicious2 /domain:compsectest.2k3.local
The command completed successfully.


C:\WINDOWS\system32>admod -b "cn=malicious2,cn=computers,dc=compsectest,dc=2k3,dc=local" -optenc "unicodepwd::Password1"

AdMod V01.13.00cpp Joe Richards (joe@joeware.net) April 2010

DN Count: 1
Using server: DC2K3-1.compsectest.2k3.local:389
Directory: Windows Server 2003

Modifying specified objects...
DN: cn=malicious2,cn=computers,dc=compsectest,dc=2k3,dc=local...

The command completed successfully


C:\temp>admod -b "cn=malicious2,cn=computers,dc=compsectest,dc=2k3,dc=local" -optenc
"useraccountcontrol::512"

AdMod V01.13.00cpp Joe Richards (joe@joeware.net) April 2010

DN Count: 1
Using server: DC2K3-1.compsectest.2k3.local:389
Directory: Windows Server 2003

Modifying specified objects...
DN: cn=malicious2,cn=computers,dc=compsectest,dc=2k3,dc=local...

The command completed successfully


Now that you are here, you have a generic computer account with interactive logon capabilities that is one level removed from a standard user account. This can continue until there are so many computer accounts owned, that stopping the use of them may require a mass deletion of objects in the Computers container which could have other impact on legitimate accounts. So, as administrators we should take steps to prevent this type of activity. This can include redirecting the default computers container elsewhere and putting restricted permissions there, dropping the default quota value to zero, changing the schema to reduce the creator/owner level default permissions on computer objects, and editing the default group policy rights to remove the Authenticated Users object in the Add machines to the domain right. These steps can reduce risks from non-privileged users, but for higher privileged users that need the ability to manage computer accounts, and combination of schema permissions changes and a tight least privilege method of rights to computer accounts can help prevent the interactive capability of a computer account. When a computer account is at its base UserAccountControl value it can't log in interactively, be used for services, or scheduled tasks, but it can be used to access network shares. Monitoring the environment for any computer objects with UAC bits flipped to the wrong values could also be a good idea.

One way to find this type of account is with another joeware utility (adfind):

adfind -gc -b dc=compsectest,dc=2k3,dc=local -s subtree -bit -f "(&(objectcategory=computer)(objectclass=computer)(useraccountcontrol:OR:=512))" -t 15000 distinguishedname

Tuesday, April 20, 2010

UserAccountControl

Write-line "Hello World"

I have been distracted from some work I was doing for computer account security research, so I thought I would get back to it by sharing some of limited fuzzing results for UAC values of objects use this attribute (anything using the User class, such as user accounts, and computer accounts).

The various bit values are shown in this table from kb305144
























PropertyHexadecimalDecimal
SCRIPT0x00011
ACCOUNTDISABLE0x00022
HOMEDIR_REQUIRED0x00088
LOCKOUT0x001016
PASSWD_NOTREQD0x002032
PASSWD_CANT_CHANGE0x004064
ENCRYPTED_TEXT_PWD_ALLOWED0x0080128
TEMP_DUPLICATE_ACCOUNT0x0100256
NORMAL_ACCOUNT0x0200512
INTERDOMAIN_TRUST_ACCOUNT0x08002048
WORKSTATION_TRUST_ACCOUNT0x10004096
SERVER_TRUST_ACCOUNT0x20008192
DONT_EXPIRE_PASSWORD0x1000065536
MNS_LOGON_ACCOUNT0x20000131072
SMARTCARD_REQUIRED0x40000262144
TRUSTED_FOR_DELEGATION0x80000524288
NOT_DELEGATED0x1000001048576
USE_DES_KEY_ONLY0x2000002097152
DONT_REQ_PREAUTH0x4000004194304
PASSWORD_EXPIRED0x8000008388608
TRUSTED_TO_AUTH_FOR_DELEGATION0x100000016777216



Having rights to write to this value does not guarantee all values can be written. There are two values related to delegation, which were smartly locked down to Domain administrator edits only. Some of the bit values are not in use, but can be used, while others are not in use and cannot be used. I break these down as follows:

M = Mandatory entry, but can only contain one type. Used for account type
N = Not possible to edit (note: domain administrator level accounts may be able to try to edit these values without error, but it won't write the value)
P = Possible to edit when write UAC property permission or write all properties permissions is possessed by editor
A = Domain admin level rights required to edit:
- = Can be used in a modify operation, but will not be written

Bits: 0000 0011 0111 1111 0011 1011 1010 1010
Oper: ---- --PA -PPP APPP --MM M-MM PNPN P-PN

When trying to write values to UAC, you can provide in hex format or integer format. Other entries or invalid characters will throw errors. Negative numbers can be provided, but they will be handled with the appropriate bit values and hold to the same restrictions.

As for computer account security, I find it interesting that the creator of a computer account can manipulate some of these values that would be better left to an administrator. One in specific would be the account type values allowing more interactive access like I mentioned in my avoiding account lockout article. Luckily, delegation enable/disable is restricted, so if you have Domain admins that understand the implications of this and restrict its implementation, you have some degree of safety. Once enabled though, maybe another story.

Tuesday, March 30, 2010

Tired of looking up security codes in events?

Hello, I have put together a few Powershell functions for this lockout tool I am working on, which help decode some of the various Kerberos and logon codes in security event log events. They are not full tested, but hopefully should work fine as is.
function decode-krbTktOpts([string]$code) {
 #code provided is in hex format
 if (-not($code -match "0x\d{8}")) {
   write-error "Invalid entry sent to decode-krbTktOpts function : value was : $code"
   return $null
 }
 
 
 ##########
 #Ticket options are 32 bits of flags.  Code comes in as hex.  Only bits 0-1,3-5,16-17,20,23,25-31 are used
 ##########
 $results = new-object collections.arraylist
 $code = [convert]::toint32($code.substring($code.indexof("x")+1), 16)
 if ($code -and 1) {
  $results.add("Validate") >$null
 } else if ($code -and 2) {
  $results.add("Renew") >$null
 } else if ($code -and 8) {
  $results.add("EncTktInSKey") >$null 
 } else if ($code -and 16) { 
  $results.add("RenewableOK") >$null
 } else if ($code -and 32) {
  $results.add("DisableTransitedCheck") >$null
 } else if ($code -and 65536) {
  $results.add("Canonicalize") >$null
 } else if ($code -and 131072) {
  $results.add("CNameInAddlTkt") >$null
 } else if ($code -and 1048576) {
  $results.add("OptHardwareAuth") >$null
 } else if ($code -and 8388608) {
  $results.add("Renewable") >$null
 } else if ($code -and 33554432) {
  $results.add("AllowPostDate") >$null
 } else if ($code -and 67108864) {
  $results.add("Proxy") > $null
 } else if ($code -and 134217728) {
  $results.add("Proxiable") > $null
 } else if ($code -and 268435456) {
  $results.add("Forwarded") > $null
 } else if ($code -and 536870912) {
  $results.add("Forwardable") > $null
 } 
 return $results

}

function decode-LogonErrorCode([string]$code) {
 #decode 32 bit microsoft logon error codes from Hex format (32 bit)
 if (-not($code -match "0x\d{8}")) {
   write-error "Invalid entry sent to decode-krbTktOpts function : value was : $code"
   return $null
 }
 
 switch($code.tolower()) {
  "0x0" { return  "Successful login" }
  "0xC0000064" { return "The specified user does not exist" }
  "0xC000006A" { return "The value provided as the current password is not correct" }
  "0xC000006C" { return "Password policy not met" }
  "0xC000006D" { return "The attempted logon is invalid due to a bad user name"}
  "0xC000006E" { return "User account restriction has prevented successful login"}
  "0xC000006F" { return "The user account has time restrictions and may not be logged onto at this time"}
  "0xC0000070" { return "The user is restricted and may not log on from the source workstation"}
  "0xC0000071" { return "The user account's password has expired"}
  "0xC0000072" { return "The user account is currently disabled"}
  "0xC000009A" { return "Insufficient system resources"}
  "0xC0000193" { return "The user's account has expired"}
  "0xC0000224" { return "User must change his password before he logs on the first time"}
  "0xC0000234" { return "The user account has been automatically locked" }
  default {return "Unknown code provided, unable to translate" }
 }
 
}

function decode-krbErrCode([string]$code) {
 #code provided is required to be in the hex format provided in the system event logs  ex: 0x2
 if (-not($code -match "x")) {
  #if we receive something in invalid format, try to convert to hex
  if ($code -match "\d+") {
   $code = "0x" + [string]::format("{0:x}",$code)
  } else {
   write-error "Invalid entry sent to decode-krbErrCode function : value was : $code"
   return $null
  }
 }
  
 switch($code.tolower()) {
  "0x0" { return ("KDC_ERR_NONE","No Error") }
  "0x1" { return ("KDC_ERR_NAME_EXP","Clients entry in Database has Expired") }
  "0x2" { return ("KDC_ERR_SERVICE_EXP","Servers entry in Database has Expired") }
  "0x3" { return ("KDC_ERR_BAD_PVNO","Request protocol version number not supported") }
  "0x4" { return ("KDC_ERR_C_OLD_MAST_KVNO","Client's key encrypted in old master key") }
  "0x5" { return ("KDC_ERR_S_OLD_MAST_KVNO","Servers key encrypted in old master key") }
  "0x6" { return ("KDC_ERR_C_PRINCIPAL_UNKNOWN","Client not found in Kerberos Database") }
  "0x7" { return ("KDC_ERR_S_PRINCIPAL_UNKNOWN","Server not found in Kerberos Database") }
  "0x8" { return ("KDC_ERR_PRINCIPAL_NOT_UNIQUE","Multiple principal entries in database") }
  "0x9" { return ("KDC_ERR_NULL_KEY", "The client or server has a null key") }
  "0xa" { return ("KDC_ERR_CANNOT_POSTDATE", "Ticket not eligible for postdating") }
  "0xb" { return ("KDC_ERR_NEVER_VALID","Requested start time is later than end time") }
  "0xc" { return ("KDC_ERR_POLICY","KDC policy rejects request") }
  "0xd" { return ("KDC_ERR_BADOPTION","KDC cannot accomodate requested option") }
  "0xe" { return ("KDC_ERR_ETYPE_NOSUPP","Kerberos server has no support for this encryption type") }
  "0xf" { return ("KDC_ERR_SUMTYPE_NOSUPP","Kerberos server has no support for checksum type") }
  "0x10" { return ("KDC_ERR_PADATA_TYPE_NOSUPP","Kerberos server has no support for PADATA type") }
  "0x11" { return ("KDC_ERR_TRTYPE_NOSUPP", "Kerberos server has no support for transited type") }
  "0x12" { return ("KDC_ERR_CLIENT_REVOKED","Clients credentials have been revoked") }
  "0x13" { return ("KDC_ERR_SERVICE_REVOKED","Credentials for server have been revoked") }
  "0x14" { return ("KDC_ERR_TGT_REVOKED","TGT has been revoked") }
  "0x15" { return ("KDC_ERR_CLIENT_NOTYET","Client not yet valid") }
  "0x16" { return ("KDC_ERR_SERVICE_NOTYET", "Server not yet valid") }
  "0x17" { return ("KDC_ERR_KEY_EXPIRED", "Password has expired - change password to reset") }
  "0x18" { return ("KDC_ERR_PREAUTH_FAILED","Preauthentication is invalid, bad password") }
  "0x19" { return ("KDC_ERR_PREAUTH_REQUIRED","Additional Preauthentication required") }
  "0x1f" { return ("KRB_AP_ERR_BAD_INTEGRITY","Integrity check on decrypted field failed") }
  "0x20" { return ("KRB_AP_ERR_TKT_EXPIRED","Ticket expired")}
  "0x21" { return ("KRB_AP_ERR_TKT_NYV","Ticket not yet valid")}
  "0x22" { return ("KRB_AP_ERR_REPEAT","Request is a replay")}
  "0x23" { return ("KRB_AP_ERR_NOT_US","The ticket isn't for us")}
  "0x24" { return ("KRB_AP_ERR_BADMATCH", "Ticket and authenticator do not match") }
  "0x25" { return ("KRB_AP_ERR_SKEW", "Clock skew is too big")}
  "0x26" { return ("KRB_AP_ERR_BADADDR", "Incorrect net address") }
  "0x27" { return ("KRB_AP_ERR_BADVERSION", "Protocol version mismatch") }
  "0x28" { return ("KRB_AP_ERR_MSG_TYPE", "Invalid message type") }
  "0x29" { return ("KRB_AP_ERR_MODIFIED", "Message stream modified") }
  "0x2a" { return ("KRB_AP_ERR_BADORDER", "Message out of order") }
  "0x2c" { return ("KRB_AP_ERR_BADKEYVER","Specified version of key is not available") }
  "0x2d" { return ("KRB_AP_ERR_NOKEY", "Service key not available") }
  "0x2e" { return ("KRB_AP_ERR_MUT_FAIL", "Mutual authentication failed") }
  "0x2f" { return ("KRB_AP_ERR_BADDIRECTION", "Incorrect message direction") }
  "0x30" { return ("KRB_AP_ERR_METHOD", "Alternative authentication method required") }
  "0x31" { return ("KRB_AP_ERR_BADSEQ", "Incorrect sequence number in message") }
  "0x32" { return ("KRB_AP_ERR_INAPP_CKSUM", "Inappropriate type of checksum in message") }
  "0x3c" { return ("KRB_ERR_GENERIC", "Generic error") }
  "0x3d" { return ("KRB_ERR_FIELD_TOOLONG","Field is too long for this implementation") }
  default { return ("Invalid code", "not in RFC") }
 }
  
}

Friday, March 26, 2010

Auditing Kerberos Delegation

Hello,

In the last few weeks I was doing some audits in my environment for accounts that were trusted for delegation. I thought I would share some LDAP searches with everyone, using Joe's great ADFIND tool. For those that are not too familiar with delegation, there are two different bits in the UserAccountControl attribute that are related to delegation. These are TRUSTED_FOR_DELEGATION (0x80000) which uses kerberos forwardable tickets, and TRUSTED_TO_AUTH_FOR_DELEGATION (0x1000000) which allows the delegated person/computer to request a ticket on a user's behalf. Both of these options should be used with extreme caution when the accounts are unconstrained, the second option even more so. If systems that are delegated in an unconstrained manner get compromised, anyone accessing them is basically giving up their account for any purpose to the compromised machine.



Finding all unconstrained delegated computer and user accounts, ignoring domain controllers.

adfind -h DCservername -b dc=mydomain,dc=com -s subtree -bit -f "(&(|(objectcategory=user)(objectcategory=computer))(|(userAccountControl:OR:=16777216)(userAccountControl:OR:=524288))(!(iscriticalsystemobject=TRUE))(!(msds-allowedtodelegateto=*)))" -t 9000 distinguishedname serviceprincipalname useraccountcontrol

Finding all constained delegated computer and user accounts, ignoring domain controllers.

adfind -h DCservername -b dc=mydomain,dc=com -s subtree -bit -f "(&(|(objectcategory=user)(objectcategory=computer))(|(userAccountControl:OR:=16777216)(userAccountControl:OR:=524288))(!(iscriticalsystemobject=TRUE))(msds-allowedtodelegateto=*))" -t 9000 distinguishedname serviceprincipalname useraccountcontrol

Thursday, March 11, 2010

Avoiding account lockout policy (pre Windows 2008)

Over the last year or so a few instances have come up with service accounts getting locked out and the owners being unhappy. Usually everyone wants to know if it is possible to set their account so it can't be locked out. Prior to Windows 2008 AD fine grained password policies and managed service accounts, the answer typically is No. The security guy in me says No way should this be done even if it is possible. But to be fair, lets look at technical feasibility.

Lockout policy/Password policy is a domain wide setting, for domain accounts it follows what policy is applying to the domain controllers. For domain member local accounts it follows whatever policy is pushed to the client system. But, there is in fact a way to avoid lockouts, though it is a bit unorthodox. Let me give some background then I will mention the how-to.

A few weeks ago, one morning I had this idea pop into my head that it would be interesting to explorer the security implications of computer accounts in the enterprise (This means computer objects...people like to mix "computer accounts" to mean user accounts). Since computer accounts have passwords and can access remote resources, I thought there may be some interesting things to find.

So on this mission, I first looked at what can you do with computer accounts. Normal tools, like ADUC, dsmod, etc don't let you set a computer account password manually. NET USER and admod will allow this however. So I created my object, reset the password and started messing around. I first found that you can't log in interactively with computer accounts and it gives you an error saying that a policy is blocking this. I granted all possible user rights to the account, and added to administrators group, but no help there. If you look at the UserAccountControl attribute, there are flags that indicate the type of account. There is also a SamAccountType attribute on users and computers. The value of this is slightly different, but you can't edit this attribute as it is controlled by the SAM. UserAccountControl however can be edited. There is some security implications with this related to computers that I will get into some other time.

Anyways, if you look at the values in the linked article above you can see these flags. You can't have both set at the same time, but you can change the computer object's useraccesscontrol level to that of a normal user. Coincidentally, this causes the SamAccountType value to be updated to match a user object as well.

Values:
0x1000 workstation trust account
0x0200 normal account

So I changed my test object's UAC to 0x0200, I retried local login and it worked fine. Also using it for scheduled tasks, services, etc were all working now as well. Previously I could only use the account to map network drives.

So this was an interesting discovery, but I took this a little further on login attempts. I noticed with repeat failed passwords my bad password count kept going up, well over the lockout threshold set in my test domain. When my normal user objects were getting locked, my computer account kept taking attempts over and over. Providing the correct password after multiple failures that should have resulted in lockout showed that I could still log in. So apparently the mechanism used to lock accounts ignores computer objects, doesn't look at UAC for them, and doesn't look at the SamAccountType. Given this, we can create an unlockable "user" by creating a computer object.

For those who may worry now about brute force password attempts on computer objects, given that most forms of logins are blocked for a standard account, and the auto generated password length is significantly high, the risk is low. For those that have pretty loose computer object creation policies, it may be time to start thinking in a different way. In the near future, I hope to provide some better details on the overall security implications of computer objects.