0

We have a licensing system where our software, a commercial product we sell to people, contacts our licensing server when starting to get an OK to run.

It contacts our licensing URL and passes up an XML file signed with our public key. We verify the signing with our private key, build an XML file to send back, and sign it with our private key. The app then uses the public key to verify that it cam from us and acts on the response.

We're looking at allowing the URL and public key to be overridden with values set in the app's config. Overriding the URL would be used for letting customers test our new license server. Overriding the public key is to handle the case where our private key becomes known and we have to change it.

However, it strikes me that someone could override both to have it point to their server using their public key and they've now given everyone the ability to bypass our check.

Is this a hole in the system? And if so, is it a bad idea to allow either to be overridden? If we can safely override either one, but just one, I think the public key is the one to allow setting in the config file.

Or is there another way to go about all this?

2
  • Does the XML file you return to the client have any limitations on when it can be used? From your description, the risk would be a replay attack - end user could copy your unsigned XML, sign it with their own key, and configure their own server as the licence server, always responding with the same XML?
    – Matthew
    Commented Oct 24, 2018 at 11:41
  • @Matthew The XML cannot be reused. When a request is sent to the server, it includes a nonce (guid). That same guid must come back in the XML signed by our server. Commented Oct 24, 2018 at 13:50

2 Answers 2

3

Short answer: Yes, if someone builds their own license server and override the public key, it sounds like they should be able to use your software without paying for a license. They don't even need the URL setting for that.

The somewhat longer answer:

If I understand correctly, the client validates the signature against a public key which is shipped in the software (and subsequently allowed to be overridden). It sounds like the software has some isAnswerSignatureCorrect() method, which could be easily altered to always return true. This is what the early days of software cracking was all about.

One can also run a local webserver, redirect the license server host to localhost and crack the software, you wouldn't even need to override the URL in the config.

What I'm trying to say here: if your audience is willing to go so far as building their own license server that would return the correct XML structure to crack their license, then the current method you are using is not going to hold up very long.

Overriding the public key is to handle the case where our private key becomes known and we have to change it.

If you fear of that happening, you should think about addressing that first. Store your key in a HSM, have it sign the response. If a 'real' HSM is too expensive, take a look at Yubico products.

If you fear losing access to the private key, consider generating a second key and ship the public key of both.

Overriding the URL would be used for letting customers test our new license server.

Consider shipping the software with a hardcoded list of allowed servers. Or add a route/header/urlparam to the request of the current license server host to allow the request to be handled by a new system without having to change hosts.

You could use public key pinning to make sure the application only communicates with a server that serves a certificate owned by your organisation.

1

Yes, it is a hole. I would suggest either adding both licences into the application and choose the proper one depending on the URL or using a CA system, where you put a certificate of your own CA into the application and then sign certificates for both server. This also allows revocation and generating new keys + certificates without changing the configs using the standard-ish PKI system.

Very Simplistic Example: You put a public key of your CA (the private key should ideally be on a hardware token or at least air-gaped coputer). You generate a key-pair for each server and sign the public key with the CA private key. Then include the signed public key when sending back the XML. The app then verifies first that the public key is properly signed using the hard-coded CA public key, then verifies the XML using the included public key.

Of course, using full X.509 certificates would be even better, though a bit more complicated.

3
  • There's a limit to how much effort this is worth, because they can go into the code (Java & .net versions) and find where the license check is, and just set that to return OK with no communication with our server. So anything we do that requires more effort than cracking the code, we've just made them go crack the code. This is more we're keeping the honest person honest. Sort of like the lock on the front door of your house - easily opened by a trained locksmith, but stops most everyone else. Commented Oct 24, 2018 at 13:54
  • @DavidThielen that is why I only suggested hard-coding a public key into your app and deal with single level of signing. But having everything in a config file simplifies this way beyond messing with machine code IMO. I only included the revocation considerations because you mentioned it. Commented Oct 24, 2018 at 18:32
  • Yeah - what you listed is a good listing of getting more and more serious about it. I just wish there was a way to not lot the code run if it's not signed by us. But it's on their machine so they have final control. Commented Oct 24, 2018 at 19:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .