Contest: find the secret value in a Business Central app

23 Jan

This is the first blog post about shipping a secret value in a Business Central app. I have prepared an app file that contains a secret value that will be stored into Isolated Storage. But I’m not 100% if this method is secure enough, and that’s why I need your help. Please, download the app file and find the secret value. If you succeed, then I need to harden it. If nobody can find the value then that either means nobody really tried or it is secure enough. Let’s see what our community can do!

Ok, let’s crack that thing, what do you want me to do?

Glad you are eager to find that secret value! You can download the app file here.

Install the app in a Business Central cloud sandbox. After installation, search for the page ‘Test Secret Value’ and enter the value that you think is shipped with the app and click on Next. The page will tell you the result. 😊

This value is not correct…

But when you enter the correct value, then you get this page.

Only for Business Central cloud

The app that I have created can only be installed in a cloud sandbox. The reason for that is that I have used the 70-million object range. If I had created the app in the 50.000 – 99.999 range, then cracking the secret would be very simple. Please let me know in the comments below if you need an app for a local docker container and I’m happy to provide one.

What’s next?

I really hope some people will try to crack this. Please post your results in the comments. Or contact me directly if you think you’ve got the secret but don’t want to reveal it. In the meantime, I’ll be writing another blog post that explains the approach in more detail.

Can you share the source code?

Well, you can extract the source code from the app file, can’t you? But to make it easy for you, I’ve published all source code on GitHub. Feel free to explore the code, I guess you will figure at quickly what I’ve done. Anyway, that’s for another blog post that will follow shortly. For now, I’m just sharing the app without further explanation because that comes closest to a published app that you can download from AppSource.

Good luck with cracking the secret! I’m really curious to see your results!

8 thoughts on “Contest: find the secret value in a Business Central app

  1. Hello! I tried to install the app on a cloud sandbox (not in a docker container) using the Extension Management page and I get this error when publishing:

    Package validation failed due to the following error(s): (1,15): error PTE0001: Page ‘RandomTextAJK’ has an ID of [70455526]. It must be between within the range ‘[50000..99999]’.
    (1,19): error PTE0001: Codeunit ‘SecretValueAJK’ has an ID of [70455526]. It must be between within the range ‘[50000..99999]’.
    (1,19): error PTE0001: Codeunit ‘SecretValueInstallAJK’ has an ID of [70455525]. It must be between within the range ‘[50000..99999]’.
    (1,19): error PTE0001: Codeunit ‘SecretValueUpgradeAJK’ has an ID of [70455528]. It must be between within the range ‘[50000..99999]’.
    (1,19): error PTE0001: Codeunit ‘RandomTextMgtAJK’ has an ID of [70455529]. It must be between within the range ‘[50000..99999]’.
    (1,19): error PTE0001: Codeunit ‘SecretValueMgtAJK’ has an ID of [70455527]. It must be between within the range ‘[50000..99999]’.
    (1,16): error PTE0001: Record ‘SecretValueAJK’ has an ID of [70455525]. It must be between within the range ‘[50000..99999]’.
    (1,15): error PTE0001: Page ‘TestSecretValueAJK’ has an ID of [70455525]. It must be between within the range ‘[50000

    Have I done some wrong?

    • No, this was my fault. I was so super focused on finishing the app, that I forgot to test the obvious. I was able to deploy to an online sandbox from VS Code, but I didn’t check the manual upload in the management extension page. Strange that you can only deploy from VS Code, but that’s another story.

      I’ve updated the app file, it is now using the customization range 50000.99999 again. This time I’ve tested the manual upload. 😉

      Thanks for informing me!

      • It works now!
        So I tried… just to share with everyone: my trial consisted to install an app before the Secret App. This app subscribes to global insert/delete database record to catch the record ref of table Secret Value and copy the content to another table.

        I do not know if I have done something wrong but I do not, I discovered that:
        – loading a navx file does not raise triggers
        – calling deleteall on an internal table during install process does not raise global triggers either

        For the first case, ok I can understand the reasons.
        For this second case, I do not really understand why: are global triggers skipped for internal tables? or during install?

        So the conclusion right now for me: the secret remains a secret 🙂

        To break the key, can we use the fact we have access the navx file? or if we consider the app should be published from the app source, we do not have access to this file.

        • Thanks for sharing! I agree, it’s strange that deleteall doesn’t trigger. Need to figure out why that is.
          So far, two people found the code by directly tweaking the navxdata file. In two different ways, actually. Which was exactly what I was afraid for, but wanted to get proof.

          Now working on a way to harden it. Will update soon!

  2. Hello guys 🙂 im new to this whole monetarization / licensing in BC.
    I tried to find valuable information about this topic, but in general i only find information about the isolated storage and how to use it.

    If i set my app to “showMyCode”: false i had the impression you can’t download any source code on app source? so if i store my secret into the isolated storage via code it should be safe?

    If i’m doing an on premise installation i could just create a runtimepackage, which would not include any source code in my application, so my code would also be safe?

    At which point do i miss something?

    • You are right, the secret you ship with the app would not be visible to anyone else. Well, except for those people who have access to the app file internally and at Microsoft.

      But if the secret gets compromised, then you need to deploy a new version of your app. That’s not a good scenario, I would say. Secrets are data, they don’t belong in source code. That’s a principle in my opinion.

      • Now I see your point! I can agree that those Secrets are most of the time data.

        In my case I want to handle a license model in a smart way and tried to figure out a way, where I can guarantee the license system not getting “compromised”. I couldn’t find in deep tutorials about a fully fleshed out license model, but I found many guidelines for using the isolated storage (like yours).

        I integrated different function for all my needs. My problem right now is, how to get the needed license data into the storage.

        Should I simply store it in the Source code? Should I implement a Web service, to request the license data and store it? Or should I use a file like yours and import the data.

        The other thing I can’t figure out is, how do I implement a trial period for feature testing? How can I secure my app against reinstalling? (resetting the period)

        Im sorry for asking so many questions, but the topic isn’t well documented…

  3. I feel your pain, many other partners are in the same position.

    To start with the last question, uninstalling and then reinstalling doesn’t reset the data. Unless it’s on-premise and somebody chooses to clean all data after uninstalling it. But then they also destroy all data of the app. So that’s not your problem.

    The question about getting the license data is more difficult to answer. It depends on how you want to receive payments, how many customers you expect, etc. But I would never store it in source code. So you need an external service, or a manual process for customers to insert license codes (like many other programs do).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.