pileofrogs has asked for the wisdom of the Perl Monks concerning the following question:

I recently wrote a question, Good IPC Message Protocols?, and wrote it badly. I know I wrote it badly because %90 of the answers weren't to the question I wanted to ask. Sigh... I accept full responsibility and beg my brethren and sistren's forbearance. Achem... And I'll give it another go.

SHORT VERSION: What's the best way to serialise a message so as to make it easy for the receiver to reject bad messages?

LONG VERSION:

I'm building a client server app on Linux. The server has root privileges and does special root-like things on behalf of the client. The client talks to humans and passes requests to the server. For the communication between the client and server I'm using unix domain sockets, so I don't need to worry about encryption and I can even limit access with file system permissions. This is all on one machine, no network required.

Authentication happens inside the server on behalf of the user. So, for instance, the user submits a username, password and request. This means I base my trust on the provided credentials, not any assumptions about the client.

My #1 priority is ensuring that baddies can not trick my server into doing bad things. I assume that baddies own my client and everything in it. When my client passes a request to my server, I want that request to come in a very very strict format. I don't want it to be so strict that I have to pre-code every possible interaction, but I want it strict. Again, I'm talking about the format of the messages themselves, not the carrier protocol.

Said another way, if my server does SQL on behalf of the client, I really really don't want SQL injection attacks to happen.

I want to find the best way to serialize it so as to minimize the chance that I'll un-serialize it wrong. YAML, SOAP, etc... are good possibilities, but they're pretty broad and I think can get better security with something simpler and stricter.

Okay, I'm going to stop now. Hopefully this makes sense this time...

Thank you! If you've read this far, you are a hero!

--Pileofrogs

Replies are listed 'Best First'.
Re: IPC Messages Redux
by zwon (Abbot) on Jan 30, 2009 at 21:13 UTC

    I think JSON, YAML -- are the right things. SOAP would also work, but it's not so simple to use and not so fast. Also you can use Storable, if both applications use the same version of Perl it won't be a problem, but IMHO JSON is more clean solution.

      ++JSON. Prefix the message body with a fixed length header for easy/fast parsing. Header has... Digest? Nonce? Length? Whatnot. Validate, JSON::XS::decode_json(). Ta!

Re: IPC Messages Redux
by salva (Canon) on Jan 30, 2009 at 21:11 UTC
    You have the old ASN.1 and derived formats...
Re: IPC Messages Redux
by BrowserUk (Patriarch) on Jan 31, 2009 at 01:02 UTC
    I don't want it to be so strict that I have to pre-code every possible interaction,

    If any part of the users input can be passed to a shell or otherwise be executed without rigorous validation, you open chinks through which the bad guys may squeeze.

    And rigorous validation of all possible interactions is going to be far harder than encoding (say) a dispatch table of all allowed interactions.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Yes, I totally agree. I'm just a lousy question-writer and I said what I said badly.

Re: IPC Messages Redux
by gone2015 (Deacon) on Jan 31, 2009 at 01:30 UTC

    I regret I still don't get it...

    My #1 priority is ensuring that baddies can not trick my server into doing bad things. I assume that baddies own my client and everything in it. ...

    ... the client and the server are running in the same machine, communicating using Unix Sockets. If the bad people "own" the client, what is to stop them sending well formed messages to the server, whatever format you choose ? Since they own the client, they own all the required code... Shirley ?

    Your authentication presumably is expected to prevent a bad person from connecting to the server ? If so, then the threat is the bad person injecting requests into an existing open conversation ? You say you don't need to worry about encryption... you may be missing the dual purpose of encrypting. The first, and obvious, purpose is to prevent someone who can intercept the conversation from being able to read it. The second, and not so obvious, purpose is to detect attempts to (a) inject stuff into, or (b) remove stuff from, or (c) tamper with the conversation. Obviously, you arrange for both ends to establish a session key during the authentication step, in such a way that the bad person cannot know it. Now, if each message is transmitted with the length of the data, the data and a crc -- where the data is encrypted -- then only after decrypting the data will the crc pass. Which implies that only people with a copy of the session key can send a valid message, or mess with a message and have it still be valid. To detect removed messages you need to include a sequence number in each one.

    I'm still struggling to understand the objective, though. As I said, if the bad people can get to own the client, it's hard to see what you can do to prevent them using it to send bad stuff to the server, simply by using the client... Even if every request requires username & password, if the bad people own the client, they just capture the credentials ?

      Just imagine what could happen if Data::Dumper/eval() was used as "IPC protocol"...

      PS: No, I don't know about the other protocols, sry.


      Search, Ask, Know

      Sorry. I'm just doing a bad job writing my questions of late.

      I'm not trying to prevent the attack where a baddie steals someone's credentials. I'm trying to prevent an attack where they inject something I didn't foresee and crack my privileged process. Just think "SQL injection." If someone says their username is "bob; rm -r *", I don't want to do something dumb like system('chdir /home/'.$username). (This is a dumb example. I wouldn't ever let user-input that close to a system() call.)

      I figure the first step in preventing this kind of attack is narrowing the protocol of communications between the client and server.

      --Pileofrogs

Re: IPC Messages Redux
by Your Mother (Archbishop) on Jan 31, 2009 at 01:06 UTC

    BrowserUK++ above. Often described as whitelisting (allow based) versus blacklisting (deny based). Whitelisting is easier to get right and much safer.

Re: IPC Messages Redux
by hbm (Hermit) on Feb 02, 2009 at 18:09 UTC

    pileofrogs, Some slightly off-forum suggestions, which I hinted at in responding to your original question. I hope I don't sound harsh or condescending - I am neither a security expert nor cgi expert!

    • Seek not yet a Perl solution; but first the advice of other system administators on whether your proposal is wise.
    • Look to do these tasks more efficiently yourself.
    • If feasible, move these root procedures to a non-root account before making them accessible to others. (For example, do they pertain to an application that is root-owned simply for a privileged port, that could run as non-root on a higher port and be NAT'd?)
    • Enable others to execute only discrete root tasks that do one thing, like restart a specific application or tail a specific log.
    • Rather than cgi, have you ruled out shell-access? That would seem a minor inconvenience for the ability to pose as root; and would give you password enforcement, permissions, logging, etc.

      A funny thing about perlmonks: I get better sysadmin advice in my perl questions (badly written though they be) here than I get asking sysadmins sysadmin questions anywhere else....