Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOS! Levure.livecodescript behavior stack does not get encrypted when building standalone, an unacceptablly high security risk! #186

Open
Tonaras opened this issue Aug 25, 2022 · 4 comments

Comments

@Tonaras
Copy link

Tonaras commented Aug 25, 2022

Hi Trevor,
This is ultra urgent! For like 5 months, I've been porting all my LiveCode projects to Levure. I'm about to release a major commercial app on which I was working since almost 2 years under insane pressure. But now, I cannot find a way to get the Levure.livecodescript encrypted along with the other stacks, library stacks and front/back script stacks. All others encrypt fine! I know that script-only stacks cannot be encrypted per se, but I was certain that the functionality of the framework's behavior script could be somehow transferred/built into the standalone stack to get encrypted along with it.

I'm hacking since 10 days to find a way but everything I've tried so far makes the entire thing just fall appart when I try to place the Levure.livecodescript handlers somewhere inside the standalone stack. I'm totally desperate and exhausted and shocked because this poses immense security risks which are totally unacceptable for a commercial application. Just with the injection of a few commands into the Levure.livecodescript file, ANYONE can take control of the app in a snap!!

I'm sincerely BEGGING you to give me a helping hand asap. Of course I'm willing to compensate you for any inconveniences and time!
PLEASE don't let me down on this. PLEASE!!!
Regards, Anton

@trevordevore
Copy link
Owner

Hi Anton. Adding encryption for the levure stack is definitely doable.

As background, password protecting stacks in the framework is intended to protect the business logic of the application so that the scripts cannot be read in an editor. Can you tell me more about the specific vector you are concerned with?

Is it that your customers who have admin access to their computer will modify the levure framework stack? Or are you concerned that a hacker will gain elevated permissions on a computer and then modify the framework to extract information out of it somehow?

As for password protecting the stack, passwords are assigned during the packaging process. That occurs in levure/packager/packager.livecodescript#packagerPackageApplication. On line 182 (in the version I'm looking at) is the comment # Copy over framework file. Mobile standalone builder won't copy it. Desktop will. The code that follows copies the framework stack into the output folder.

Something like this should probably work. You can update your copy of the packager script with the code that appears after the "NEW CODE FOLLOWS" comment, save the changes, and then launch the LiveCode IDE and try packaging your app.

        # Copy over framework file. Mobile standalone builder won't copy it. Desktop will.
        put levureFrameworkFilename() into tSourceStackFilename
        put tCopyFilesTempFolder & "/" & the last item of tSourceStackFilename into tTargetStackFilename
        _fileCopyFile tSourceStackFilename, tTargetStackFilename
        put _errorMsg("copying file [" & tSourceStackFilename & "] to [" & tTargetStackFilename & "]", the result) into tError

        ##
        ## NEW CODE FOLLOWS
        ##

        if tError is empty and sPassword is not empty then
          # When the copied framework file is loaded into memory it will conflict
          # with the framework stack already in memory. Lock messages so we dont' see
          # any alerts about stack name conflicts.
          lock messages

          # remove from memory
          delete stack tSourceStackFilename

          set the scriptonly of stack tTargetStackFilename to false
          _setPassword tTargetStackFilename, sPassword
          save stack tTargetStackFilename with newest format
          put _errorMsg("saving framework stack", the result) into tError

          delete stack tTargetStackFilename
          unlock messages

          if tError is empty then
            # Load back into memory
            start using stack tSourceStackFilename
            levureLoadAppConfig pBuildProfile
            put the result into tError
          end if
        end if

@Tonaras
Copy link
Author

Tonaras commented Aug 26, 2022

Hi Trevor. I don't know how to thank you for your immediate reply and great help. You've definitely saved me from a nervous breakdown.

I've added the script you posted and it all works like a charm! Before your reply I was already hacking in that exact section of that packager handler but following the wrong strategy. I wasn't aware that a SOS stack that is referenced as a behavior could be saved as a "normal" stack and thus be encrypted without causing hickups in the message path.

For others who read this and need to have the "levure.livecodescript" file encryted in their standalones, I want to mention an equally working and tested alternative: If you don't want to fiddle with 'hacking' the original handlers of the packager you can just do what this scriplet does by hand. Just build your Levure App as usual. After the Standalone files are built you can open the "levure.livecodescript" in the LC IDE, set its scriptonly property to false, set the same password for it as in your Levure App and save the stack.

So, EVERYTHING in Levure works phantasticly stable and smooth and I have only two major remaining issues with it:

  1. How can I change the file extensions of my stacks in the built App from ".livecode" and ".livecodescript" to something else without everything falling appart? It would be a phantastic upgrade if file extensions for packaged stacks could be declared in the yaml file!!
  2. The upcoming script compiler will be amazing and I'm worried that the Levure framework & packager will not support it. Of course it's still too early to predict anything and we barely even know how that thing will work and look like. But it's an important issue for ensuring the future of this extraordinary framework.

Finally, to answer your question about security, Yes, both possibilities you mentioned are giving me headaches. IMHO, anyone who can hack their way into the source code of a component that is executed automatically at runtime, be it benevolent, be it with very bad intentions, can cause immense damage. The first to get the blame would be the publisher of the app and I certainly don't want to be in the frontline here no matter how miniscule the chances of such a hack of my products may be. There are certainly other means to hack and hijack even compiled code, no matter what. But making it THAT easy to inject code, legalese asside, I couldn't sleep well at night anymore from an ethical standpoint. Do you agree?

@trevordevore
Copy link
Owner

You're welcome @Tonaras. To answer your questions:

How can I change the file extensions of my stacks in the built App from ".livecode" and ".livecodescript" to something else without everything falling appart? It would be a phantastic upgrade if file extensions for packaged stacks could be declared in the yaml file!!

Right now you would need to rename all of your files on disk. The Levure packager doesn't support this.

The upcoming script compiler will be amazing and I'm worried that the Levure framework & packager will not support it. Of course it's still too early to predict anything and we barely even know how that thing will work and look like. But it's an important issue for ensuring the future of this extraordinary framework.

What is the concern? The framework relies entirely on the LiveCode environment. I haven't read up on the script compiler you are referring to, however. Is there something about it that you think will break how Levure works?

Finally, to answer your question about security, Yes, both possibilities you mentioned are giving me headaches. IMHO, anyone who can hack their way into the source code of a component that is executed automatically at runtime, be it benevolent, be it with very bad intentions, can cause immense damage. The first to get the blame would be the publisher of the app and I certainly don't want to be in the frontline here no matter how miniscule the chances of such a hack of my products may be. There are certainly other means to hack and hijack even compiled code, no matter what. But making it THAT easy to inject code, legalese asside, I couldn't sleep well at night anymore from an ethical standpoint. Do you agree?

If that is the case then just password protecting the levure.livecodescript stack won't offer the protection you want. Any stack file on disk can be replaced IF a person has write permissions to the application files. Try it with any of the stacks in your app. Password protecting them doesn't change this.

There may be a couple of solutions to this problem if it is important enough to you to solve.

  1. Add a feature to the Levure packager which creates an array of hashes for every file included in the packaged application and store it as part of the standalone file. When the application launches code within the standalone can compare the hash of the files on disk with the hash that was stored at packaging time to make sure they are the same.
  2. Devise a way to add all files in the application to the standalone so there is only one file that is ever distributed.
  3. On macOS it looks like it may be possible to use the the data in MyApp.ap/Contents/_CodeSignature/CodeResources to verify the signatures of files on disk. I haven't researched this but I did find the following two articles which may be useful:
    https://developer.apple.com/forums/thread/129657
    https://developer.apple.com/forums/thread/129657
  4. If [3] is viable then you could see if it is possible to do something similar on Windows. Though on Windows I'm only familiar with signing the executables.

@Tonaras
Copy link
Author

Tonaras commented Aug 30, 2022

Thanks for the follow up @trevordevore.

Right now you would need to rename all of your files on disk. The Levure packager doesn't support this.

I'm affraid that it's not enough to simply rename the files. After doing so, the built Levure App fails to locate and load the stack files with changed extensions. So, file references to the stacks seem to be "hard coded" within the depths of framework to look for ".livecode" and ".livecodescript" extensions explicitly. I'm not sure if I can figure out where all this referencing is taking place and addapt the code without causing major hickups. Since you are the "father" of this great framework and your know it inside out, I'd appreciate any hint to get this done!

What is the concern? The framework relies entirely on the LiveCode environment. I haven't read up on the script compiler you are referring to, however. Is there something about it that you think will break how Levure works?

No, I'm sure Levure won't break. But I guess it will need to be updated to support the new functionality of the upcoming LiveCode environment. From what I've heard so far, the scipt compiler will be a payable add-on and its settings will be controlled on the "Standalone settings" section in the LC IDE. I wonder, how the Levure Packager would be aware of this new functionality without an update? But hey, it's too early to say anything anyway, so let's not get consumed in speculations. Let's wait and see.

If that is the case then just password protecting the levure.livecodescript stack won't offer the protection you want. Any stack file on disk can be replaced IF a person has write permissions to the application files. Try it with any of the stacks in your app. Password protecting them doesn't change this.

Yes, I totally agree and have thought about this too. Using file hashes generated during packaging etc. would be impractical though if one needs to save modified stacks (for whatever reason) from within the built Standalone. I believe it would be largely sufficient to hide some UUIC in each stack and query against that during the startup sequence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants