Examples

0

Honeypot as a Service (HaaS) Part 1

Disclaimer:

This series will show some Ideas which include “homemade” Security Functions. For professional environments, I recommend to talk to the security Vendor of your choice to build up a secure environment. This series will show examples which include different VMware products and their Interaction and teach things which can be done with them.

Now, let’s start.

Today I will start a series which I call Honeypot as a Service (HaaS). What is the Idea behind the HaaS?

In most environments hackers are already a long time present bevor the get localized. When the hacker has access on one of the server, he will start to search for other systems where he can get access and grab sensitive information (credit card data, intellectual property). So, which are system / functions a hacker is locking for?

So, most Hacker are looking for routing information and will start a “slow and silence network scan” for systems which he can attack and get into his hands. When we now start to place virtual machines in our network, which doesn’t have any functions for our network nobody should access them in normal case. From the standpoint of an attacker, he doesn’t know if a system is relevant or not. That’s will be the point for us, to provide the hacker a system with an old infectible SMB Server which he can attack. So, if somebody / somewhat tries to access such an “no functional VM”, we generate a log entry which is forwarded to an Log system. There we can parse the logs and generated “automated” rules to isolate VMs or VM communications.

In this example, I will use a lot of different VMWare products to archive these HaaS environment and the actions we will use.

This series will include:

  • VMware vRealize Log Insight as log host
  • VMware vRealize Orchestrator as “workhorse for a lot of task”
  • VMware NSX for VM isolation and Firewall Rules
  • A small Linux System as Honeypot with an SAMBA Service

So, let start to build up a Linux System which we can use in our vRA Blueprint as Honeypot. I prefer a CentOS Distribution. I choose a 7.x Release of CentOS. The ISO can be downloaded here http://ftp.hosteurope.de/mirror/centos.org/7/isos/x86_64/

I will use the minimal Installation ISO and Install Samba and SSH afterwards.

We will change the Hostname and IP Settings for a later time in vRA so during installation we keep the hostname and network on default settings. We have one important things which we take care about during installation. By default, the NICs are not automatically connected during installation, so that should be changed.

After our Installation has finished we will install the following packages:

  • Perl
  • Samba
  • DNS tools (just for Troubleshooting)
  • Network Manager (Text Version if you need to reconfigure your Config)

This can be done via this command:

yum -y install perl samba system-config-network-tui.noarch dns-utils

When you don’t have a DHCP Server in place, then you need to configure your network settings on Command line: $ sudo ifconfig eth0 192.168.1.50 netmask 255.255.255.0

Also, you need to set your default route:

$ sudo route add default gw 192.168.1.1 eth0

As last step you need some DNS Server entries:

$ sudo vi /etc/resolv.conf

Modify or enter nameserver as follows:

nameserver 8.8.8.8

After we have installed the need packages we can start with the installation from the VMware tools. This is documented well in the VMware documentation so I will not write it down here.

The next Step is to configure our Samba Server for a SMB Share which is available for the attacker.

Now, let us create a fully accessed anonymous share for the users. Everybody can read/write in this share.

We create a directory called /samba/backup and set full permission. The reason (for me) to set the name to backup is, to mark the share as important and a useful target which information or potential interesting thinks in it. I also will create some additional folders to have a interesting target. I use a linux bash script to create the folder and set the required permissions.

#!/bin/bash
echo "This script creates a bunch of folder which were used in a samba share example on vcoportal.de"

dirname=/samba/backup

echo "$dirname"

if [ ! -d "/$dirname" ]

then

echo "Folder doesn't exist. Creating now"

mkdir --p "/$dirname"

echo "Create some other Folders ....."

mkdir --p "/$dirname/HR"

mkdir --p "/$dirname/IT"

mkdir --p "/$dirname/Dev"

mkdir --p "/$dirname/Public"

mkdir --p "/$dirname/Files"

mkdir --p "/$dirname/Userhome"

echo "Set some permissions for the parent Folder"

chmod -R 0775 /samba/backup

echo "Set nobody as Owner for the Folder so that everybody can read see and read it"

chown  nobody:nobody /samba/backup

echo "Change SE Linux Permissions on the Folder"

chcon -t samba_share_t /samba/backup

else

echo "Parent Directory exists"

fi

Just create a file and make it executable with the script content in it. You can change the directory names to whatever you want / need.

After we created the directory we must edit the Samba configuration file.

vi /etc/samba/smb.conf
# See smb.conf.example for a more detailed config file or
# read the smb.conf manpage.
# Run 'testparm' to verify the config is correct after
# you modified it.
 
[global]
        workgroup = vcoportal
        security = user
 
        passdb backend = tdbsam
 
        unix charset = UTF-8
        dos charset = CP932
 
        hosts allow = 127. 192. 172. 10.
 
        max protocol = SMB2
 
 
        map to guest = Bad User
 
        # log files split per-machine (the host logs are stored on a non-default path):
        log file = /var/log/samba/log.%m
Log level = 2
        # maximum size of 50KB per log file, then rotate:
        max log size = 50
 
 
[homes]
        comment = Home Directories
        valid users = %S, %D%w%S
        browseable = No
        read only = No
        inherit acls = Yes
 
 
[Backup]
comment = Backup Share
path = /samba/backup
browsable =yes
writable = yes
guest ok = yes
read only = no
force user = nobody

Now we can test the Samba server configuration

We can test the Samba server configuration syntax errors using the command ‘testparm’.

testparm

When everything looks good you can browse to your samba share.

 

 

 

 

That’s it for Part 1

 

Honeypot as a Service (HaaS) Part 2 Link: http://wp.me/p7tsEp-Cb
Honeypot as a Service (HaaS) Part 3 Link: http://wp.me/p7tsEp-Cl

0

vRO and the OpenStack Public API

This is the second post regarding the interaction of vRealize Orchestrator and OpenStack. The first Post can be found here:

vRO and OpenStack thoughts on the Orchestrator

As I already mentioned in the first post it is possible to interact from vRO with OpenStack. Before we start with an example I would point you to the OpenStack API structure.

OpenStack knows two different APIs.

–          The Public API

–          The Admin API

The APIs are accessible over different Ports. The Standard Port for the Public API is port 5000. The Admin API is accessible over Port 35357. The Ports can be changed in the configuration files. I used the standard ports in my environment. So when you try to build the workflows for our environment take a look at the used ports. I created my OpenStack Installation on a single host. This isn’t the best configuration and most installations will have different servers for the services. This is also something which a take care when you start to create the Demos.

Now let’s come back to the admin and the public API. The public API offers some functions but not all. For example you cannot create a user on the public API. Therefore you have to use the Admin API.

For the two APIs you have to use different authentication ways but we will come to that later.

OpenStack offers a lot of documentation regarding the functions which are available on the API. Here is a links which are useful for the development of the workflows.

http://docs.openstack.org/api/openstack-identity-service/2.0/content/preface.html

Every service in OpenStack has such a documentation. In my examples I will work with the Identify services were the link above pointed to.

First thing we have to do is to add the Rest Host to vRO. Due the circumstance, that you must use different ports to access the public and admin API you have to create to REST Hosts with different ports.

Just insert the needed information’s in the workflow for the host. If you server provide the possibility to use HTTPS just change the URL to use the secure Protocol to access the API. This is recommended!

I doesn’t need a proxy server so I can go  fast over this screen.

The last page is for Authentication. We provide the user information in our workflow so we doesn’t need the Host Authentication and set it to “none”.

After we have insert the REST Host we can start with the first workflow. Before we can “access” public API functions we have to authenticate to the Identity service.

The authentication is done with JSON formatted call to the API. The API response is also in JSON. To create the Authentication Token we have to make the Call to the OpenStack Server. The call is done as a PUT command to the /v2.0/tokens extension.

Here a quote from the API documentation mentioned above.

Client authentication is provided through a ReST interface by using the POST method with v2.0/tokens supplied as the path. Include a payload of credentials in the body.

The Identity API is a ReSTful web service. It is the entry point to all service APIs. To access the Identity API, you must know its URL.

Each ReST request against the Identity Service requires the X-Auth-Token header. Clients obtain this token, along with the URL to other service APIs, by first authenticating against Identity with valid credentials.

So, let’s use this information for a first workflow or better a first action which handles the authentication. My Action is named “OpenStackCreateAuthToken”. In vRO we start with a new action element. The Action itself need some parameter.

This parameter are required to specific the REST Host with parameter, Username, Password and so on. In the Scripting Section we insert this code:

// We need a Json formatted String for Authentication. We build together the JSON String with the information we request for the Workflow.

var content = '{"auth": {"passwordCredentials": {"username": "' + authUserName + '","password": "' + authPassword + '"}}}';

// After we have built the Json String we create the Session and insert the Answer in the Response

var SessionRequest = RestHost.createRequest("POST", "/v2.0/tokens", content);

SessionRequest.contentType = "application/json";

var SessionResponse = SessionRequest.execute();

// Show the Content

System.log("Session Response: " + SessionResponse.contentAsString);

//Split the response as Json

var JsonContent = JSON.parse(SessionResponse.contentAsString);

// Here we get the ID with is used for Authentication in the following sections.

var SessionIDKey = JsonContent.access.token.id

// Just for information

System.log(" Session Key: " + SessionIDKey);

// The Session ID Key were will work with

return SessionIDKey

I provided required information in the code itself for explanation.

After we have created our action, we create a New Workflow. I put it in a OpenStack Folder with the name “OpenStackGetTenants”.

On the Schema Tab I added the Action which I created before.

Now we need to Create Inputs for the Action. You can do this via Drag and Drop on the Visual Binding.

In the Attributes, I already insert some Values for the connection.

These values are required for the connection. Now let’s start with a first run.

When everything worked fine you become an Output similar to mine.

As we can see we got a session key which we can use in another workflow or action.

Now let’s create a second Action. I named it “OpenStackGetTenantID”. Like before we need some Inputs.

A lot of them we already used before.

Know lets create the script.

//Authenticate the request with the X-Auth-Token

var SessionRequest = RestHost.createRequest("GET", "/v2.0/tenants", null);

SessionRequest.setHeader("X-Auth-Token", SessionID);

var SessionResponse = SessionRequest.execute();

// Log which answer did we get from the API Request

System.log("Session Response: " + SessionResponse.contentAsString);

//Let's split the API Response to filter for our wanted information

var JsonContent = JSON.parse(SessionResponse.contentAsString);

var Tenants = JsonContent.tenants

// Now we want search for our specified tenant (Name)

for (var idx=0; idx < Tenants.length ; idx++) {

if (Tenants[idx].name.toLowerCase() == TenantName.toLowerCase()){

var TenantID = Tenants[idx].id;

}

}

// Let's provide the Output when it is not null

if (TenantID != null) {

System.log("Tenant Name: " + TenantName + " found");

System.log(" Session Key: " + TenantID);

return TenantID;

}

else{

System.log("Tenant not found!");

}

After we finished the Action we extend our Workflow we created before.

First we create an additional attribute to output the Tenant ID which can be used in following workflows.

After that we use the “Visual Binding” Editor to bind the parameter.

Validate the workflow and let’s run it.

As you can see I have an additional input. I use this input to filter the response for a specific Tenant. As you can see we found the tenant.

 

So this was an example of how to use the OpenStack Public API. In the next post we interact with the Admin API.

Have fun and orchestrate the World 😉

0

The Standalone VMRC Console and permissions…….

This Week I had a Customer requirement were the usage of the VMRC Plugin could be a good solution to resolve the issue. The customer had the requirement to use virtual machines as VPN gateways for connections outside his network. Therefore virtual machines were created and placed into a DMZ Zone. The customer Idea was, that his service staff could use the virtual machines to make VPN connections to external customers. One of the problems here is, that most VPN connections cut all other connections when the VPN connection is established.  These leads to the problem that RDP or VMware View connections could not be used because they are dropped when the tunnel came up……The Service people should not use a “full” Web Client therefore I made the suggestion to use the Standalone VMRC Console.

For those who are not familiar with the Standalone VMRC Console William Lam made a good post on it which could be found here: http://www.virtuallyghetto.com/2014/10/standalone-vmrc-vm-remote-console-re-introduced-in-vsphere-5-5-update-2b.html

After installing and configuration of the VMRC Console I created a new role on the vCenter Server. This role had the permissions to interact with the Client Console and some other stuff like stopping and starting the VM.

After that, I created used a group which was provided with the created role and permissions.

When I was finished, I made a test with the VMware Web Client and could access the console without any problems. I created links for the user so that could connect directly with the virtual machine without starting the VMware Web Client. The links I created was from type: vmrc://[VC]/?moid=[VM-MOREF-ID]

I didn’t used a Username in the call so every user could start the VM Console with his user and password. For me as administrator of the environment everything worked link expected…..

We rolled out the solution to the user. The user were requested to provide a Username and password but then get and error message.

I did some research and that but could find an answer in the first step…..after a chat with Joerg Lew  he pointed me to the right direction……Thanks Jörg!

When you use the Standalone VMRC Console with Username and Password the VMRC Console redirect the connections after the initial connection with the vCenter Server to the ESXi host. So I had to include the group with the permissions on the ESXi Hosts.

After that, the VMRC Console worked like a charm and we could solve the customer requirement without the usage of the VMware Web Client.

So have fun and orchestrate the World 😉

0

vCO and defensive scripting – practical experience

In the last couple of weeks I did a lot of Customer vCO Workshops to enable the Customers to create their own solutions. During the workshops I noticed some recurrent errors which were made from the  teams.

On some point of our Workflow, we will work with Userinputs. These Inputs can be direct Inputs from the users or maybe also Lines which are read from a file (CSV as example). Mostly these Inputs are compared to other Information’s . In this example I will use the ESX Hostname.

As you can see I have a VC with an cluster and one ESX Host with the name vmware01.example.com

Now we want to check if a Host with a specific name. So we use a really simple workflow.

In the scripting element I use this code:


for (i = 0; i < allHostsofVC.length; i++) {

if (HosttoCheck == allHostsofVC[i].name)

{

System.log("Yeah, we found the Host. Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

else

{

System.log("oh no......no host found.Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

}

So, now let’s make a first run

As we can see the search string and the hostname are identical.

Now let’s see what happens when the user write the hostname in Uppercase.

As we can see the name isn’t resolved. This leads to wrong results. The easiest way to avoid this is to change everything into LowerCase. So let’s modify our scripting element:

for (i = 0; i < allHostsofVC.length; i++) {

if (HosttoCheck.toLowerCase() == allHostsofVC[i].name.toLowerCase())

{

System.log("Yeah, we found the Host. Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

else

{

System.log("oh no......no host found.Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

}

Let’s start the last run again:

Also the User Input and the return string are different, we got the correct match.

This example leads us to another problem when we have to catch a user input regarding the hostnames. Most users tend to write only the name as shortname.

We can check it with the code we used before.

As we can see we didn’t catch the server. Why can we see in the vCenter Server MOB Browser. The Server is registered with the FQDN and from VMware API sight the shortname isn’t available.

How can we solve this problem? It is quite easy……. We just split the name at the dot and compare it with the name.

for (i = 0; i < allHostsofVC.length; i++){

var HostShortName = new Array()

HostShortName = allHostsofVC[i].name.toLowerCase().split(".")

if (HosttoCheck.toLowerCase() == allHostsofVC[i].name.toLowerCase() || HosttoCheck.toLowerCase() == HostShortName[0])

{

System.log("Yeah, we found the Host. Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

else

{

System.log("oh no......no host found.Input is " + HosttoCheck + " Value from allHostsofVC[i].name is: " +  allHostsofVC[i].name);

}

}

Then we get our Hostname also when it is insert as shortname.

So, hope this help some to get their workflow created without to big problems. Have fun and Orchestrate the world 😉

0

vCO and the parseInt JavaScript “Bug”

Today I was by a customer to develop a Custom workflow to evacuate one of his DCs with vCO. The evacuation should be done by only invoking an String into the Workflow. The Hosts were stretched over both DCs and also the Datastores. The ESX Hosts in his environment were named with vmwareXX were the XX represent a number. For the DC1 the Hosts had an even number. The Hosts in the DC2 the numbers are even.

There were hosts with names from

vmware01 till vmware24

So we developed some task to get the Datastores and the Hosts to divide them to their correct DCs. Therefore we created two Arrays were the hosts were placed for future actions. The names of the hosts were split and the Number was taken into a variable as integer. We made this with the command:

substring = parseInt(Hostname[i].substring(6,8))

After we had the number, we created an loop with if-else and placed the Hosts into the correct array.

var Odd_array = new Array ()

var Even_array = new Array()

var Nametemp

var Substring

for (i = 0; i < Hostname.length; i++) {

substring = parseInt(Hostname[i].substring(6,8))

System.log("Substring = " + substring + " Hostname = " + Hostname[i])

if (substring % 2)

{

//it is odd

Odd_array.push(Hostname[i])

System.log( Hostname[i] + " is in Odd Array")

}

else

{

//it is even

Even_array.push(Hostname[i])

System.log( Hostname[i] + " is in even Array")

}

}

The above script generates this output.

Take a deeper look on the part with the hostnames vmware07 to vmware09. As you can see we get wrong results. The Host with the Name vmware07 was in the correct Array. The Hosts with the name vmware09 was in the even array were it was wrong.

It took some time to figure out that this is a JavaScript parseInt “Bug”. A good explanation about this behavior can be found here:

http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256C85006A6604

So for us the solution was to use

substring = parseInt(Hostname[i].substring(6,8), 10)

as command and everything worked like expected.

Maybe everyone expect me did not this before but this information could be useful for others so that is the reason why I created this post.

Have fun and orchestrate the World 😉