DS commands and FOR loops

Good old fashion "ds" commands, basic but always available and just do the job! While now days we have PowerShell, I still do come across Win 2003 boxes. DS commands in combination with FOR loops are quite powerful.

How to query Active Directory for disabled computer accounts and move them to specified OU?

for /f "Tokens=*" %s in ('dsquery computer -disabled -limit 0') do (DSMOVE %s -newparent "ou=Disabled_Computers,dc=securesenses,dc=net")

How to move computers to a specified OU using list of hostnames? (hostnames must be listed on per line)

for /f "Tokens=*" %i in (comps.txt) do dsquery computer -name %i | (dsmove -newparent "OU=DBServers,OU=Servers,dc=securesenses,dc=net")

How to create security groups with descriptions listed in a text file?

for /f "delims=, tokens=1,2" %i in (groups.txt) do dsadd group "CN=%i,OU=Groups,DC=securesenses,DC=net" -desc %j

How to disable list of computers?

for /f "Tokens=*" %i in (comps.txt) do dsquery computer -name %i | dsmod computer -disabled yes

How to create user accounts from a list? 

for /f "delims=, tokens=1,2" %i in (accs.txt) do dsadd user "CN=%i,OU=SERVICEACCOUNTS,DC=securesenses,DC=local"  -display %i -samid %i -upn %i@securesenses.local -pwd %j -pwdneverexpires yes -canchpwd no


WMIC is a command line interface to WMI (Windows Management Instrumentation). WMI is a powerful management interface that we can access from directly from command line. 

WMIC can be used to manage remote computers. 
If we want to execute WMIC commands on a single computer we prepend command with /node: as shown below:

/node:hostname123 - specifies single server 
(wmic /node:hostname123 qfe where hotfixid="KB974571" list full)

If we want to execute WMIC commands on multiple computers listed in c:\nodes.txt we prepend command with /node:@ as shown below:

/node:@'c:\node.txt' - specifies text file with server names 
 (wmic /node:@'c:\node.txt' qfe where hotfixid="KB974571" list full)

It's worth keeping in mind that not all WMI classes have corresponding classes (called aliases) in WMIC. It is however possible to access WMI classes directly from WMIC:

wmic /namespace:\\root\NAMSPACE path CLASSNAME

To directly access WMI classes in CIMv2 namespace  

wmic /namespace:\\root\cimv2 path win32_useraccount

To see if there are any predictive failures using WMIC: 

wmic /namespace:\\root\wmi PATH MSStorageDriver_FailurePredictStatus get 

We can use Microsoft WMI Studio to explorer WMI classes, properties and methods

We can tell WMIC to repeat a command at specified interval:

/every:5    -  repeats a command every 5 seconds 

WMIC can also output to an HTML file using /output and /format switches 

wmic /output:c:\cpu.htm cpu get name, maxclockspeed /format:hform.xsl

HTML output is no longer available in Windows 2008 or 7, on these platforms we omit /format switch.

qfe - wmic query for hotfixes and patches 

query for a given patch by using a KB ID: 

wmic qfe where hotfixid="KB974571" list full

process - process management 

query for an exe path of a process 

wmic process where caption="Apntex.exe" get executablepath  

query for a process's thread count  

wmic process where caption="Apntex.exe" get threadcount 

to execute a  command on a remote machine  

wmic /node:hostname process call create 'cmd.exe /c net stop iisadmin' 

To kill a process using WMIC: 

wmic process where caption="notepad.exe" call terminate 

service - service management: 

Disable service using WMIC

wmic service where caption='SSDP Discovery Service' call changestartmode disabled 

Enable service using WMIC

wmic service where caption='SSDP Discovery Service'  call changestartmode enabled 

Stop service using WMIC

wmic service where caption='SSDP Discovery Service'  call stopservice 

Startservice using WMIC

wmic service where caption='SSDP Discovery Service' call startservice 

Retrieve service status

wmic service where name='........'  get status 

To retrieve service name: 

wmic service list instance 

product - Software Management 

List installed software: 

wmic product get

wmic product list brief 
Only required attributes: 

wmic product get name, vendor, version 

Only products from Adobe: 

wmic product where "vendor like 'adobe%'" get 

 Find out a username of a user logged on to a computer: 


 Configure a static IP address using WMIC: 

wmic nicconfig where Index=1 call EnableStatic (""), ("") 

To retrieve index ID: 

wmi nicconfig where ipenabled='true' 
Enable DHCP using WMIC: 

wmic nicconfig where Index=1 call EnableDHCP

File management using WMIC: 

list details about c:\script\comps.txt file 

wmic datafile where "path='\\scripts\\' and name='c:\\scripts\\comps.txt'" list full   

Backup event log using WMIC:

wmic nteventlog where "logfilename='system'" call backupeventlog "c:\system.evt"

wmic nteventlog where "logfilename='application'" call backupeventlog "c:\application.evt"

Query local groups:

wmic group where (localaccount=true) get name

Local groups with "sql" in the name:

wmic group where (localaccount=true and name like 'sql%') get name

Cisco Secure ACS 5.3 and GNS3

In a previous post I showed how I installed ACS in VBox. The reason I wanted it in VBox was so I could add it to GNS3 topology as a host. GNS uses first NIC in of a VM as a “management” NIC and adds a second NIC for linking within the topology.  ACS supports only single NIC (even the hardware appliance that comes with 4 NICs, has 3 of them disabled). “Runtime”  is the process that listens to and processes TACACS and RADIUS requests. It gets “bound” to the IP addresses configured during the initial setup. When ACS is added to GNS and second NIC installed and configured, the "runtime" still listens only on the first NICs IP address. Configuring the second NIC, disabling the first one and restarting ACS application results in "runtime" not starting at all.

To get around that, I needed to do the following at the ACS’s console once ACS was added to GNS as a VBox host:

1.         Configure second NIC with the same IP address as the first one

# configure terminal
# interface gigabitEthernet 1
# ip address (or whatever address you used)
don't restart the services
#copy running-config startup-config

2.       Restart the VM and login to ACS

# configure terminal
# interface gigabitEthernet 0
# shutdown
don't restart the services
# end

3.       Restart ACS app (not the VM just the application)

# acs stop
# acs start

It takes a few minutes to stop and restart

4.       Confirm all ACS processes are started

# show application status acs

5.       Confirm ACS is listening on runtime ports (TCP 49 for TACACS)

# show ports

When you do “show interfaces”, ACS displays real interface names (eth0 and eth1) however to configure them you need to use “gigabitEthernet”.  

You could also try editing the startup-config file by booting to a Live Linux CD and editing the file using VI or some other text editor. The config file is stored in /_storedconfig partition. 

Monitoring Cisco Secure ACS 5 for authentication failures

Monitoring and alerting on failed authentication attempts is a crucial part of a security strategy. Failed authentication events may be a result of someone trying to guess or brute force passwords.   ACS is used for controlling access to network devices such as switches, routers, firewalls as well as authenticating VPN connections and wireless access. Authentication failures from ACS could alert us of an attacker trying to establish remote connection over VPN or trying to penetrate our wireless.

We’ll need 3 separate alarms to notify us of:

Attempts to access network devices (TACACS+ authentication failures )
      Attempts to penetrate wireless or VPN (RADIUS authentication failures)
          Attempts to access ACS admin interface (ACS Instance authentication failures)

To configure alerting we need to go to:
“Monitoring and Reports” -> “Launch Monitoring & Report Viewer”
 “Alarms” -> “Thresholds”

1.       Configuring TACACS+ authentication failures alerts
a.       Click “Create”
b.      Specify alarm name
c.       Leave “Schedule” at default value of “nonstop”

d.      Go to “Criteria” page
e.      Under “Category” select “Failed Authentications”
f.        Under “Failed Authentications greater than” specify desired value of occurrences
g.       Under “In the past” specify desired time
h.      Select for an “Access Service”

i.         Set “Protocol” to “TACACS+”

j.        On “Notification” page
k.       Set desired “Severity”
l.         Configure either email notification or syslog message or both
m.    Click “Submit”

2.       Configuring RADIUS authentication failures alerts
Procedure is the same as for TACACS+ but protocol must be set to RADIUS.

3.       Configuring ACS Instance authentication failures alerts
Once again procedure is the same as above but we select “ACS Instance” instead of “Access Service”

Now it would be a good idea to test if alerting works by attempting to login with incorrect password.

Installing Cisco Secure ACS 5.3 in VirtualBox

ACS 5.3 is supported on a hardware appliance, VMWare ESX and VMWare Server. Even though not supported, it works without modification in VMWare Player. None of the above helps us if we want to test it with switches or routers in GNS3. While version 5.2 could be installed in VirtualBox, v5.3 consistently failed installation with “Unsupported hardware” error message. After trying all possible combinations of virtual hardware in VBox it still refused to install. After some hacking I eventually managed to get working.

Installation requires modification of the ISO image provided by Cisco and a bit of cheating in the kickstart file and pre-creation of partitions in the VM. We will need ISO editor (ISOpen or MagicISO), text editor (such as Notepad++) and a Linux live CD of your choice.

VBox hardware configuration:
OS Type: RedHat
RAM: 1024
CPU: PAE/NX enabled, VT-x/AMD-V disabled
Floppy: Disabled
Storage: Disk 70GB (I used dynamically expanded), Controller SCSI, SCSI Port 0
Audio: disabled
Network: Adapter Intel PRO/1000 MT
Serial Ports & USB: Disabled

All remaining settings stay at defaults.
Now we need to modify the kickstart file – ks.cfg – found in the root of the installation disk.

Red color shows old values and blue new ones. 

Change 0 to 1 on line 36


Delete line 54
54:   UDI_PID=`/sbin/cars_udi_util -p`

Set variable “ret” to 0

56:   ret="$?"0

Delete lines 57 to 61 inclusive

57: if [ "$ret" -eq 0 ]; then
58:   echo "***** Cisco UDI PID: $UDI_PID " > /dev/console
59:     case $UDI_PID in
60:       Cisco-VM-SPID)
61:         VM_APPLIANCE=1

Delete –all from line 104

104:             echo "#clearpart --all --initlabel";

Delete lines 186 to 195 inlcusive

186:   else
187:       echo "***** Error: Unsupported Hardware Configuration. " > /dev/console
188:       echo "*****        This software can only be installed on Cisco " > /dev/console
189:       echo "*****        supported hardware or Virtual Machine technology " > /dev/console
190:       echo "*****        meeting the requirements specified in the installation guide." > /dev/console
191:       echo "*****        Exiting Installation..." > /dev/console
192:       sleep 5
193:       /sbin/halt -f
194:       exit 0
195:   fi

Save the file, and replace the existing ks.cfg in the ISO image.  When saving the edited ISO make sure the it is still bootable (ISOopen shows if the disk is bootable in the main UI).

Edited ks.cfg file can be downloaded here: http://www.filefactory.com/file/a322ga9ez05/n/ks.cfg

If we try the installation with our edited ISO we’ll get further than before, the install will still fail though.
Now we need to create partitions on the disk we’ll be installing ACS to.
Boot the VM to a Live Linux distro of your choice, create 2GB partition /sda1 and format it as ext3.
Now we should be able to install ACS. Simply boot the edited installation disk and follow the prompts. 

When booting ACS sits on "ip_contract" for a few minutes so be patient it will eventually boot.

Linux auditing using Nessus

Nessus can scan a range of Linux flavours. As of writing these are:
  • CentOS
  • Debian
  • Fedora
  • Gentoo
  • Red Hat
  • Slackware
  • SuSE
  • Ubuntu
There are two types of scans Nessus can run against Linux hosts: 
  • Patch audit
  • Compliance audit

Patch audit - the plugin families are "[distro name] Local Security Checks". Nessus will audit targets and report on missing security patches based on advisories released by respective distributions. Nessus requires credentials in order to preform this type of scan as this are local checks. Tenable recommends that root level  credentials are used, though I have been able to successfully scan Linux hosts with a "standard" account. This however depends on distribution and how hardened it is.

On Red Hat distros Nessus executes the following commands which work with non-root accounts:

$rpm -qa
$uname -a

Nessus then compares its database with versions of kernel and installed packages.
Compliance audit - Tenable provides a number compliance audit files based on various industry best practices or regulations. The audit files can be downloaded from support forums. Compliance scan require elevated permissions as Nessus reads various system files. 

I generally opt for using elevated permissions in both types of scans.

Setting up an account used for scanning

In most cases SSHing directly with root account is disabled (which is a good thing from security standpoint). To confirm if it's disabled we can check /etc/ssh/sshd_confing. We need to look for line reading: "PermiRootLogin". If it's commented out or set to "yes". Root login is possible. 

Nessus can use standard account to connect and then elevate permissions using su, sudo, su + sudo. I generally opt for "sudo" option. In this case Nessus will prepend each command with sudo.

To create a user "auditor"  and add it to sudoers list do the following:

#useradd auditor
#passwd auditor

#vi /etc/sudoers  or simply #visudo

add the following line: 

auditor    ALL=(ALL)    ALL

This will allow user "auditor" to execute all commands including "sudo su" which would let the account to elevate to full root - which may not always be desired. This can be restricted by adding ",! /bin/su" at the end of the line. 

Nessus supports both password and key authentication. For highest level of security and scanning targets out on the internet key auth should be used. This would also apply to blanket scans, when you scan a whole subnet and not specific hosts. There is a risk of someone setting up an SSH server and intercepting the password. We'll use password authentication in our example.

Configuring Linux scanning policy in Nessus:


I like leaving "Netstat SSH Scan" enabled to get a list of listening ports. Output from netstat is most accurate and least intrusive. 

1. Set credentials type to "SSH Settings"
2. Specify the user name
3. Set "Elevate privileges with" to "sudo" (or whatever method you chose)
4. Specify escalation password
5. optionally change ssh port

Plugins - Patch Audit policy:

We need to enable actual local security checks as well as relevant settings. I recommend enabling the whole "Settings" family as it contains a number of useful plugins besides required "SSH Settings" plugin.

1. enable desired local security checks family (for instance "CentOS Local Security Checks"
2. enable whole "settings" family 

Useful plugins in "settings" family:

19506 Nessus Scan Information - info about the scan itself

12634 Authenticated Check: OS Name and Installed Package Enumeration  - this plugin confirms whether supplied credentials worked and if Nessus was able to elevate permissions. If this plugin does not appear in scan output it means Nessus was unable to login to the target.  

21745 Authentication Failure - Local Checks Not Run - If this plugin appears in scan output it means that authentication did not work and Nessus was unable to login to the target. 

In additional to the above the following plugins provide additional information about Linux hosts:

33851 Network daemons not managed by the package system - lists software installed - in most cases - from source. These application will not be updated by the package manager and may indicate compromised host. 

25221 Remote listener enumeration  - show processes listening on ports
33276 Enumerate MAC Addresses via SSH - shows L2 interfaces

22869 Software Enumeration (SSH) - list of installed software
25202 Enumerate IPv6 Interfaces via SSH - shows IPv6 interfaces
25203 Enumerate IPv4 Interfaces via SSH - shows IPv4 interfaces

This is all we need to do to create oatch audit policy. 

Plugins - Compliance Audit policy:

For compliance audit we need to enable "Settings" family and plugin "21157 Unix Compliance Checks"


A desired audit policy file must be uploaded to Nessus server. 

Securing OSPF

There are multiple ways to secure OSPF.  The essential one is authentication. By default there isn't any validation to assure legitimacy of an OSPF topology update. Basically an attacker or a bored employee could install a physical router and become a member of a routing system. Alternately a tool such as LOKI (http://www.ernw.de/content/e6/e180/index_eng.html) could be used. LOKI provides a GUI and is very simple to use, I however found it a bit buggy. More on that can be found in my Attacking OSPF - route injection post.

Other tools that could be used include:
  •  SCAPY http://www.secdev.org/projects/scapy/ - very advanced and fairly complicated packet generation tool, to craft OSPF packets it requires OSPF extension
  • TCPREPLAY -  http://tcpreplay.synfin.net/ - a legitimate OSPF adjacency set up and database exchange could be captured, modified and replayed (I had limited success with this technique)
On a Cisco router we can use the following to secure our OSPF routing:
  • authentication
  • passive interfaces
  • access control list
  • route filtering
OSPF authentication is part of the protocol standard and should be inter operable between vendors.  We will focus on Cisco specific implementation.

There are three types of authentication supported by OSPF:
  • none (Type 0)
  • clear text (Type 1)
  • MD5 (Type 2)
Sample OSPF hello packets with different types of authentication enabled.
  • none

  • clear text (the key is "testkey")

  • MD5 

Clearly, MD5 is the way to go. When MD5 authentication is enabled, each OSPF packet is hashed using MD5 and configured key (this is called a keyed hash). Neighboring router does the same operation on received packet and if the hash values match packet is accepted and processed. If it doesn't packet is discarded.  

Authentication is enabled on per area and per interface basis. We can have area 1 with authentication, and area 2 without, configured on the same router. What's important to note is that we can have different keys on different interfaces belonging to the same area. This is important in situation when we want to exchange routes with a routing system we don't control. 

In order to enable authentication we need to enable it in router ospf configuration context and on each interface.  

Sample router configuration - enables authentication for area 1:

router ospf 1
 network area 1
 area 1 authentication

Sample interface configuration - enables MD5 authentication on F0/0:


interface FastEthernet0/0

 ip address

 ip ospf authentication message-digest
 ip ospf message-digest-key 1 md5 testkey

On Cisco devices by default, once routing is enabled, routing information is propagated and accepted on all interfaces. In default configuration, Hello packets can be captured on access ports. This gives a potential attacker information about routing protocol in use. What's more important is that hello packets would also be accepted and processed on those ports. So let's suppose there is an OSPF Denial of Service vulnerability in Cisco IOS. At this point an attacker could crash our routers. I assume at this point we have already enabled authentication so our network would be immune to route injection attacks.

To help combat this problem, Cisco IOS implements "passive-interface" feature. Basically, routing information will not be sent out or accepted on an interface marked as passive.

There are two ways to implement this feature :

1. "passive-interface default" - marks all interfaces as passive, interfaces that should be part of routing system must be explicitly configured with "no passive-interface" command.

Sample configuration (sets all interface except f0/0 and f0/1 to passive mode):

router ospf 1
 passive-interface default
 no passive-interface f0/0
 no passive-interface f0/1

2. mark specific interfaces as passive:

router ospf 1
 passive-interface f0/0
 passive-interface f0/1

It is important to note that in both cases the configuration is performed in the OSPF process context and not interface context.

Access Control List (ACL) is another option to accomplish what passive interfaces would. (Though I find passive interface option much more manageable) We can apply ACLs blocking OSPF traffic on access ports or any ports as required. We need to apply them in both directions as we don't want OSPF traffic coming in or going out. 

Sample configuration:

access-list 101 deny ospf any any
interface f0/0
 ip access-group 101 in
 ip access-group 101 out

Route filtering should also be employed to protect routing systems. Filtering works best at topological edges such as WAN aggregation points. For example if we have 3 branch offices using network ranges of, and we can configure a filter  that will prevent any routing updates outside of range. This can generally be done effectively only on Area Border Routers or Autonomous System Border Routers.  OSPF route filtering is a complex and complicated subject which I'll cover some other time. 

Attacking OSPF - route injection

LOKI and author's Black Hat presentation can be downloaded here:  http://www.ernw.de/content/e6/e180/index_eng.html 

Falsifying routing information can have disastrous consequences to network stability. For example an attacker could reroute traffic through a monitoring station and capture traffic for later analysis. An attacker could also reroute traffic to a black hole or reroute a 10 Gig transit link traffic towards a 1 GB link causing a Denial of Service (DoS) condition. 

Both network topology and scenario presented in this post are extremely simplistic but should be sufficient to present potential implications.

Our topology:

R1's routing table looks as follows:

R1#show ip route
C is directly connected, FastEthernet1/0 is subnetted, 1 subnets
C is directly connected, FastEthernet0/0
O [110/2] via, 00:00:01, FastEthernet0/0 is subnetted, 1 subnets
C is directly connected, Loopback0
O [110/3] via, 00:00:01, FastEthernet0/0

Its OSPF neighbor table:

R1#show ip ospf neighbor

Neighbor ID     Pri   State                  Dead Time   Address         Interface       1    FULL/BDR        00:00:35      FastEthernet0/0

To launch LOKI in its default directory -  #python /usr/bin/loki.py 

Once we click run, LOKI will by default capture all control plane protocols it supports. In the screenshot below we can see that LOKI captured an OSPF Hello packet from its adjacent router. From the captured packet we can see the following:
  • IP address the hello was sent from is
  • router ID is (by default highest loopback interface address)
  • OSPF Area is 1
  • OSPF authentication is not enabled

From here we can craft our own OSPF packets. 

Firstly we'll send an empty Hello packet and see what happens. To do so we set "area" to "1" and Authentication type to "AUTH_NONE". We start sending packets by clicking "Hello".

In R1's console we confirm that adjacency was set up:

*Mar  1 04:42:46.654: %OSPF-5-ADJCHG: Process 1, Nbr on FastEthernet1/0 from LOADING to FULL, Loading Done

R1#show ip ospf neighbor

Neighbor ID     Pri   State                 Dead Time   Address         Interface              1   FULL/BDR        00:00:38          FastEthernet1/0       1   FULL/BDR        00:00:35      FastEthernet0/0

To get even more details we enable debugging. 

R1#debug ip ospf events

*Mar  1 00:58:49.691: OSPF: Rcv hello from area 1 from FastEthernet1/0
*Mar  1 00:58:49.691: OSPF: 2 Way Communication to on FastEthernet1/0, state 2WAY
*Mar  1 00:58:49.695: OSPF: Neighbor change Event on interface FastEthernet1/0
*Mar  1 00:58:49.695: OSPF: DR/BDR election on FastEthernet1/0
*Mar  1 00:58:49.695: OSPF: Elect BDR
*Mar  1 00:58:49.695: OSPF: Elect DR
*Mar  1 00:58:49.695:        DR: (Id)   BDR: (Id)
*Mar  1 00:58:49.699: OSPF: Send DBD to on FastEthernet1/0 seq 0x24F2 opt 0x52 flag 0x7 len 32
*Mar  1 00:58:49.699: OSPF: Neighbor change Event on interface FastEthernet1/0
*Mar  1 00:58:49.699: OSPF: DR/BDR election on FastEthernet1/0
*Mar  1 00:58:49.699: OSPF: Elect BDR
*Mar  1 00:58:49.703: OSPF: Elect DR
*Mar  1 00:58:49.703:        DR: (Id)   BDR: (Id)
*Mar  1 00:58:49.703: OSPF: Send immediate hello to nbr, src address, on FastEthernet1/0
*Mar  1 00:58:49.703: OSPF: Send hello to area 1 on FastEthernet1/0 from
*Mar  1 00:58:49.707: OSPF: End of hello processing 

At this point we've set ourselves up as an OSPF neighbor and successfully created an adjacency.

Now we'll inject a false route to network

Now R1 believes that it can get to network via F0/0 (real route) and F1/0 (bogus route). Both paths have the same cost.

R1#show ip route

C is directly connected, FastEthernet1/0 is subnetted, 1 subnets
C is directly connected, FastEthernet0/0
O [110/2] via, 00:00:00, FastEthernet0/0
                    [110/2] via, 00:00:00, FastEthernet1/0 is subnetted, 1 subnets
C is directly connected, Loopback0192.
O [110/3] via, 00:00:00, FastEthernet0/0

We didn't do any actual damage in this example, but this type of attack in an enterprise network could cause serious disruptions. 

This attack can be easily defeated in a number of ways. We can use OSPF authentication, passive interfaces, access control lists or route filtering. Actually all of the above should be used together. More on defenses some other time.  

LOKI supports both clear text (though I couldn't get it to work) and MD5 authentication for OSPF. Clear text is not much of security as the key is sent in clear text so it can be sniffed.  In 

LOKI detects type of authentication used and let's us attempt to crack it. We can feed it a word list or use brute force. LOKI cracked my key of "test" (not much of a key) on a slow VM in a couple of seconds.