SQL Injection Example

12/10/2015 22:08:33
Luke McGrane

For years I’ve known that SQL injection is bad and how to protect against it. In fact, I’d go so far as to say that everything except the very first classic ASP pages I wrote were safe against malicious SQL but for some reason I’d never actually tried attacking a vulnerable page to see what was really so bad about it.

We all know the XKCD comic about little Bobby Tables and yes you could simply drop the tables or database very easily on an unsecured page but what if you aren’t simply bent on destruction? As developers we spend our lives building little hand-holds into application to stop people breaking things, and that’s just for those that aren’t trying to do anything bad! What about those that want to slip in, infiltrate, and hold your organisation to ransom?

Here’s a brief example of how easy (scary) it is for one unchecked variable to be used as the gateway to read your entire database.

Some things to note:

  • The pages are classic ASP because .NET does not easily let you be so careless
    • PHP, just like Linux, will let you do what you want even if that is pure self-destruction
  • The database back-end is MSSQL Express but this doesn’t matter too much as the theory is the same for any DB backend

First, I’m greeted by a login prompt:

Simply enter a single apostrophe into either field to see if this page is vulnerable.

Awesome! Not only is the page vulnerable, it’s got error reporting turned on so I can see the exact part of the query I’m interested in! This error is saying there is “unclosed quotation mark” in the query which means the apostrophe we entered has been taken literally by the server and executed as part of the query. Simply because of one extra quotation mark the query fails because MSSQL can’t figure out where each string starts/ends.

How can this be exploited? Well, commonly a low-tech self-made login process would select a record where the username and password both exist. Now we’ve seen part of the SQL statement this website uses we can see if we can “log in” without a password, just for fun…



Jackpot. We’re technically logged in but apparently only as BasicUser which just so happens to be the first user out of the database in the very simplistic query we tried. At this point any developers should be thinking this is pretty bad and that they’d never leave any unchecked user input. Read on…

I’ve logged in but I don’t know anything about this server or its secrets. I’ve decided I want to know:

  • What user tables there are
  • What columns each table has
  • List all usernames and passwords

So, step one, I’d like to know how many tables there are so I enter this into the username part of the login prompt:

' UNION SELECT 1, count(*), '3' FROM sys.objects WHERE type='u';--

There are only two tables in this database so it shouldn’t take long to list them all, except that I can’t simply list all the tables as I’ve only got one output to work with which seems to be trying to welcome the visitor by name. I guess I’ll have to do it one-by-one:

' UNION SELECT 1, name+'+'+convert(varchar,[object_id]), '3' FROM sys.objects WHERE type='u';--

Hey look there’s a messages table, I guess these users can chat to each other. I’ve outputted the object ID because that’s what I’ll use to get the columns later. But first I want to know what the other table is so I’ll exclude Messages and do the query again:

' UNION SELECT 1, name+'+'+convert(varchar,[object_id]), '3' FROM sys.objects WHERE type='u' AND name NOT IN ('Messages');--

Now I can get the field names for each table by doing a similar query but this time looking at sys.columns:


' UNION SELECT 1,name,3 FROM sys.columns WHERE object_id = 277576027;--

Now I’ve got a column I can use “AND name NOT IN(….)” again to get them all and repeat the process for both tables. Here’s the result:

Users (ID: 245575913)

Messages (ID: 277576027)










I wonder if logging in as “admin” will work, assuming the account exists. Due to how there’s completely no security on this page I could simply put ‘ OR Username = ‘admin’;-- into the username field so if there is an account with that name it’ll log me in without needing the password but that’s easy, what if I want to actually know the password? Very easy, I just do the same sort of query as above:

' UNION SELECT 1,Password,3 FROM Users WHERE Username = 'admin';--

The password is ‘admin’ !! Not only is the page SQL injection vulnerable the username/password policy is ridiculous too and every good developer knows to NEVER have something like this in their code… don’t you ;)

Also, once logged in as admin it seems something else cropped up and it looks like a message from BasicUser. It’s important to note here that the messages sent to the administrator appear because the username and password are both ‘admin’ and would not have shown up otherwise. This is because the example looks for messages sent to a Username so by using the above query to get the password the application would think the password was the username and find no messages logged against it.

Now I know there is somewhere that does an iterative list to output a record set and I know what columns it will use I can get a little more creative and simply list all usernames and passwords from this database:

' UNION SELECT 1,''' UNION SELECT Id,Username,Password,Password FROM Users;--',3;--


In conclusion, I hope this shows you that the little SQL bug you have in a project which crashes whenever anyone called O’Leary turns up is absolutely worth fixing right now.

NOTE: I have omitted some details explaining exactly what each SQL query does as this post is intended to explain to a developer why SQL injection vulnerabilities are a critical security flaw, not just something that results in a few errors every now-and-then. 

Microsoft Edge hmm we can't reach this page

07/09/2015 19:09:00
Luke McGrane

Microsoft Edge, the new name for (or replacement to) Internet Explorer, has a bug where it may not be possible to browse any websites unless you are connected to a 'Private' network.

Changing the network location has traditionally been very difficult but Windows 10 includes an easy way of doing this. In the control panel look for Home Group and choose to search for other machines on the network and allow yours to be discoverable. Now Edge will work

Source: tinkertry.com

WMI Windows Management Instrumentation

08/08/2015 14:52:18
Luke McGrane

I am running a VPS with only 50Gb disk space so have to regularly clear log files and such which, as an unimportant server only personal stuff, I wasn't too fussed about automating. This VPS was purchased originally so I could code things and try them out online so I decided to look into building a tool to easily visualise the state of a Windows system.


There's so much information about WMI that it can be difficult to know where and how to start so my first stop is to begin getting to grips with what exactly WMI is in terms of what the relationship is between it and the things it is telling you about and what the data model looks like.

WMI uses the Common Information Model (CIM) to interact with, and even control, system data. The Wikipedia article explains that this model is updated regularly and provides a helpful link to the Distributed Management Task Force site where the specifications are publically available. For example, this is the current (from June 2015) complete CIM specification: DMTF Schema Documentation 2.44.1.

At this point I now have the information available to know exactly what is possible through WMI but this is entirely different to what Windows will actually let me do. The next step is to decide on how I'm going to interact with WMI.

The MSDN has a helpful article which gives an overview of what providers can be used and how they work. From the WMI Architecture article I know that anything which can query COM will work and that .NET is by design the best choice.

Coding begins...

It's at this point where things get tricky because there are several ways of working with WMI and it seems you, as the programmer, kind of need to know all of them to get anything useful in .NET because you're simply provided some objects like ManagementObject and ManagementClass and left to your own devices. There is no nice enum of every piece of information you might want to pull from WMI and while you can search online it's very likely the 'name' of something that looks interesting simply won't work through .NET. Also, the DMTF CIM scheme documentation gives you their name for everything but Microsoft obscures this by modifying their implementation of the scheme. For example, CIM_PROCESS is now WIN32_PROCESS. This does actually make sense in one way as CIM is a method of describing data and it can be used on far more than just Windows but Microsoft want to give their users only information relevant to Windows and, of course, put their own spin on things.

Thankfully Microsoft have listed all of their WMI classes on the MSDN and that is exactly what I've been searching for: Performance Counter Classes.

using System;

using System.Windows.Forms;

using System.Management;


namespace WMITesting


    public partial class Form1 : Form


        public Form1()





        private void Form1_Load(object sender, EventArgs e)


            ManagementClass mc = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");


            foreach (var p in mc.Properties)

                textBox1.AppendText(string.Format("{0}={1}\r\n", p.Name, p.Value));




This works in as much as it gives some information back to me but, oddly, the collection it returns does not contain any values.

As it turns out, all this code does is create a new instsance of Win32_PerfFormattedData_PerfOS_Processor instead of requesting a proper one from the system. Getting it to actually get any values from the system is confusing at first and I learned that WQL is used for ManagementObjectSearcher while a 'standard' ManagementPath will use something like \\.\root\CIMV2: Win32_LogicalDisk.DeviceID="C:" as the example shows in MSDN. I know what information I want so I don't want to do a search every time the application updates so I need to find how to get a current instance of Win32_PerfFormattedData_PerfOS_Processor which means finding what that 'path' should be. Clearly the application needs to be told where to look to get the data and this is done using ManagementScope.

private void Form1_Load(object sender, EventArgs e)


            ManagementScope wmiScope = new ManagementScope(@"\\.\root\cimv2");

            ManagementPath wmiPath = new ManagementPath("Win32_PerfFormattedData_PerfOS_Processor.Name=\"_TOTAL\"");

            ObjectGetOptions wmiOptions = new ObjectGetOptions(null, TimeSpan.MaxValue, true);

            ManagementObject wmiObject = new ManagementObject(wmiScope, wmiPath, wmiOptions);


            foreach (var p in wmiObject.Properties)

                textBox1.AppendText(string.Format("{0}={1}\r\n", p.Name, p.Value));




What if I want more granular information instead of just looking at _TOTAL for the process class or C: for the disk. I might want to list everything that's available and let the user decide. After a lot of playing around and trying to avoid using the searcher it became clear that ManagementObject is for single instances while ManagementClass lets you get all instances of the class.

private void Form1_Load(object sender, EventArgs e)


    ManagementScope wmiScope = new ManagementScope(@"\\.\root\cimv2");

    ManagementPath wmiPath = new ManagementPath("Win32_PerfFormattedData_PerfOS_Processor");

    ObjectGetOptions wmiOptions = new ObjectGetOptions(null, TimeSpan.MaxValue, true);

    ManagementClass wmiClass = new ManagementClass(wmiScope, wmiPath, wmiOptions);

    var wmiInstances = wmiClass.GetInstances();


    foreach (var i in wmiInstances)

        foreach(var p in i.Properties)

            textBox1.AppendText(string.Format("{0}={1}\r\n", p.Name, p.Value));



This code gives the same output as before but with data and includes every instance of the Win32_PerfFormattedData_PerfOS_Processor class.


That's it for this post. I've gone from using WMI only through the command line to knowing where to find all the class names & their descriptions then pulling back individual or all instances of that class in any application I want. The next obvious step is to query remote computers but I'm thinking of looking at how to display the data in a different way and may do another post about it at some point.

© Luke McGrane 2016 Login