Comparing #AWS S3 Upload via CLI to #Azure Blob upload via CLI.

The AWS Command Line Interface (CLI) is a unified tool to manage AWS services. With just one tool to download and configure, you can control multiple AWS services from the command line and automate them through scripts.

The Azure Command-Line Interface (CLI) is a set of commands used to create and manage Azure resources. It is available on Windows, macOS, and Linux.

Both the AWS CLI and Azure CLI allow you to manage cloud resources from the command line and automate them through scripts. However, there are some key differences to be aware of:

  • Services: AWS offers a wider range of services, but Azure has some services that AWS does not, such as Azure Arc for managing hybrid environments.
  • Language support: The AWS CLI supports multiple programming languages, including Python, Node.js, and C#. The Azure CLI is written in Node.js and is designed to be used with the Azure Resource Manager.
  • Installation and setup: The AWS CLI is installed using a package manager or by downloading a standalone binary. The Azure CLI is installed using a package manager or by downloading the installer.

Overall, both the AWS CLI and Azure CLI are powerful tools that allow you to manage and automate your cloud resources. It really comes down to which cloud platform you are using and which services you need to manage.

Both the AWS and Azure CLI make it easy to upload files, but lets take a look at the difference

To login you type AWS Configure for AWS or AZ login for azure. the AZ login opens a browser so you can provide your credentials, whereas AWS Configure prompts for a IAM user key and secret. In my opinion, AZ makes this process easier for a first time user, but AWS tends to guide you towards the principle of least access better, so more secure for the novice user.

AWS arranges it’s S3 storage into buckets, and optionally folders within the buckets. Azure has storage accounts, and you must have at least one container within the storage account.

To upload a file on Azure it’s

az storage blob upload -f -c database-backups –account-name backupaccount

And the same on AWS is:

aws s3 cp s3://backupaccount/

Some complexities I had found with both Azure and AWS, is if you have multiple accounts, or subscriptions. In Azure, you have to select your subscription as follows;

az account set –subscription “PayAsYouGo”

Wheras, you can have multiple profiles in AWS, and that is selected using

aws s3 cp s3://backupaccount/ –profile AWS

Categories: Uncategorized

U2FsdGVkX1 and #AES – Why you should never use #CryptoJS

If you’re googling the term “U2FsdGVkX1” then you’re looking at some Base64 encoded AES encrypted text? How do I know that, becuase it decodes to “Salted__” – It’s the default value of the first few bytes in a block cypher.

AES (Advanced Encryption Standard) is a symmetric encryption algorithm that is widely used to secure data transmitted over the internet and to store data in encrypted form. One common way to use AES is to encrypt a message with a secret key, which can then be decrypted using the same key.

The “Salted__” prefix that sometimes appears at the beginning of AES-encrypted text is related to a technique called salting, which is used to make it more difficult to attack the encrypted data.

When a message is salted, a random sequence of bits (called a salt) is generated and appended to the message before it is encrypted. The salt is then stored along with the encrypted message, so that it can be used to reconstruct the original message when it is decrypted.

The purpose of salting is to add an extra layer of security to the encryption process by making it more difficult for an attacker to use precomputed tables or other techniques to try to break the encryption. For example, if an attacker knows that a particular message is encrypted with AES, they may be able to use a precomputed table of common words and phrases to try to guess the key and decrypt the message. However, if the message has been salted, the attacker will not be able to use the same precomputed table, because the salt will have changed the encrypted message in a way that is not predictable.

The “Salted__” prefix is added to the beginning of the encrypted message to indicate that the message has been salted, and to provide a place to store the salt. The prefix is followed by the salt itself, which is typically 8 bytes (64 bits) long. The rest of the encrypted message follows the salt.

In summary, the “Salted__” prefix is added to AES-encrypted text to indicate that the message has been salted, and to store the salt used in the salting process. Salting is used to add an extra layer of security to the encryption process by making it more difficult for an attacker to use precomputed tables or other techniques to try to break the encryption.

Beyond the theory, the text U2FsdGVkX1 can indicate the cypher mechanism used, which points an attacker towards AES. AES by itelf is very secure, but implementations of it can be very weak. I would immediately point the finger at CryptoJS. If you are using this in your webpage, you have just added a speedbump to a would-be attacker, nothing more than a paperclip holding your door closed. AES is secure, but it’s symetric, so therefore the client needs to know the key in order to encrypt the data. If you share your key on the page, and your browser can read it, then so can an attacker.

In fact, CryptoJS is such a bad idea, it gives a false sense of security. Is a padlock secure, yes. Is a Padlock with the key left in it still secure? Absolutely not.

Categories: Uncategorized

Poland Vehicle License plate search now available via #API

Today, we have just launched our Vehicle License plate lookup API for poland, available here:

The license plate lookup API for Poland is a tool that enables users to retrieve vehicle information from the Polish vehicle registry by providing the license plate number. This API allows users to access accurate and up-to-date information about vehicles registered in Poland, including details such as the make and model of the vehicle, the year it was manufactured, and the vehicle identification number (VIN).

The license plate lookup API for Poland is easy to use and can be integrated into a wide variety of applications. For example, it can be used by insurance companies to verify the details of a vehicle, or by car rental companies to ensure that the vehicles they are renting out are properly registered. Additionally, the API can be used by law enforcement agencies to quickly and easily obtain information about vehicles that may be involved in a crime.

Overall, the license plate lookup API for Poland is a valuable tool for anyone who needs to access vehicle information in Poland. It is fast, accurate, and easy to use, and can help users save time and improve the accuracy of their vehicle-related operations.

Poland support

Car registration plates in Poland use the /CheckPoland endpoint and return the following information:

  • Make / Model
  • Year
  • VIN
  • Engine Size
  • Power
  • Fuel
  • Weight
  • Region
  • Representative image

Sample Registration Number: 


Sample Json:

  "Description": "SAAB 9-3",
  "RegistrationDate": "2002-06-04",
  "RegistrationYear": 2002,
  "CarMake": {
    "CurrentTextValue": "SAAB"
  "CarModel": {
    "CurrentTextValue": "9-3"
  "MakeDescription": {
    "CurrentTextValue": "SAAB"
  "ModelDescription": {
    "CurrentTextValue": "9-3"
  "VehicleIdentificationNumber": "YS3DD55C622039715",
  "EngineSize": 1985,
  "Power": 110,
  "FuelType": "Petrol",
  "IsPlugIn": "False",
  "SteeringWheelSide": "L",
  "ManufacturingYear": 2002,
  "Mileage": 175102,
  "Weight": "1.9",
  "Region": "Łódź",
  "ImageUrl": ""
Categories: Uncategorized

Running a scheduled task on #AWS – A workaround for the 15 minute #Lambda limit

Let’s start with a bit of context. You want to run a process every day that could last 30 minutes, perhaps you’re importing data from an external source to a database. You can’t use Lambda, because the limit is 15 minutes, and it’s wasteful to use an EC2 instance because for 99% of the time the server will sit idle.

So, containers to the rescue. This is where you firstly write your code, and containerize it. Make sure it runs locally, as expected. Then you push the docker image to ECR. I followed most of the steps in this blog post:

The difference being, in my case, the application had a finite run time – i.e. do a task, then exit (not a web server).

Which means, that after I created my task definition, I then went to the Scheduled Task tab as shown below;

Where I could create a scheduled task that I can set to run every day, or minute, or whatever you need (the minium is 1 minute).

The container will run until it has finished it’s workload, so there is no 15 minute limit, like on AWS lambda.

Categories: Uncategorized

Format prices correctly in #MSSQL using currencies in #ISO4127 format.

If you want to specify a price including a currency, you can always write EUR 1,234 or USD 1,234, but it’s more concise to write $1,234 or €1,234, and users expect that format. You can always handle this at application layer, but here’s how to do it at Database layer.

Here, I’ve created a table of the currencies I needed, – it’s not complete, and I hope that someone can post a link to a complete table.

create table CurrencyLocales
 id int identity(1,1),
 currency varchar(3),
 locale varchar(5)

insert into CurrencyLocales (currency,locale) values ('AUD','en-AU')
insert into CurrencyLocales (currency,locale) values ('BRL','pt-BR')
insert into CurrencyLocales (currency,locale) values ('CAD','en-CA')
insert into CurrencyLocales (currency,locale) values ('CZK','cs-CZ')
insert into CurrencyLocales (currency,locale) values ('DKK','da-DK')
insert into CurrencyLocales (currency,locale) values ('EUR','en-IE')
insert into CurrencyLocales (currency,locale) values ('GBP','en-GB')
insert into CurrencyLocales (currency,locale) values ('HUF','hu-HU')
insert into CurrencyLocales (currency,locale) values ('MXN','es-MX')
insert into CurrencyLocales (currency,locale) values ('MYR','en-MY')
insert into CurrencyLocales (currency,locale) values ('NOK','nb-NO')
insert into CurrencyLocales (currency,locale) values ('NZD','en-NZ')
insert into CurrencyLocales (currency,locale) values ('RUB','ru-RU')
insert into CurrencyLocales (currency,locale) values ('SEK','sv-SE')
insert into CurrencyLocales (currency,locale) values ('SGD','en-SG')
insert into CurrencyLocales (currency,locale) values ('USD','en-US')

create index idxCurrency on CurrencyLocales(currency)

-- example
select *, FORMAT(1234, 'C', locale) as formattedPrice  from CurrencyLocales
4CZKcs-CZ1 234,00 Kč
5DKKda-DK1.234,00 kr.
8HUFhu-HU1 234,00 Ft
11NOKnb-NOkr 1 234,00
13RUBru-RU1 234,00 ₽
14SEKsv-SE1.234,00 kr
Categories: Uncategorized

Runing Hosted CapMonster Locally in C#

If you use CapMonster Cloud, then you may find that the per-request pricing does add up over high volumes, if you have spare computing power, then you can run CapMonster Hosted on your own server., or if you are running a batch-process on your own local PC, then this could be a big cost saver.

It’s not free, since you need to buy a license from CapMonster for the base sofware, I used the Lite version for $37, available here: – Then you also need the sitekey add on, which is $10 per month, available here; – But this now allows you solve 100,000 captchas per day, instead of the $0.6 * 100 = $60 per day cost of the equivalent on CapMonster Cloud at the same volume.

So, After downloading the required software, it will start a server on (port 80) by default that exposes the same API as – but obviously with a differnt endpoint (local vs remote).

The problem is that if you use the NuGet Package here; then you will notice that this does not offer the API endpoint to be configurable.

What I did was clone the repo from and then set then change the ApiBaseUrl specified in Endpoints.cs – or make it a public property, and modify it in your client code.

So, this could be a good cost saving tip, for heavy users of CapMonster.

Categories: Uncategorized

Using AWS CloudFront as a proxy

Typically, CloudFront is used to serve your own website, so that it can leverage AWS’s CDN, and various edge servers in many countries, so that data is not transferred accross the world with every HTTP request.

But, you can also use it as a proxy, by pointing CloudFront at someone else’s website. This means that when you visit the CloudFront URL, the request to the third party website will come from AWS rather than from your local machine.

It’s not as anonymous as a good proxy, since there are various headers that would undoubtedly expose you, based on the request made to HTTPBIN below;

  "args": {}, 
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Accept-Language": "en-US,en;q=0.9", 
    "Dnt": "1", 
    "Host": "", 
    "Sec-Ch-Ua": "\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"", 
    "Sec-Ch-Ua-Mobile": "?0", 
    "Sec-Ch-Ua-Platform": "\"Windows\"", 
    "Sec-Fetch-Dest": "document", 
    "Sec-Fetch-Mode": "navigate", 
    "Sec-Fetch-Site": "none", 
    "Sec-Fetch-User": "?1", 
    "Upgrade-Insecure-Requests": "1", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-636908d7-xxxxxxxx"
  "origin": "", 
  "url": ""

Here X-Amzn-Trace-Id could probably be tied to you.

Categories: Uncategorized

Extract Assemblies.blob / Assemblies.manifest from Xamarin APK

When unzipping a Xamarin-built APK, you may notice that in the \assemblies folder there are no longer a list of DLLS, but two files, Assemblies.blob and Assemblies.manifest, where the manifest contains a list of filenames, and their associated Hashes, and the blob file contains the compressed data. All this gives the APK a smaller footprint on device. (Even though the APK is zipped anyway, but I presume that someone has done the maths!)

To uncompress the Assemblies.blob file, you’ll need python installed on your machine – and clone the repo from

With this script, you can decompress the assemblies.blob / manifest using the syntax;

usage: [-h] [–blob BLOB] [–manifest MANIFEST]

After this, you have a load of Lz4 files. You pick the file you’re interested in, and then git clone the repo

Then using this script, you then run the command;

python [filename].lz4

Which gives you the DLL that you can import into dotnetpeek or ILSpy.

Categories: Uncategorized

Verify a #SouthAfrican #VAT number via an API

If your company deals with South African companies, and you need to verify the VAT number provided by them, to ensure it matches the same company, then here is an API that can do this automatically for you.

Firstly, register with RapidAPI, and go to this page once registered, you will get a RapidAPI key, which you will need to run the below code example;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;

var client = new RestClient("");

var request = new RestRequest
    Method = Method.Post
request.AddHeader("X-RapidAPI-Key", "**********");
request.AddHeader("X-RapidAPI-Host", "");
request.AddHeader("Content-Type", "application/json");
var body = JsonConvert.SerializeObject(new { vat = "4910202524" });
request.AddParameter("application/json", body, ParameterType.RequestBody);
var response = client.Execute(request);
var company = JObject.Parse(response.Content ?? "{}");
var resultTable = company["Table"] ?? new JObject();
var tradingName = resultTable["TRADING NAME"] + "";
var area = resultTable["AREA DESC"] + "";
Console.WriteLine($"{tradingName} is registered in {area}");

The code above is a console app for .NET Core in C#, and will require the following NuGet packages, which can be installed as follows;

Install-Package RestSharp 
Install-Package Newtonsoft.JSON
Categories: Uncategorized

#TLS client authentication sends target host as plaintext

TLDR; Github repo is here;

First and foremost, I am not highlighting a security flaw in TLS, I’m just pointing out a parameter that should never be “hijacked” for purposes of client identification, since it is sent in plaintext over an TLS (aka SSL) connection, and thus easily read by anyone who may be intercepting the connection.

This example is in C#, and at TCP level, a HTTPS connection needs to call “AuthenticateAsClient” before it can exchange content with the server. This step is where the client can provide to the server an X509 client certificate, to prove who the client is. Often the client does not provide an X509 certificate, and the server must use something else to authenticate the client.

The parameters to AuthenticateAsClient as the TargetHost, and an optional list of certificates. The TargetHost parameter is meant to indicate to the server which certificate to use, but it should never be used to pass any authentication credentials, like a user id – because, as the screenshot shows, the target host is passed in plaintext, and can be intercepted.

Here is my sample client;

client.Connect("", 500);
var s = client.GetStream();
var bMessage = Encoding.UTF8.GetBytes("HELLO WORLD");
var ssl = new SslStream(s);
ssl.AuthenticateAsClient("SOME SECRET INFORMATION", null, SslProtocols.Tls12, false);
ssl.Write(bMessage, 0, bMessage.Length);

Here, I am connecting to a local server on port 500, then using SSL (TLS) to connect to it. I authenticate as a client, passing something I shouldn’t in the Target Host.

On a seperate thread, I am listening for incomming data; and outputting it to screen, and it’s really obvious how the TargetHost appears in plain text. Note that the incomming stream is not decrypting the SSL, it is just printing it raw to the screen.

So, Once again, this isn’t anything to get worried about. By default, Http client libraries won’t expose this property, you need to be down at TCP level to change it, so you’re not likely to “accidentally” leak data this way. Generally if you are writing TCP level code, you’re heading in the wrong direction – but if you do think that this property could be a short-cut to client authentication – don’t do it!

Categories: Uncategorized
%d bloggers like this: