Tuesday, August 10, 2010

Managing odd services in group policy

If you feel that using group policy to manage system services for security purposes is a good idea, and you want to block certain services that typically won't be in the list of services in the edit console, there are several ways to get around this. One suggestion (the hard way, and bad way), is to have the service installed on a machine, and edit the GPO from that machine. That will work, but it is time consuming, and may open up security problems just to set up the GPO.

The easier way is to create a GPO and pick any service from the list. Use this service to set whatever permissions, start type, and other options you want. From here you can either backup the GPO, or just directly edit the files in sysvol. In the policy you will see 3 folders:

Adm
Machine
User

The services are under machine, so open this. Drill down through Microsoft-> Windows NT->SecEdit and open the GptTmpl.inf in notepad. From here you can see a section called [Service General Settings]. One example line here for a vnc service:

"WinVNC4",4,"D:AR(D;;DCRPWPDTSDRC;;;BA)(A;;CCLCSWLOCRRC;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"

Here we have the service name (this is not the display name you see in the services MMC. It is the service name you use with "net start" or how you find it in the registry. You can get this with psservice or sc.exe). Since we already set up all the other settings that we want, we can keep all the ACL information in place, and just change the name of the service that is in the first set of quotations. Edit what you want, add more services if you need and save.

If you backed up the GPO before editing it, you can just import this information into a new GPO object. If you are directly editing sysvol files you may need to update the version details in the same file (and possibly in other files and the GPO AD object), so it is best to go with the backup/restore method and create a new group policy object. This gives versioning flexibility and an easier backout path in case of problems.

Finding the distinguishedName of an AD integrated DNS zone

As a precursor to some work I want to do for standard users to be able to create DNS records in AD integrated zones, I threw together some started code to find the actual location of a DNS zone. If you read my previous post looking at DNS without the DNS protocol, I mentioned the various places zones can be located. When you have more than one domain in a forest, this increases the number of possible places to look. This sample code is a basic starter for looking at anything outside of specialized application partitions, to find a specified zone inside the current forest.
#get-dnspartition
#
#Searches different paritions for the distinguished name of a dns zone
#V1.0  Aug 2010.  Checks the forest dns, domain dns and legacy domain dns locations for the existence of a zone
#and returns the distinguished name of all results.
#
# Future work possibilities.  Looking for application partitions.  Working with reverse zones in a way that does
# more of a wildcard search to get a better match when the network ID is unknown or scope of the reverse zone is unknown.  
#Search capability for subzones that are in the same parent zone
# object.  In AD these just show up as part of the record's Name attribute..recordname.subzone

#note, some partitions may not allow authenticated users read access to view the base cn=microsoftDNS containers
#but opening the parent container and doing a subtree search for the zone bypasses this restriction.


$zonename = $args[0]

$forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$mytopleveldomain = $forest.schema.name
$mytopleveldomain = $mytopleveldomain.substring($mytopleveldomain.indexof("DC="))
 
$Arrmyresults = @()

function search-dns-partition($partion, $domainDN, $zonename) {
 $de = new-object DirectoryServices.DirectoryEntry("LDAP://" + $partition + $domaindn)
 $ds = new-object DirectoryServices.DirectorySearcher($de)
 $ds.filter = "(&(objectclass=dnszone)(name=" + $zonename + "))"
 $fu = $ds.findone()
 if ($fu -ne $null) { 
  return $fu.properties.distinguishedname 
 } else { return $null }
}

function dns-to-dn ([string]$dnsname) {
  #may 09
  
  #this is a helper function which will convert a dns name to a distinguished name dc= 
  #type of result by breaking off each piece of the dns name to become a DC entry
  
  $domainDNnamearr = $dnsname.split(".")
  $domainDNname = ""
    
  foreach ($component in $domainDNnamearr) {
     $domainDNname = $domainDNname + "DC=" + $component + ","
  }
  $domainDNnamearr = $null
     
  #remove trailing , off
  $domainDNname = $domainDNname.substring(0,$domainDNname.length -1)
  return $domainDNname

}

#check domain and domain legacy partitions
foreach ($dom in $forest.domains) {
 foreach ($partition in ("cn=System,", "dc=domaindnszones,")) {
  $domainDNval = dns-to-dn $dom.name
  $myresult = search-dns-partition $partition $domainDnVal $zonename
  if ($myresult -ne $null) {
   $Arrmyresults += $myresult
  }
 } 
}

#Check forest partition
$myresult = search-dns-partition "dc=forestdnszones" $mytopleveldomain $zonename
if ($myresult -ne $null) {
 $Arrmyresults += $myresult
}

return $arrmyresults

Monday, August 9, 2010

Getting the NIC card binding order

I was playing around with some ideas today for identifying what is the primary NIC card of a Windows system, so I could add that to some Dns client setting monitoring I'm working on. The problem of NIC bindings has come up in the past during some troubleshooting on servers that were plugging into trunk ports and had a lot of virtual nic's for different subnets. For those that do no know about binding order, when you are in windows, on the network properties page (for newer OS versions that is "Change adapter settings"). There is a menu item, though it may be hidden to make your life more difficult in new OS's. Try alt-N to pull up the network Advanced menu, and select "Advanced Settings". In this dialog box, you will see a list of connections available and their order. You can move NIC's up and down to set what is the primary NIC for a system. On some Os's this requires reboot to take effect. The binding order is stored in the registry under HKLM\System\CurrentControlSet\Services\TcpIP\Linkage key with a multistring value called Bind. This lists devices by GUID. You can match up the guid values here to the interfaces in other registry locations, or read them through WMI. The reason NIC binding can be important can include, selection of default gateway (windows only supports 1 at a time), and determining what interface traffic originating from the machine uses. In the case of my previously mentioned problems, the problem was DNS lookups were going out the wrong interface, into a secluded subnet to DNS servers that could not reply back due to firewall restrictions. Moving the order will allow you to control what NIC is your source IP. In any case, I though it would be useful to throw together a basic script to list out the binding order of multihomed machines. This script returns an array of PSObjects with the following: BindingOrder, Description, GUID, IP, SubnetMask, Gateway; where description is the text value that shows up in your list of network adapters, and GUID is what is used to reference it in the registry.
#get-binding order
#Check a remote machine to see NIC binding order.

$server = $args[0]

if ($server -eq $null -or $server -match "\?") {
 Write-Host -ForegroundColor "yellow" "Usage:  Get-NicOrder "
 Write-Host -ForegroundColor "yellow" "    Enter the name of a system to connect to.  This script will"
 Write-Host -ForegroundColor "yellow" "    provide the network card binding order of a remote machine."
 exit
}

$key = "System\CurrentControlSet\Services\Tcpip\Linkage"
$type = [Microsoft.Win32.RegistryHive]::LocalMachine
$regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$server)

if (-not $?) {
 Write-Host -ForegroundColor "red"  "Cannot check remote machine, exiting...."
 exit
}

$regkey = $regkey.opensubkey($key)
$ArrBindingGUIDs = $regkey.getvalue("Bind")
 
$ArrNicList = Get-WmiObject -ComputerName $server -Query "select Description,settingid,ipaddress,ipsubnet,defaultipgateway from win32_networkadapterconfiguration"

$ArrResults = New-Object collections.ArrayList

for ($i = 0; $i -lt $ArrBindingGUIDs.length; $i++) {
    if ($arrbindingguids[$i].contains("{") {
  $guid = $ArrBindingGUIDS[$i].substring($ArrBindingGUIDs[$i].indexof('{'))
  foreach ($nic in $ArrNicList) {
   if ($nic.settingid -eq $guid) {
    $result = New-Object psobject
    Add-Member -InputObject $result NoteProperty BindingOrder $i
    Add-Member -InputObject $result NoteProperty Description $nic.Description
    Add-Member -InputObject $result NoteProperty GUID $nic.SettingID
    Add-Member -InputObject $result NoteProperty IP $nic.ipAddress
    Add-Member -InputObject $result NoteProperty SubnetMask $nic.ipsubnet
    Add-Member -InputObject $result NoteProperty Gateway $nic.defaultIpGateway
    $Arrresults.add($result) >$null 
   }
  }
 }
}

Return $arrResults
 

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?