+ Reply to Thread
Results 1 to 12 of 12
Like Tree1Likes
  • 1 Post By Imhothar

  Click here to go to the first Rift Team post in this thread.   Thread: Proprosal for message signatures

  1. #1
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default Proprosal for message signatures

    Since I cannot avoid RiftReputation to become real I gave some thought into how one could improve on its integrity and came up with something that might actually work for other Addons as well.

    This would require quite some work to become real and I'm not 100% sure on its efficiency so it might not hurt to have several people have a look at it.

    Problem Statement

    The following attacks must be avoided:
    • Send a forged message pretending it comes from a different addon
    • Manipulation of a message after it was sent by the addon but before it leaves the client

    The problem is: we cannot put any public/private keys in Addons as anyone can just open the source code and read them out. This means we need some help from the RIFT API to make this work. Further, Lua makes it quite difficult to enforce certain preconditions due to its dynamic nature.

    We need the following safety measures:
    • Ensure that calling a RIFT API method like Command.Message.Send really calls the original C-method and not some custom replacement hook
    • Ensure a message is really originating from a certain addon

    Proposed Solution

    The first problem requires a change to the RIFT API which is easy to implement but still takes some effort:
    First, create a new API category, let's call it "Protected". This table contains protected API methods which cannot be hooked. The "Protected" table as well as all member tables are made read-only with metatable magic. In order to prevent someone simply replacing the global "Protected" symbol this table is passed as additional ... parameter to Lua files, meaning every Lua file has access to the original, unmodified "Protected" table. The name of this table is actually meaningless as it should not exist as global symbol.

    Second, for each addon identifier RIFT creates a random unique token and passes this userdata value (light userdata in Lua terms) to the .lue file as additional ... parameter when loaded. Why userdata? Because userdata cannot be created by Lua code. Note that this token is not consistent across clients as it may simply be the addon identifier string's address converted to userdata. This token should only be stored in local values, so other addons cannot access it. The reason for this token is explained later.

    The second problem requires a bit more of work:
    Add a new value to RiftAddon.toc similar to "Signed=true/false". If this value is present, RIFT computes a hash signature over the source code of RiftAddon.toc and all loaded .lua files of the respective addon. This signature can be retrieved with signature = Inspect.Addon.Signature(addon) -- string/nil <- string

    Now to the reason for all the "Protected" talk above. We require two additional methods:
    Protected.Command.Message.Signed.Send() and Protected.Command.Message.Signed.Broadcast() (maybe come up with shorter names). These commands work exactly like their respective Command.Message.* counterparts but send signed messages. Signed messages do not trigger Event.Message.Receive() but Event.Message.Signed.Receive(). The event has an additional parameter called "signature" which can be used together with Inspect.Addon.Signature() to determine whether the message should be processed or ignored.

    Now the new Signed.* commands are a bit tricky. It must be ensured they add the correct signature to the message. A na´ve approach is simply taking the active addon identifier and look up it's signature, but that is not safe. The active addon identifier can be manipulated in two ways: either using Utility.Dispatch() or by inserting a handler into an Event.* table with a different identifier. Both would result in the protected methods to be called with wrong identifiers. I assume RIFT already keeps a stack of identifiers for making Utility.Dispatch() work properly. This stack could be used by the Signed.* commands: Instead of appending the signature of the current addon, use the identifier at the bottom of the stack after the most recent event dispatch. And here the token comes into play: The send methods must be provided a token and only if this token matches the token of the addon identifier at the bottom of the callstack is the call valid and the message is sent with the respective signature. Without the token a custom entry in an Event.* table with the victim addon's identifier would allow any addon to send signed messages on behalf of other addons.

    So far I can only come up with one vulnerability: The debug package. Currently only debug.traceback() is available, but Zorba stated his wish to add more in the future. Some functions of the debug package (especially debug.set/getupvalue() and debug.set/getlocal()) can completely wreck any of the above prevention mechanisms as they allow total control over all Lua values, thus retrieving the secure tokens.

    Conclusion

    As long as certain methods of the debug package are not present and the addon author does not store the token in an accessible location I believe the system can ensure that received signed messages originate from a certain addon.

    Note that this only targets the sending end. One could iterate through Event.Message.Receive and call all handlers with wrong values, but that requires "normal" players to be "infected" with a "malicious" addon. The psoposal here aims at preventing a sender to forge invalid messages.

    Now I don't know whether we actually need this. It first started as a thought experiment if anything like this could be realized in Lua and an environment like RIFT.

    So does anyone else think this may work or did I do a major mistake?
    Last edited by Imhothar; 04-04-2012 at 01:29 PM.

  2. #2
    Plane Touched
    Join Date
    Feb 2012
    Posts
    228

    Default

    Aside from the advantages and disadvantages of securing comm channels this way, I think this wouldn't be enough to prevent message forging unless the full API is put in "Protected" mode.

    Even if you could secure the communication channel and prevent modifications on the addon code, it will need to get its data from somewhere (a Inspect call, a Frame, an Event...). Unless that point is protected too, it could be used to forge fake messages.

    In the case of the ratings addon, you could hook Inspect.Unit.Detail from another addon to generate fake names.

    I think security in the current addon environment is impossible, so the best we can do is either don't care about it, or only trust messages from sources the player decides to trust.

    However, I think I've been too negative in my latest posts, so in order to add some constructive feedback, the signature method you describe could work if the addon could be put in a sandboxed environment and the signatures were hard to forge.

  3. #3
    RIFT Guide Writer Redcruxs's Avatar
    Join Date
    Jan 2011
    Posts
    3,935

    Default

    it would save me a lot of headaches if i could verify that a message is coming from my addon only and not from someone else's /script Command.message.broadcast()

    currently the only thing i can do is design my addon so that it doesn't matter who generates the message. and ensure that there is no incentive to forge messages, both of which are a pain but once i get those accomplished then a Signed.Broadcast() won't be needed.

    i plan on using LibAccount to verify the sender, hopefully that can't be too readily bypassed

  4. #4
    RIFT Community Ambassador the_real_seebs's Avatar
    Join Date
    Jan 2011
    Posts
    16,859

    Default

    Quote Originally Posted by Redcruxs View Post
    i plan on using LibAccount to verify the sender, hopefully that can't be too readily bypassed
    It provides no verification at all. All it does is let you tell whether two character names you've logged in as are on the same account.
    You can play WoW in any MMO. You don't have to play WoW in RIFT. Oh, and no, RIFT is not a WoW clone. Not having fun any more? Learn to play, noob! I don't speak for Riftui, but I moderate stuff there. Just came back? Welcome back! Here's what's changed. (Updated for 2.5!)

  5. #5
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Quote Originally Posted by Baanano View Post
    Aside from the advantages and disadvantages of securing comm channels this way, I think this wouldn't be enough to prevent message forging unless the full API is put in "Protected" mode.

    Even if you could secure the communication channel and prevent modifications on the addon code, it will need to get its data from somewhere (a Inspect call, a Frame, an Event...). Unless that point is protected too, it could be used to forge fake messages.
    You're right, and I was thinking about this too. A way to prevent this would be to mark certain Lua files as "protected" in RiftAddon.toc, for example:
    Code:
    Protected = {
    	"Foo.lua" = true,
    }
    When loading Foo.lua it would not be executed with the global environment _G, but a separate one, in which the API tables Command, Inspect, Event, and so, on are guaranteed to point to the original C-methods. Imagine this like calling setfenv() with a RIFT-provided table before executing the loaded file.

    And thinking about it even more, this would make the Protected.* stuff mentioned in the first post obsolete. The downside to this is of course that the protected file has only access to the API methods, the libraries provided by RIFT (string, table, zlib,...) and it's own Addon and private table. It would be completely shielded from outside influence, but could still access other stuff by bridging it using the addon's private table.

    Quote Originally Posted by Baanano View Post
    and the signatures were hard to forge.
    The idea was that the RIFT API would append the signatures to the messages and signed messages were treated different from normal messages, so all that would be required for the signature is to be unique and reproducible across clients.
    Last edited by Imhothar; 04-04-2012 at 03:00 PM.

  6. #6
    Plane Touched
    Join Date
    Feb 2012
    Posts
    228

    Default

    Quote Originally Posted by Imhothar View Post
    The idea was that the RIFT API would append the signatures to the messages and signed messages were treated different from normal messages, so all that would be required for the signature is to be unique and reproducible across clients.
    What I wanted to say with forging a signature was to forge the "evil" addon code so it produced the same signature than the original one.

  7. #7
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Quote Originally Posted by Baanano View Post
    What I wanted to say with forging a signature was to forge the "evil" addon code so it produced the same signature than the original one.
    Rest assured, creating an addon that generates a SHA-2 hash collision is definitely not worth the effort and currently not even possible

  8. #8
    RIFT Community Ambassador the_real_seebs's Avatar
    Join Date
    Jan 2011
    Posts
    16,859

    Default

    What about minor patches and version upgrades?

    I suppose a cryptographically signed database of Known Versions would be something, but that sounds... heavy.

    Possible alternative: Messages can be forged. You know who sent it, you don't know that they are trustworthy.
    You can play WoW in any MMO. You don't have to play WoW in RIFT. Oh, and no, RIFT is not a WoW clone. Not having fun any more? Learn to play, noob! I don't speak for Riftui, but I moderate stuff there. Just came back? Welcome back! Here's what's changed. (Updated for 2.5!)

  9. #9
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    This is not about encrypting messages. It is only about ensuring the sender can be trusted.

    You're right that the Addon would need to know the hashes of compatible versions. That shouldn't really be such a big problem, as the hash values can be retrieved and the hashes of previous versions can be simply stuffed in a local table. It's located on the receiving end, so doesn't need to be signed or encrypted or anything.

    People with outdated versions would stop receiving messages from newer versions. That is a downside. But: the message is still received and could contain a short version information. The old client receiving such a message with an unkown signature but a "newer" version might show a message to the user asking for an update. But this stuff was never meant to be used by everyone, as the hash would count towards the message size (forgot to mention Utility.Message.Size would need to accept the hash as another parameter) and does present a certain performance hit for the callstack walking and stuff.
    Last edited by Imhothar; 04-04-2012 at 03:49 PM.

  10. #10
    RIFT Community Ambassador the_real_seebs's Avatar
    Join Date
    Jan 2011
    Posts
    16,859

    Default

    I'd been thinking of having Trion sign them or otherwise verify them, so you could only send a protected message as LibExample if you had a signature in their known list, but come to think of it, all we really need is for the API to send unforgable checksums and we can look them up ourselves.

    Good point.
    You can play WoW in any MMO. You don't have to play WoW in RIFT. Oh, and no, RIFT is not a WoW clone. Not having fun any more? Learn to play, noob! I don't speak for Riftui, but I moderate stuff there. Just came back? Welcome back! Here's what's changed. (Updated for 2.5!)

  11.   This is the last Rift Team post in this thread.   #11
    Rift Team
    Join Date
    Oct 2010
    Posts
    927

    Default

    As much as I admit this is a rather interesting conversation, it's probably not going to happen. Security is a big and complex subject, and attempting to guarantee it would either dramatically reduce the potential for interactions between various addons or result in a truly horrifying amount of work. And you still haven't dealt with the issue of a malicious user simply opening up the SavedVariables .lua and editing it.

    Unless someone comes up with a really elegant, clean, efficient, and simple way of providing this, it's really not gonna happen.

    Don't let me stop you from brainstorming though!

  12. #12
    General of Telara
    Join Date
    Apr 2011
    Posts
    944

    Default

    Quote Originally Posted by Imhothar View Post
    People with outdated versions would stop receiving messages from newer versions. That is a downside. But: the message is still received and could contain a short version information. The old client receiving such a message with an unkown signature but a "newer" version might show a message to the user asking for an update.
    A bit unrelated, but that sounds like a great use of messaging system in general to inform players about updates without requiring them to be actively following Curse/RiftUI (or using Curse client *eww*). Not sure how practical it would be, but the idea is here incase someone finds a good way to implement it.

    And about the security, wouldn't the hash solution be easy to implement?
    - When loading addons, the Rift client stores the hash for it
    - Addons can read their own hash with something like Inspect.Addon.Hash() so they can add the current version's hash as a trusted source in saved variables.
    - Rift client embeds the addon's hash with any message sent (so the addons have no control over that part of the message). Maybe only send the hash if an option is set to true somewhere, so most addons that won't need/want the extra security won't waste bandwitch (and if someone disables it on his side, the legit client on the other end will get hash = nil and be able to just ignore the message)

    Even weak cryptographic hash functions (to get a small hash such as a 128 bit one with MD5) should provide way more security than needed. With all the known weakness, it's still quite close to being preimage resistant (and collision attacks aren't a concern in our case). And I certainly can't see anyone trying to create an addon to send fake RiftReputation messages (or any kind of data that will ever get transferred between addons), it's simply cheaper and faster to open hundreds of Rift accounts to vote yourself up (and your enemies down)

+ Reply to Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts