How to Build Your Own Website Uptime Monitoring Script using VBScript: Part 1

Website Uptime Monitoring: The Basics

There are lots of website uptime monitoring services out there but all the components you need to build your own website monitoring tool can be found in good ole’ Microsoft VBScript.

Stop laughing, I’m not kidding!

In this article, I’ll share with you some scripts and tips I’ve used successfully in the past for monitoring website uptime even if your website is running in a complex load balanced enterprise environment which some of mine are.

VBScript Components for Uptime Monitor

Most people don’t know that VBScript can make Ajax HTTP calls but it can.

We will use VBScript’s ability to make Ajax HTTP calls to our website to see if it responds then put some simple logic around that response to log the results in a text/csv file.

It really is amazingly simple once you get all the code components together.

The ISWebSiteUp Function

The ISWebsiteUp function takes a URL string and makes an Ajax HTTP call to see if we get a HTTP code 200 or 404 returned meaning website loaded OK.

Once we get our 200 or 404 HTTP response code that, script returns true in the form of a text message box or if script times out you’ll get a false in an error message box.

You might be saying to yourself about now, what about the 404 response code for page not found. Yes, you might want to add some more code to handle that differently than a 2oo OK response but for this script, we just want to know if server is up. If we are pointing to a page at the root of a domain, we don’t typically get 404 errors in reality.

The Script Code

To use this code, copy it in to a text file and save it with a .vbs file extension for VBScript. Once you have the .vbs file, double click on it and you should get a message box with the names of the logged in user on the specified Windows PC on your network.


'isWebsiteUp: Takes String URL 
'isWebsiteUp: Returns strMessage in Message Box
Function isWebsiteUp(strURL)

	On Error Resume Next

	Set http = CreateObject("MSXML2.ServerXMLHTTP")
 	'Set http = CreateObject("Microsoft.XmlHttp")
	http.open "GET", strURL, False
	http.send ""

	'Only check for error of the HTTP Get request for 200 or 404 code returned. If any status is returned then the server is up
	if http.responseText <> "" AND err.number = 0 then
		'Commented out showing the response text. Use this for troubleshooting or exploring.
		'msgbox(http.responseText)
		isWebsiteUp = true
		strMessage = "is up"
	else
		isWebsiteUp = false
		strMessage = "is down"
	end if
	Set http = Nothing	

	msgbox(strURL & ":" & strMessage)
	err.clear
End Function

call isWebsiteUp("https://www.google.com") 

What the Web Server Sees in the HTTP call: WinHTTPRequest User Agent

The VBScript Ajax HTTP call to the web server presents itself as a web browser asking for the home page.

In the server logs a server admin may see this “User Agent” in their logs.

Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)

Script Errors & Blocked HTTP Calls

This script works out of the box. Google is the most open website in the world in terms of IPs that their servers accept traffic from as they are in the business of collecting data about everything including every system that connects to it.

Other web servers, like ones I run, may not be so forgiving. Many server admins use many tools at their disposal to filter HTTP request at various levels.

Here are some examples of tools Windows Server Admin have at their disposal to block or filter your script from connecting to their web servers.

Windows Server Admin Tools for Handling HTTP Traffic

  • Firewall IP Restrictions (Window Server Admin)
  • HTTP Response Filtering (IIS Application Server Admin)
  • IP Restrictions (IIS Application Server Admin)

VBScript WMI: How to Get Computer Serial Number from Local or Remote Windows PC

This Windows WMI script using VBScript, retrieves the serial number of the local or networked computer.

To use this code, copy it in to a text file and save it with a .vbs file extension for VBScript. Once you have the .vbs file, double click on it and you should get a message box with the names of the logged in user on the specified Windows PC on your network.

Windows WMI VBScript

Function GetComputerSerialNumber(strComputer)
	Set objWMIService = GetObject("winmgmts:" _
		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 

	Set colComputer = objWMIService.ExecQuery _
		("SELECT * FROM Win32_ComputerSystemProduct",,48)
	 
	For Each objComputer in colComputer
		GetComputerSerialNumber = objComputer.IdentifyingNumber
	Next	
	
End Function

'strComputer = "XPS1234"
strComputer = "."

' Pass a . to run this on your own PC or add a string value for another on your network
call msgbox(GetComputerSerialNumber(strComputer))

VBScript WMI: How to Get Logged in User from a Windows PC

If your in need of finding out who is logged on to a specific Windows PC on your network, run the VBScript below.

When executed, you’ll see a message box with the name of the account currently logged in the computer specified.

The VBScript Code

To use this code, copy it in to a text file and save it with a .vbs file extension for VBScript. Once you have the .vbs file, double click on it and you should get a message box with the names of the logged in user on the specified Windows PC on your network.

Function GetLoggedinUser(strComputer)
	Set objWMIService = GetObject("winmgmts:" _
		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 

	Set colComputer = objWMIService.ExecQuery _
		("Select * from Win32_ComputerSystem")
	 
	For Each objComputer in colComputer
		Wscript.Echo "Logged-on user: " & objComputer.UserName
	Next	
	
End Function

' Pass a . to run this on your own PC or add a string value name for PC on your network
'strComputer = "XPS1234"
strComputer = "."

call msgbox(GetLoggedinUser(strComputer))

Stay tuned for more scripts in upcoming blog posts!

Hope this helps somebody!
~Cyber Abyss

VBScript WMI: Get List of Administrators from Windows PC

I’m breaking down a large VBScript I wrote as part of a larger computer inventory system prototype I built for what later became a much larger company.

This project was a big time investment for me that provided a lot of value to the company until they went out and purchased a commercial product and even then, the commercial product had things it did not do as well as my prototype.

The scanning volume eventually got so big that I had to run copies of the script on different parts of Active Directory at the same time to try and scale the scanning of computers on the network with all the data being stored in a SQL database backend.

This script and others I’ll be sharing in this series were contained within a loop of Active Directory computer records for a good size enterprise with about 10,000 desktops and laptops for some Active Directory OUs.

This script leverages Windows Management Instrumentation (WMI) to query what’s going on with this Windows network PC.

The first piece of code I’m sharing is for querying the Windows WMI to get a list of Administrators from a Windows PC. This code was used as part of a project to determine if any computers had unauthorized admin accounts we didn’t know about.

GetAdminstrators Function

To use this code, copy it in to a text file and save it with a .vbs file extension for VBScript. Once you have the .vbs file, double click on it and you should get a message box with the names of the admin accounts from the target device.

Function GetAdministrators(strComputerName)
On Error Resume Next

    Dim objWMIService, strQuery, colItems, Path, strMembers, strAdminList, iCounter
	iCounter = 0
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputerName & "\root\cimv2")
    strQuery = "select * from Win32_GroupUser where GroupComponent = " & chr(34) & "Win32_Group.Domain='" & strComputerName & "',Name='Administrators'" & Chr(34)
    Set ColItems = objWMIService.ExecQuery(strQuery,,48)
    strMembers = ""
    For Each Path In ColItems
		Dim strMemberName, NamesArray, strDomainName, DomainNameArray
        NamesArray = Split(Path.PartComponent,",")
		strMemberName = Replace(Replace(NamesArray(1),Chr(34),""),"Name=","")
		DomainNameArray = Split(NamesArray(0),"=")
        strDomainName = Replace(DomainNameArray(1),Chr(34),"")
        If strDomainName <> strComputerName Then
            strMemberName = strDomainName & "\" & strMemberName
			if iCounter = 0 then
				strAdminList =  strMemberName
			else
				strAdminList = strAdminList & " > " & strMemberName 
			end if
			iCounter = iCounter + 1
			
        End If
	Next
	
	GetAdministrators = strAdminList
End Function
' Pass a . to run this on your own PC or add a string value for another on your network
call msgbox(GetAdministrators("."))
call msgbox(GetAdministrators("NetworkComputer1"))

Stay tuned for more scripts in upcoming blog posts!

Hope this helps somebody!
~Cyber Abyss

VBScript Error – MSXML3.dll error ‘800C0005’

This is a popular re-post from my old Blogger blog.

I’m working on  a website up-time monitoring script.

After I had my initial prototype working, I received more requirements for logging output to CSV in addition to storing output in Access DB and decided to add CPU usage percentages to the logging.

Once I had all that done, I started getting odd errors when solution should be detecting a down-time event.

Testing the script with older version of Microsoft.XmlHttp had issues where certain but not all websites the script would call were incorrectly displaying HTTP status code 404 but a 200 OK was really sent back verified by using Fiddler.  Very odd behavior.

The error is related to VBScript’s use of the older version of the Microsoft.XmlHttp object.

The Code

Function isPortalOffline(strURL)
 'Set WshShell = WScript.CreateObject("WScript.Shell")
 Set http = CreateObject("Microsoft.XmlHttp")

 http.open "GET", strURL, False
 http.send 
 
 'Only check for error of the http Get request
 if err.Number <> 0 Then
  isPortalOffline = True
 Else
  'Wscript.Echo "error" & Err.Number & ": " & Err.Description
  isPortalOffline = False
 End If

 'Clear the error after setting isPortalOffline
 err.clear
 'set WshShell = Nothing
 Set http = Nothing 

 ReportError("isPortalOffline")
End Function

Error: MSXML3.dll error ‘800C0005’ The System cannot locate the resource

Changed MSXML Objects.

The Fixed Code

Replaced Microsoft.XmlHttp with MSXML2.ServerXMLHTTP.

Function isPortalOffline(strURL)
 'Set WshShell = WScript.CreateObject("WScript.Shell")
 Set http = CreateObject("MSXML2.ServerXMLHTTP")

 http.open "GET", strURL, False
 http.send
 
 'Only check for error of the http Get request
 if err.Number <> 0 Then
  isPortalOffline = True
 Else
  'Wscript.Echo "error" & Err.Number & ": " & Err.Description
  isPortalOffline = False
 End If

 'Clear the error after setting isPortalOffline
 err.clear
 'set WshShell = Nothing
 Set http = Nothing 

 ReportError("isPortalOffline")
End Function

This resolved my issues!

I hope this helps someone. 🙂

InfoSec Tip: What’s in those web server 404 NOT FOUND errors?

Catching Bad Guys using Web Server 404 Errors!

404 NOT FOUND pages in your web server logs are often the earliest sign of surveillance, foot printing or reconnaissance.

This probing event I caught was using the IP, bypassing DNS while probing for non-existent file called “/admin/config.php” all the way from Ramallah Palestine. #Infosec#OSINT#cybersecurity

Hope this helps someone!

Regards,
Rick

3 Low Cost Ideas to Address RDP Brute Force Attacks on Your Windows Web Server

Its late at night, I’m remoted in to my Windows web server. I’m reviewing the event logs and see something suspicious. Audit failures in the Security event logs.

The next 7 hours had me consumed in learning everything I can about “Brute Force RDP Attacks” and try to apply it to my server ASAP.

Before I go any further, I want to reiterate that this a hobby server I run. This is not a server I work on for my day job in a large enterprise environment. Hence the focus on low cost solutions.

First, Remote Desktop Protocol (RDP), is probably one of the most commonly unsecured items on Windows web servers which is also why your server is going to be relentlessly pounded by scanning tools and hackers trying to access your server via RDP, usually via port 3389.

Video: Brute Force Attack with Hydra Hacking Tool

I could just block port 3389 and move on with my life but I personally prefer to access this particular server via RDP to handle administrative tasks. Everything else is done via FTP or telnet.

I run all my hobby servers on a super tight budget. This article will discuss what I learned and how I applied that knowledge to mitigate some of the risk associated with managing Windows servers exposed to the Wild Wild West (WWW) with RDP connections using techniques that are no cost except for your time to implement.

Low Cost Ideas for Mitigating RDP Brute Force Attacks on Your Windows Servers

  1. Use Strong Passwords
    • Strong passwords are your first and best defense for any RDP brute force attack.
      • Use a password with a length or 12 character or more.
      • Don’t use words that can be found in a dictionary
      • Use a combination of UPPER CASE, lower case, numbers and special characters
      • Be Social Media aware! Don’t use friends, family, pets or info that could be derived from Social Media posts.
  2. Clean Up Old User Accounts
    • Make sure only the accounts you need are on your server.
    • Fewer accounts reduces possible attack vectors.
    • Also validate the level of access of the accounts on your server.
  3. Update Windows Firewall Rules
    • Exclude IP Ranges for Countries with highest amount of hacking.
    • See steps below for updating your Windows Firewall configuration to block IP ranges for China, Russia and North Korea.

Before You Mess with Your Firewall

The PowerShell script I cover below worked great but then decided to build a firewall rule manually for South American IP addresses and re-learned a very important lesson about working with Firewalls.

A word of caution: Don’t build your Firewall IP restrictions manually.

Always script them out in PowerShell. If you’re not 100% awake and paying attention, you will find yourself blocked out of your server and kicking yourself in the ass like I did.

Thankfully, I have a great hosting company, AccuWebHosting, who has been able to un-do all my screw ups so far. I’ve used them happily for many years and highly recommend them. I pay about $500 a year for a decent Windows server VPS with great support.

Use Windows Firewall to Block IP Ranges for China, Russia and North Korea and many others.

The steps to block IP ranges using Windows Firewall are pretty simple.

  1. Create a directory for working with PowerShell and PowerShell Scripts.
    • Example: C:\ip-security
  2. Go to this page click on Step 2 link to download your PowerShell scripts zip file.
  3. Extract contents of the the ip-security-package.zip file to your “C:\ip-security” folder.
    • You folder should look like this:
  4. Open PowerShell from the Command Line as an Administrator so you’ll have the correct rights to make changes to the Windows Firewall
  5. Run this command to make sure PowerShell is in the right mode
    • “Set-ExecutionPolicy Bypass”
    • Type “Y” when prompted to access the change
  6. Type the following commands to import the IP Range Exclusions in to Windows Firewall.
    • Import-Firewall-Blocklist.ps1 -inputfile china.zone.txt
    • Import-Firewall-Blocklist.ps1 -inputfile russia.zone.txt
    • Import-Firewall-Blocklist.ps1 -inputfile northkorea.txt
  7. You should now have IP blocks in your firewall.

If you’ve done these three things, your web server is better prepared than most.

Some Closing Thoughts on Web Server Security

Security on the internet is hard and ever changing. Running your own server for your hobby or side hustle can be done but can be very frustrating and overwhelming at times. Do as much of what I covered as you can.

We covered a few options above, but if you get nothing else from this article, make sure your passwords are long and hard to guess as this is the last defense before a bad guy gets access to your system.

From meetings I’ve been in with Enterprise engineers, passwords of 12 characters or more are best. Rainbow hash attacks can typically get most common passwords less than 12 characters. Scary, right?

Don’t use passwords made from words that can be found in a dictionary and now with the new world of social media, avoid using your kids, significant other or pet’s name or other references that can be guessed from online posts.

In one of the attacks that prompted me to write this article, one attacker used my youngest Son’s full name. I don’t use Facebook anymore so there only a few places you could go to figure that out.

I hope this story helps someone else on their IT Journey.

Regards,
Rick Cable
Lost in the Cyber Abyss

References:

https://www.gregsitservices.com/blog/2016/02/blocking-unwanted-countries-with-windows-firewall/

http://www.ipdeny.com/ipblocks/

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-6