Implementing #EV #X509 parsing in C# (.NET Core)

Security certificates can be DV (Domain Validation), OV (Organisation Validation) or EV (Enhanced Validation).

DV will prove that the domain you are visiting is what it says it is, but says nothing about the organisation that runs the domain. It’s perfectly possible for a hacker legally purchase the domain “Micr0s0ft.com” (note the zero), and get a DV SSL cert for it. The DV is not saying that the hacker has any relation to the company “Microsoft Inc”, it’s just saying that the domain has been externally validated to respond to a basic ownership challenge.

OV and EV go a step further, and the certificate issuer will take extra manual steps to verify, that the domain is owned by a given company, and/or at a particular address.

This level of EV validation is then stored in the Subject line of the Certificate, and can be read by all visitors of the site. Browsers will typically highlight the extra level of trust and verification with a green tick in the address bar.

Reading and parsing the subject line can be done with some C# code shown at this repo; https://github.com/infiniteloopltd/EvCertParser

The code to get the cert is as follows;

public async Task<EvCertificate> Request(string url)
{
	EvCertificate certificate = null;
	var handler = new HttpClientHandler
	{
		UseDefaultCredentials = true,
		ServerCertificateCustomValidationCallback = (sender, cert, chain, error) =>
		{
			var export = cert.Export(X509ContentType.SerializedCert);
			certificate = new EvCertificate(export);
			return error == SslPolicyErrors.None;
		}
	};
	using var client = new HttpClient(handler);
	using var response = await client.GetAsync(url);
	return certificate;
}

Which can evidently throw errors if the URL is invalid, doesn’t have a cert, or an invalid cert.

Categories: Uncategorized

Making a DataReader behave like a DataSet #sql #dotNET

In C# / .NET a DataSet is easy to use, you can iterate over it using a simple For Loop, however, if you are using a large query like “select * from hugeTable” then you’ll find that the memory footprint, plus the time taken to read the whole dataset into memory is prohibitive.

Using a DataReader is the alternative, where you explicitly specify when you want the next row, so hopefully, the first row of your query will return faster. But, client code can’t use a simple for loop to iterate over the data.

So, here is my hybrid solution;

public static IEnumerable<Dictionary<string, object>> PopulateReader(string command)
{
	var sqlConnection = "---READ DSN FROM CONFIG---";
	var connection = new SqlConnection(sqlConnection);
	connection.Open();
	var sqlCommand = new SqlCommand(command, connection);
	var reader = sqlCommand.ExecuteReader();
	while (reader.Read())
	{
	    var result = new Dictionary<string, object>();
	    for (var column = 0; column < reader.FieldCount; column++)
		result.Add(reader.GetName(column), reader.GetValue(column));
	    yield return result;
	}
	connection.Close();
}

And your client can call this, in a very similar way to how a DataReader would be called.

var reader = PopulateReader(sql);
foreach (var dr in reader)
{
	var id = dr["id"].ToString();
	... 
}

Hope this helps, or acts as inspiration for someone!

Categories: Uncategorized

Retrieving state in a FirstChanceException in .NET

If you’re using a application-wide FirstChanceException handler, this is great for covering lots of bases at once, it helps make sure that you can catch (and record) an exception even if it happens with a bit of code you didn’t expect.

However, the scope of the handler is what it is, so accessing state, and hence, the context of the error, is going to be tricky. After all, it’s helpful to know where the error happened, but what was the state of your application at the time, is there an edge-case that causes the error?

So, Lets try and demonstrate this issue, in a simplistic example.

static void Main(string[] args)
{
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
    {
	Console.WriteLine("An Error occurred, but at what state?");
    };
    Parallel.For(-100, 100, (state) =>
	{
	    if (state == 42)
	    {   
		throw new ArgumentException("Some error with state #42");
	    }
	}
    );
    Thread.Sleep(TimeSpan.FromSeconds(5));
}

So, in this example, we can see that state number 42 causes an error. The FirstChance exception is triggered, but within the handler, we cannot tell what state causes the error.

If we try a naïve approach, and just try storing the state in a static variable, and then report the last known value, let’s see what happens;

private static int lastKnownState = 0;
static void Main(string[] args)
{
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
    {
	Console.WriteLine($"Last Known state {lastKnownState}");
	Console.WriteLine("An Error occurred, but at what state?");
    };
    Parallel.For(-100, 100, (state) =>
	{
	    lastKnownState = state;
	    if (state == 42)
	    {   
		throw new ArgumentException("Some error with state #42");
	    }
	}
    );
    Thread.Sleep(TimeSpan.FromSeconds(5));
}

In this case, “lastKnownState” returned as 99, not 42. It may be a different value on your computer, but it’s important to note that it’s not correct. Since the lastKnownState gets overwritten by multiple threads, and so it’s not thread-safe.

So Attempt #2, let’s create a concurrent Dictionary, store the states associated with each thread, then lookup the state within the FirstChanceExceptionHandler.

public static ConcurrentDictionary<int,int> ThreadStates = new ConcurrentDictionary<int, int>();
static void Main(string[] args)
{
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
    {
	var ok = ThreadStates.TryGetValue(Thread.CurrentThread.ManagedThreadId,out var state);
	if (ok) Console.WriteLine($"An error occurred at state {state}");
    };
    Parallel.For(-100, 100, state =>
	{
	    ThreadStates.TryAdd(Thread.CurrentThread.ManagedThreadId, state);
	    if (state == 42)
	    {	      
		throw new ArgumentException("Some error with state #42");
	    }  
	}
    );
    Thread.Sleep(TimeSpan.FromSeconds(5));
}

This looks right, but, it’s not. The state is still incorrect within the Exception Handler? Why is this. Well, because Parallel.For will recycle threads. Which means that the “ManagedThreadId” can be the same for multiple states. The TryAdd will ignore duplicates, so data will be lost.

public static ConcurrentDictionary<int,int> ThreadStates = new ConcurrentDictionary<int, int>();
static void Main(string[] args)
{
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
    {
	var ok = ThreadStates.TryGetValue(Thread.CurrentThread.ManagedThreadId,out var state);
	if (ok) Console.WriteLine($"An error occurred at state {state}");
    };
    Parallel.For(-100, 100, state =>
	{
	    ThreadStates.TryAdd(Thread.CurrentThread.ManagedThreadId, state);
	    if (state == 42)
	    {
	      
		throw new ArgumentException("Some error with state #42");
	    }
	    ThreadStates.TryRemove(Thread.CurrentThread.ManagedThreadId, out var oldState);

	}
    );
    Thread.Sleep(TimeSpan.FromSeconds(5));
}

So, the trick is to remove the state from the ThreadStates collection once complete, using the code highlighted in bold.

Now, that’s working, let’s refactor the code to keep the specifics of the code separate from the main logic flow. So, I’m creating a class called ThreadContext as follows;

public sealed class ThreadContext<T> : IDisposable
{
	private static readonly ConcurrentDictionary<int, T> ThreadStates = new ConcurrentDictionary<int, T>();

	public static T RetrieveState()
	{
	    var ok = ThreadStates.TryGetValue(Thread.CurrentThread.ManagedThreadId, out var state);
	    return ok ? state : default;
	}

	public void Dispose()
	{
	    ThreadStates.TryRemove(Thread.CurrentThread.ManagedThreadId, out var oldState);
	}

	public ThreadContext(T state)
	{
	    ThreadStates.TryAdd(Thread.CurrentThread.ManagedThreadId, state);
	}
}

Notice, that the class is now generic, so that it can hold any nullable object – like a string, a nullable int, or something much more complex.

Now the Main method becomes

AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
{
	var state = ThreadContext<int?>.RetrieveState();

	if (state != null) Console.WriteLine($"An error occurred at state {state}");
};
Parallel.For(-100, 100, state =>
{
    using (new ThreadContext<int?>(state))
    {

	if (state == 42)
	{
	    throw new ArgumentException("Some error with state #42");
	}
    }

}
);
Thread.Sleep(TimeSpan.FromSeconds(5));

Now to go try this on a real project …

Categories: Uncategorized

Simple #CSRF protection in PHP

CSRF of Cross Site Request Forgery is like a layer of security that you can apply to your site that protects adequately against simple attacks on your website. It’s weak security against bot attacks, but when combined with a properly configured CDN, it does help a little.

Think of it like a plastic padlock. It’s enough to stop a light fingered kid, but not enough to stop anyone who really wants to steal your stuff.

Anyway, here’s a simple CSRF script for PHP. It’s not standardised, so anyone who sees it, has to figure it out (or read this post).

First, on the Javascript side, add the code;

  var _0x1933=["","\x6A\x6F\x69\x6E","\x6D\x61\x74\x63\x68","\x75\x73\x65\x72\x41\x67\x65\x6E\x74"];
  var csrf = navigator[_0x1933[3]][_0x1933[2]](/\d+/g)[_0x1933[1]](_0x1933[0]);

Post the CSRF along with your AJAX request, and then on the PHP side add the check;

  $csrf = $_GET["csrf"];
  $ua = $_SERVER['HTTP_USER_AGENT'];
  preg_match_all('!\d!', $ua, $matches);
  $csrfCheck = implode($matches[0]);
  if ($csrf == "" || $ua == "" || $csrfCheck != $csrf) die('csrf mismatch');

What does it do? – well it’s rather cryptic on the JS side, but on the PHP side, you can see that it is just the numerical part of the User Agent, which can be read by both client and server without any modification.

Again, If I did not have to restate this again. This is weak protection, but it may frustrate a would be attacker just enough to make him move along to the next victim, and leave you alone.

Categories: Uncategorized

Using #ARP to determine other devices on your users network.

ARP is a low level protocol, that is used to provide mapping between IP addresses and MAC (Hardware) addresses. Using a command such as “Arp -a” on Windows will determine what devices are on the network.

From the MAC address, it it possible to determine the manufacturer of the Device, such as in this case, 3C-15-C2-* is Apple. So this could be a mac, or an iPhone, or an apple TV.

The interesting thing is that the Arp table is available on Android without Rooting, by reading the file

/proc/net/arp

This means that any android app, could build up a picture of it’s users home devices, once connected to the home WIFI.

This means, that an advertiser could tell what type of printer you have, to advertise the right brand of Ink.

If your phone connects to multiple networks, it could build up a picture of your Office network. How many computers are at your office? – Is it a design studio with 50 apple macs ?

iOS has the ARP cache locked down to developers, and in my mind, rightly so.

Categories: Uncategorized

Unspecified error when connecting to a Network Share on Windows 10 #Emtec

There is probably a million fixes for this online, but perhaps this may be one of the more obscure fixes. I got a new network hard drive, from Emtec, which would connect to every other device in the house (mac, old PC, Android TV, Apple TV) but not my main Windows PC. So why?

Not a very helpful error message, when I simply tried to connect to \\emtec, since I just got a “Unspecified error”. I could ping the device, and even the path \\emtec\data worked, but this didn’t grant write access.

So when I tried \\emtec\WiFiDisk1_Volume1 it told me that it was using a deprecated version of SMB, SMB 1 instead of SMB 2. Thankfully, this was at last a meaningful error message, so I could use “Add Windows Features” to add SMB 1 support to my PC, and it finally worked.

A lesson for developers … give descriptive error messages. Something may seem super-obvious to you, but if you just swallow the error, then you give your end users nothing to go on.

I can’t say if the problem is with Emtec, using an old version of SMB, or with Windows for not describing the error properly. But the easier fix would be at the Windows level.

Categories: Uncategorized

Evaluate #Javascript in the cloud with #AWS #Lambda

TL;DR;

https://rapidapi.com/dananos/api/evaluate-javascript

Evaluating Javascript on the server side is a bit of an unusual ask, but perhaps you have an application that you’d like to be highly user-configurable, like you want to support fields that are supplied as complex mathematical formulae, or with complex if/else conditions.

Now, this opens a Pandora’s box of problems. What happens if someone writes malicious or simply bad code that could potentially damage or expose private data on your server, in which case, it’s good to run this in an isolated environment like Lambda (Running under a least-privilege IAM Role)

So, I first create a super simple lambda function as follows

exports.handler = async (event) => {
     const response = {
         statusCode: 200,
         body: JSON.stringify(eval(event.body)),
     };
     return response;
 };

And then create an API gateway as a Trigger, which means that I can now evaluate Javascript on the server side, using a CURL command as follows;

curl -X POST "https://xxxxxx.execute-api.eu-west-1.amazonaws.com/eval" -d "1+5" -H "Content-Type: application/json"

Where xxxx is dynamically assigned during the API gateway setup, and eval was the name of my Lambda function

The result of “1+5” is returned as “6” in the response.

Now, be aware, that the inner workings of your lambda can be exposed by executing Javascript like “process.env”, but as long as the Lambda itself has little permissions, then the damage it can do is limited also. Also, the running time and memory limits are capped, so it is unlikely to cost much.

Categories: Uncategorized

CRUD with #AWS #DynamoDB in .NET Core

One of the true benefits of DynamoDB is that it’s great for mini-projects, where you have to run on virtually zero budget. It doesn’t charge per-hour like the amazon RDS options, or Document DB options. It charges per storage >25GB and per million requests.

So, I set up a DynamoDB via the UI, and named it “test”. It’s much better if you name this something more meaningful, but I was just messing. I added a primary key of ID which is a number.

Then, as you create a new .NET Core project, you’ll need a Nuget package as follows;

Install-Package AWSSDK.DynamoDBv2

So with any Database, the first thing is to connect to it, which you’ll need to set up your IAM credentials, and then write some code like;

var credentials = new BasicAWSCredentials(AWS_USER, AWS_KEY);
 var client = new AmazonDynamoDBClient(credentials, RegionEndpoint.EUWest1);
 var tableResponse = client.ListTablesAsync().Result;
 var context = new DynamoDBContext(client);

I’ve written everything synchronously here, not best design, but it makes it easy to follow the flow. The ListTablesAsync is optional, but helps verify that it’s working.

The Object I defined, named “test” is as follows;

class test
 {
     public int id { get; set; }
     public string animal { get; set; }
 }

CREATE

context.SaveAsync(new test {id = 4, animal = "Frog"}).Wait();

READ

var conditions = new List
 {
     new ScanCondition("id", ScanOperator.Equal, 4)
 };
 var allDocs = context.ScanAsync(conditions).GetRemainingAsync().Result;
 allDocs.ForEach(t => Console.WriteLine(t.animal));

UPDATE

context.SaveAsync(new test { id = 4, animal = "Lion" }).Wait();

DELETE

context.DeleteAsync(new test {id = 4, animal = "Lion"}).Wait();

Categories: Uncategorized

Send #APNS #Push notifications using #RapidAPI

TLDR; Go Here: https://rapidapi.com/dananos/api/simplified-apns-apple-push-notification-service

This is a simple tutorial to send an APNS (Apple Push Notification Service), to production using C# (RestSharp) and Rapid API. It uses HTTP/2, so will continue to work after the March 31st deadline.

To do this, you will need:

  • The P12 production certificate, and it’s password
  • An APNS token of an iOS app, that has subscribed to push notifications.
  • A subscription Key to this RapidAPI service.

Create a new project in Visual Studio, and add your p12 certificate to the project. Change it’s build properties to “copy always”.

From the Package management panel, Install Rest Sharp via Nuget with “Install-Package RestSharp”

Add the following code;

public static string Push(string destination, string message, string certFile, string certPassword, string rapidApiKey)
        {
            var certificate = File.ReadAllBytes(certFile);
            var client = new RestClient("https://rapidapi.p.rapidapi.com/Prod");
            var request = new RestRequest(Method.POST);
            request.AddHeader("x-rapidapi-key", rapidApiKey);
            request.AddHeader("x-rapidapi-host", "simplified-apns-apple-push-notification-service.p.rapidapi.com");
            request.AddJsonBody(new
            {
                destination,
                message,
                certificate,
                certPassword
            });
            var response = client.Execute(request);
            return response.Content;
        }

The calling code will be up to you, but it will be in the form;

        var destination = "8ec378164725d019fce12c420cea7......";
        var message = "hello, this is rapidAPI!";
        var certPassword = "XXXXX";
        var certFile = "XXXXX.p12";
        var rapidApiKey = "PUB#XXXXXXXX";
        var pushResponse = Push(destination, message, certFile, certPassword, rapidApiKey);
        Console.WriteLine(pushResponse);
Categories: Uncategorized

Deleting a large number of records from a database without locking it (for ages) #SQL

If you have a large database, with millions of rows, and you need to run an batch operation on it, like deleting lots of old records, then you’ll quickly find that the operation often will lock the table, and prevent users get at their data – as well as bloating the transaction log table.

So, the trick is to break it down into manageable chunks. Let’s say the operation I want to run is this;

delete from log where success=0

If the “log” table has millions of rows, then this will undoubtedly lock the log table, as the statement is running. Preventing new logs from being written.

If I then write something like:

delete top (100) from log where success=0

This completes in a jiffy, and deletes 100 rows from the log table. The actual 100 rows that get deleted are beyond your control, it’s just the first 100 that it finds. But that isn’t really a problem.

So, let’s write this as a loop as follows;

declare @FirstPass Bit
select @FirstPass = 1;
while @@ROWCOUNT = 100 or @FirstPass = 1
begin
set @FirstPass = 0;
delete top (100) from log where success=0
end

This just means that it will run this command over and over again until it no longer has rows that it can delete.

Now, to improve upon this a bit more, I’m going to add the lines;

  WAITFOR DELAY  '00:00:01';  
  RAISERROR('ok',0,1) WITH NOWAIT;

Which will put a 1 second delay in the loop, to make sure we’re not hogging all the Database’s processing power, and the “RaiseError” just flushes the output to the messages window, so we can see that everything is running smoothly.

Categories: Uncategorized