http://www.perlmonks.org?node_id=327440

Background: I am currently in the process of writing a training course, and potentially a book as well, that deals with Perl security. The topic which follows is the result of a discussion I had with jarich on a train. The purpose of this node is to foster discussion and ideas on what may be a worthwhile addition to Perl's existing security features.

Update (12th Feb 2004): This was originally posed as an academic question, with the intention of the mechanism to act as an extra layer of protection for experienced programmers, in much the same way as strict, warnings and taint checks provide extra safety. jarich presents an excellent explanation and response on this.

My apologies to anyone who thought that this was intended instead of other security mechanisms. This was certainly not my intention. The thoughts presented here are instead intended as an additional tool for the experienced programmer who wants additional safety layers to protect against programmer error.

Restricted data

Perl has a concept of 'tainted' data. Data that is considered tainted cannot be used to open files or used with anything involving the shell. It's a great way of stopping uncleaned data from being used where it should not.

However, to my knowledge there is no mechanism in Perl to prevent private data from being used where it should not. If I have a credit-card number that I wish to process, then I don't want that being printed to the screen, to a log-file, saved to disk, and definitely not sent out in an e-mail.

There are programming practices that can help prevent this (eg, undefining the variable as soon as you're finished with the sensitive information), but no inbuilt mechanism to prevent accidental disclosure. As such, I'd like to float the idea of 'restricted' data.

'Restricted' information cannot be sent to an I/O boundry which is not specifically marked as being able to accept restricted data. In our credit card example above, the connection to the credit-card processing facility would be marked as being able to accept restricted data, but everything else would not.

In the same way that the result of any expression involving tainted data is tainted, the result of any expression using restricted data would also be considered restricted.

There are many applications for such a framework. Passwords, encryption keys, and other sensitive data in many systems can be marked as restricted, providing an extra safeguard against them inadventantly being revealed. In government or military systems, classified information could also be marked as restricted.

I'm hoping to gauge the community's feel for both the need for restricted data, and also any input on what may be felt as the best way to implement these features. As such, I have a few questions I would like to pose:

As stated in the introduction, the purpose of this node is determine if the idea has merit, and to discuss the best way to progress forward if it does.

All the very best,

  • Comment on 'Restricted' data, an additional security mechanism for Perl.

Replies are listed 'Best First'.
Re: 'Restricted' data, an additional security mechanism for Perl.
by Abigail-II (Bishop) on Feb 08, 2004 at 17:23 UTC
    You might be able to do something like that by opening all your IO handles via a specially made layer, and by tainting all sensitive data. Your layer can then prevent output of tainted data, unless it's the handle is marked to accept tainted data.

    You might be able to do something by tieing your filehandles. Or you could dive in the Perl internals, and use XS to set some special magic on sensitive data.

    Abigail

      A way to approach this would be to create a pair of facilities - a 'restricted-datasource' and a 'restrict-output'.
      The first causes any data obatained from that a specified source is 'auto-tainted' (to coin a phrase) - essentially one half of your I/O handle layer. Note that default input operations remain untainted (unless tainted by other means).
      The second overloads the various output functions, and prevents output of any tainted data (and should throw a compile-time error).

      The downside of this sort of approach, however, is that you can still fall prey to the '$a=taintsource; $b=$a; print $b;' problem. The only way to prevent that is to move all data into a complex object (that contains sensitivity information along with the data), and write operator/function overloads to operate on that object - as well as a set of new functions to raise/lower the sensitivity of an object.
      The performance impact is left as an exercise...although it offers the basis for a very secure language - where you could only output data specifically flagged as outputable for that destination.
      -R
Re: 'Restricted' data, an additional security mechanism for Perl.
by simonm (Vicar) on Feb 08, 2004 at 21:46 UTC
    Neither a simple boolean "restricted" flag nor a tiered "restriction level" system are really sufficient.

    For example, customer credit card numbers should only be passed to the card-processing facility, while your SQL DBMS connection password should only be passed to the database. They should both be marked as "restricted", but you don't want to let them cross-contaminate. (Unless you explicitly enable that.)

    Instead of a flag or an incremental level, something along the lines of categories might be more useful -- this data is restricted as "customer private" while that other data is marked as "server internals", and only channels/objects which are approved for that category can access them.

    More generally, you might want to look at Capabilities for a more sophisticated way of building an access control model.

      This is very close to what pjf and I were talking about. If we were to talk some sort of implementation from the programmer side of things you might do something like this:
      #!/usr/bin/perl -wTR use strict; use CGI; use DBI; restrict DBPassword, DB; my DBPassword $passwd = "abcdef"; my DB $dbh = DBI->connect("DBI:mysql:something", "someone", $passwd); # ALLOWED my $cgi = new CGI; print $cgi->header(); print $passwd; # NOT ALLOWED, program terminates print STDERR $passwd; # NOT ALLOWED, program terminates open(FILE, "> somefile") or die "Failed to open: $!"; print FILE $passwd; # NOT ALLOWED, program terminates restrict CreditCard, CreditCardGateway; my CreditCard $credit_card = $cgi->param("credit_card"); my CreditCard $expiry = $cgi->param("expiry"); my $foo = "$credit_card $expiry"; # Foo is now # CreditCard type too. print $foo; # NOT ALLOWED, program terminates print STDERR $foo; # NOT ALLOWED, program terminates print FILE $foo; # NOT ALLOWED, program terminates my CreditCardGateway $gateway; open ($gateway, "| cc_card_gateway") or die "failed to open gateway: $ +!"; print $gateway $foo; # ALLOWED print $gateway $credit_card; # ALLOWED print $gateway $expiry; # ALLOWED $foo++; # Still of CreditCard type...
      What this gives us is the ability to specifically choose where our data can go. We still have to make sure that we correctly filter stuff (just like we shouldn't use the regexp /(.*)/ in taint checking) but it helps us be just that little bit more sure that we're not going to make stupid mistakes and send out private date to the wrong person/process.

      So, does anyone other than pjf and I think this would be worth while?

      Update: changed the title

        I'll still going to say I don't understand the motivation, but this makes your goals more clear. I don't have a vested interest in fighting this one, but I am enjoying playing devil's advocate...

        So, if the goal is to keeping newbie programmers from using a variable without first running a subroutine on the variable, what is to say they can't use a weak subroutine to "clean" a variable?

        filter CreditCard, sub { return $_ };

        Also, what is to prevent someone from just passing around the gateway variable as a "key" within the code?

        sendToEvil(DB,$passwd)

        I could be missing some of the finer points, but essentially my point is "a lock is no good if the key is under the door mat". It seems the key is under the door mat. If not, I'm darn sure I could get that key fairly easily, and that by definition of the facilities employed in implementing this, isn't not really a security measure at all.

        Now some languages have private variables, and this is marginally useful if your fear is someone printing a password. It seems we would go further by trying to find a way to write private variables that can only be read from certain packages. However, this not say some one can't modify the original code (or perform other exploits) to defeat this "security".

        So why don't we trust the code we are running? Is this part of a plugin architecture where arbitrary users can upload code? If not, don't allow that. Otherwise, isolate your credit card and password items into modules no folks have value tampering with. If you really can't trust your fellow coders on a project, you might (possibly) be able to write FETCH/STORE kind of wrappers that deny access from outside the package. (This is theory, I don't know...).

        Essentially security should deal with external sources getting at data -- other users, other programs, networked or not. When you can't trust your own code, that's sandboxing, and is a different problem. Calling this security, at least in my eyes, gives us a false illusion of being secure. This is just a very small piece...helping to know that you have not handled data loosely throughout your app.

        For one who is teaching security, start with the basics. Network security. Open ports. Packet sniffers. Plaintext data. Encoding is not Encryption. Injections. SSL without keys and key exchange. DOS vulnerabilities. Cross-site scripting and SQL vulnerabilities. Changing HTML forms to alter important fields. Spoofing and IP games (arp). Man-in-the-middle. Local security. Permissions. Uploading and executing code to gain local access. Only once that you have stopped all-of-the-above is the "restricted code" module really important. All of the others have higher gains and are more likely to be exploited by 'evil'.

        I'm not a security expert by any grounds, but where I work I've seen and fixed numerous holes in our mystery app (FYI -- it's not Perl) since I'm one of few that has interest in finding/closing them. The most obscene was encoding passwords BASE64 (plaintext-equivalent) and leaving the file permissions as 655! Local socket exploits (non-root user being able to connect and manipulate root daemon) were also found. We also used to use a lot of plaintext network traffic. It's a big deal, and you've got to look everywhere to clean up what most folks don't know to think about. This is all white-hat easy stuff too... I'm sure it can get a lot more evil/complicated if someone really wanted in to our app. In conclusion, we aren't even close to secure now...but it's getting better.

        Write a module that does this. See how much you like it. I'm not saying it's a bad idea, and I'd love to have a module that would allow me to choose where I even want restrictions to be usable. (In other words, I'm not willing to jump in two feet first off the high diving board ... yet.) The idea of cleaning does make the whole concept more palatable. But, I think you're not going to be as thrilled with it in practice as you are in theory. (It's ok - most good theories are like that. It's just that not all good theories are practical.)

        ------
        We are the carpenters and bricklayers of the Information Age.

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        This is what I already understood pjf to be explaining.

        I don't agree with putting this kind of thing in the core. If your code had "use Data::Restrict;" or some similar module invocation near the top, that'd be fine by me.

        One way this could be made a module is to make that module override all the output functions, which is what I had said already. The data structures I used, although ugly, get the job done. Your restrict function, as part of a module, could be just a way to set values in such a data structure. The new versions of the output functions in the same module would use that data structure.

        Your example seems to have a weakness I and others have already pointed out -- restricting the printing of one variable at a time does not prevent assigning the value of it to another variable, then printing that. You could carry magic around in the language for every variable, but that would likely be bad for the common case. Since what is being proposed is sort of like a SuperTaint -- "don't even let this variable be output until cleaned or pointed at a certain output path" -- then perhaps it could be worked into the core to use the same Taint flag and just add code to the path when a restrict option is passed to the interpreter. I still don't like that. It's bulky, clumsy, and the porters have enough work to shoulder now.

        The smart thing to do from a security standpoint is always to deny by default and implicitly allow what is needed. This is the same when one is protecting oneself from oneself as when protecting oneself from strangers. I've shown code which does that. I've explained ways to further the protection, as by using Safe to disable the core's output routines except inside the module handling this.

        Using Safe, in fact, allows one to prevent variables from being in a scope where they are not wanted. Anything inside a Safe compartment has to be explicitly handed a variable in order to be able to get to that variable's value. By making the code for your program modular to the point that each fundamentally different operation can be in a separate compartment,one can only share those variables which are sensitive with compartments which need them. Any compartments which don't need to do output can be left unable to do so. Any compartments which need to do output but which don't need access to the sensitive variables can be part of a namespace that can't reach those variables. This part is all accomplished just by good use of Safe.pm.

        In addition, a restriction on printing variables other than those explicitly allowed can be helpful I guess, but not all that necessary, as proper use of Safe keeps the scope of the variable very small, keeps the areas of the program which can do output fairly small, and keeps the parts where the scopes of the sensitive variables and the ability to do output overlap only where absolutely needed. To debug those parts then becomes much simpler.



        Christopher E. Stith
        This development seems interesting, both as belt-and-suspenders, and as a platform for adding actual security functions with a simple Use statement. Some thoughts:

        If each restriction class (i.e. CreditCard, CreditCardGatewy, PinNumber, Password) is made equivalent to a unique bit flag, you could add them together to produce a "security level bit vector". This might force more than one kind of cleaning to be done, or might restrict more kinds of usage (i.e. is allowed in a certain db field, is not allowed in a cookie, output anywhere triggers a logged alert).

        This could be extended to objects, and maybe using @ISA to hold the different security classes would lend itself to describing the concatenation of restriction types.

        If extended to only cleaning certain fields of an object (or keys of a hash) you could i.e. keep $o->{MothersMaidenName} while cleaning out $o->{PinNumber}.

        It could scan symbol table for variables and hash keys which match certain built-in and customizable regexes, like /sec|pass|pwd|pin|salt/i, so you can enjoy reduced stress by maintaining the practice of naming sensitive variables a certain way, as in Hungarian notation (not used much in Perl though).
        This could also be used to drop a security policy on top of an existing module without changing the module itself (basically tainting specific parts of some data structures it uses). Then perl -cw would tell you what it finds, i.e. "Hash key mypass used insecurely at User.pm line 100", in the case that you have a debugging statement left in. This is not of course security, but it is neat in terms of engraving that "line in the sand" a bit deeper.

        Some effects I could imagine that would be useful:
        Data::Dumper would show only securely cleaned strings.
        Variable $cc_pin would be cleaned before destruction so it is eradicated from memory
        Security policy can be implemented at prototype level
        Maybe could be mixed with other prototyping modules, to allow only certain things to be sent to certain gateways (inverse of the original intent of the module).
        By catching how certain variables are used, this might be used for debugging.
        Being able to overlay policies over specific uses of parts of objects might be interesting for other uses than security.

        Maybe it would work like this. (Pardon I am saying 'secure' this, not 'restrict' this):

        use CreditCard; use Person; # a Class::DBI object use Data::Dumper; use Data::Secure qw(SecurityTypes secure secureall); my $secmgr = new Data::Secure->SecurityManager; # to alter general ope +rations $secmgr->regex = '^sec|pass|cc_/i'; # overwrite default regex $secmgr->classes = qw(CreditCard CreditCardGateway); # each has a set +of policies and cleaners associated with it. my $pincleaner = $secmgr->cleaner->new(CreditCard, qw(&cleanccpin &cle +anccnum)); # cleaners called in series $pincleaner->disable(&cleanccnum); # unload one my $perry = new Person("Perry Rhodan"); print $perry->password; # carps since "password" matches the regex secure CreditCard $perry->card; # now $perry->card ISA CreditCard my $buckaroo = secure Person->new("Buckaroo Banzai"); # $buckaroo now +secured by default policy. secure Person; # or just do this for all new instances of Person from +now on $buckaroo->addsec qw(PersonalData DenyCookies DenyTmpFolder); # Add po +licy classes, so now ISA CreditCard, PersonalData, etc. secure SecureRamen $buckaroo->noodles; # this now safe to eat secureall (CreditCard | PersonalData) Person; # secure all current and + future instances of Person. Can you do this, which also needs Credit +Card to be treated as a scalar value? my $kyle = new Person "Kyle McLaughlin"; print Data::Dumper $kyle; # this now would substitute asterisks for di +gits in $kyle->card->cc_number my CreditCardGateway $gw = $some_io_object; print $gw $kyle->card->cc_number; # okay here and db only
        Yes, this is pretty much what I thought you were talking about earlier. And I like it. I can't see any way to implement it though without messing around in the core.
        Dear jarich and pjf,
        I think that the confusion about the issue of restricted data stems from it being a solution to a problem we haven't seen. You should define the cases where this would be neccessary, perhaps with some examples. I, personally, have never encountered a situation such as sensitive data leaking out etc. and so restricted data seems superficial to me.

        I am sure that there are others with my opinion and I urge some of the more experienced monks to clearly explain the situations in which we would need restricted data...

        The guy with the cheap signature.
        My site
        Is any of this implemented, or is this just wishful thinking?

        Abigail

        Here are some potential issues:

        1. In a long project, how would I figure out which data is restricted? If the data is restricted 2,000 lines above where I tried to use it, short of an egg hunt, how would I know? (Seeing if the program dies when trying to print is an unacceptable solution.)

        2. If I unrestrict the data for an operation, do I need to restrict it again? What if I forget, since I might have dozens of restricted variables? One omission could be disastrous.

        3. And would people become more careless, thinking they are safe with this proposed option? (Read #2)

      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: 'Restricted' data, an additional security mechanism for Perl.
by jacques (Priest) on Feb 08, 2004 at 16:08 UTC
    If I have a credit-card number that I wish to process, then I don't want that being printed to the screen, to a log-file, saved to disk, and definitely not sent out in an e-mail.

    Then don't do any of those things. There isn't any safeguard for programmer error. It happens all the time.

    Passwords, encryption keys, and other sensitive data in many systems can be marked as restricted, providing an extra safeguard against them inadventantly being revealed.

    I couldn't help but think about Java's private, protected and private protected (or is it protected private?) safeguards. By default, Perl 6 will make class variables private, which I think is a good thing.

      If I have a credit-card number that I wish to process, then I don't want that being printed to the screen, to a log-file, saved to disk, and definitely not sent out in an e-mail.

      Then don't do any of those things. There isn't any safeguard for programmer error. It happens all the time.

      You're correct, there is no safeguard for programmer error, but it is possible to add mechanisms to make it more difficult for the programmer to make mistakes without taking steps to get around those mechanisms. Taint checks are a close anaology to the idea of restricted data. By requiring that you clean your data before using it, the programmer is required to give thought to that process. Even a good programmer will make mistakes at times, and taint checking helps avoid these. Even the use of strict and warnings won't stop programmer mistakes, but they go a long way to catch many of the common ones.

      The idea of restricted data is the same -- to provide a mechanism whereby programmers need to go to more effort in order to make a mistake. A very good real-world example of this is when something goes wrong and the program generates an error message. We don't want sensitive data in that message, even if the subroutine which generated the error was dealing with sensitive data at the time. It's not a trivial task for your (potentially third-party) subroutine to tell whether or not its arguments are sensitive.

      As for a lot of security being provided by the operating system (mentioned in other responses), I quite agree, but the operating system is only part of a complete security solution. There's a long history of very secure machines running very insecure programs, and vice-versa. In the case of the proposed restricted data mechanism in Perl, we may be able to signal to the operating system that such data should be treated in a special way -- eg, by using secure (non-swappable) memory to avoid sensitive information being written to a swap file.

      The comments that such a mechanism would incur a higher overhead are well founded, and not something I had previously given much thought. I imagine that the overhead would be similar to that incurred by turning on taint checks. One would hope that any implementation would give developers a choice as to the use of restricted data, in the same way that one has a choice as to whether or not taint checks should be used.

      Many thanks to everyone for the feedback, it is very much appreciated.

        The idea of restricted data is the same -- to provide a mechanism whereby programmers need to go to more effort in order to make a mistake.
        This statement scares me. If this were true, and there were no programmers of any worth in the world, we'd need to throw away all of our C and assembler code right now. It's too easy to make mistakes. Nope, a good programmer tests his code, and better yet, has folks test his code for him. Shepherding is all well and good, but it is no substitute for education, analysis, and foresight.

        If you can't trust the software you are running, then it's really a lost cause in all languages. A programmer who needs to write "use restricted variable yes I really mean it", can abuse this just as well as any other variable. In the real world, private access isn't there for security reasons, it's there for a much better reason -- locking an API down to enforce an interface.

        Other languages that have private access can usually access private variables through either reflection/symbol-tables or native bindings (example: I can read & write private variables in Java using both reflection and JNI).

        So, adding additional security 'features' into a language may only give a false sense of security, odds are that injection attack or cross-site-scripting bug is still there, as it's an algorithmic/implementation bug rather than a language issue.

        Having security features can often be misleading. For instance, I know of a certain application that saves passwords BASE64 with world-readable permissions. I know of another that saves passwords plaintext. Local-socket exploits too. The language can't shield you from any of these, and often these sort of problems are the worst kind.

        Security, essentially, is needing to know all of these things. They can't all be fixed in terms of language usage. It takes a very strong programmer to know what code is insecure and what isn't.

Re: 'Restricted' data, an additional security mechanism for Perl.
by Vautrin (Hermit) on Feb 08, 2004 at 19:23 UTC

    First off, I'd like to mention that a large part of security does not rest with the programmer; it rests with the operating system. If your operating system allows an attacker to gain access to swap space, they can scan if for senstitive information. If your operating system allows an attacker to access memory that isn't his or hers, they can (once again) scan for senstitive information. (This is, by the way, why the OpenBSD project encrypts swap space.)

    Having said that, I think it would be great if some kind of Restricted Data switch was available, i.e. by calling restrict ($var); only I/O conduits marked safe for restricted data could use it. I would also love to see some kind of encryption built in, so that even on OSes that allow programs to peek at the private data of other programs, it would be impossible to understand the data -- een if it could be viewed. (Although it is important to point out that an attacker could look for encrypted data -- because they would know it was valuable, and if the encryption could be compromised this would be much more insecure then if the data wasn't encrypted)

    What mechanism (if any) should be providing for 'cleaning' restricted data (eg, so only the last four digits of your credit card number can be shown)? Regular expressions are the obvious choice.

    I think that people should be able to create subroutines to "unrestrict" their data, since they are the ones restricting its use in the first place. So you could create a subroutine to chop off the first 12 digits of a credit card number, to X out the numbers in a bank account, or whatever you deemed suitable.

    Should there exist a hierachy of restricted information (Eg, 'Top Secret' data cannot be sent via a 'Secret' channel, but the reverse would be fine.), or should data simply be restrict/unrestricted, in the same way that data is either tainted/untainted.

    I think that users should be able to create thier own hierarchy. You're going to run into a lot of situations where an arbitrary hierarchy won't quite fit. But if those conditions were met, or there was by default a "Secrect" -> "Top Secret" -> "I could tell you but I'd have to kill you" hierarchy that would be even better.

    As far as computational cost of such a system, I think it would be negligible. The programmer would have to explicitely invoke it, and even then the only data that would need to be sepcially handled would be invoked as "restricted". Of course, this could be a problem if the restriction system worked something like the $`, $' variables -- i.e. use one slow your whole program down.


    Want to support the EFF and FSF buy buying cool stuff? Click here.
Re: 'Restricted' data, an additional security mechanism for Perl.
by zentara (Archbishop) on Feb 08, 2004 at 14:00 UTC
    It sounds like you are trying to give to Perl some "MS-windows" style of security. Let the OS (interpreter) decide what you can and can't see. Of course, just as with windows, that kindof security can be hacked. The best way to implement security, is to make GPG (or PGP) more of a standard. In other words, just keep things you don't want seen, encrypted.

    For example, with the credit card data problem: An easy solution would be for the browsers to have the ability to PGP encrypt data, with your key, before submitting it.

    All this would really take, is to get a promo campaign going to get the average person familiar with the basics of keys. It's not that hard, but it seems complicated at first. Then the browser developers could build in PGP encryption of form-data.

      you are trying to give to Perl some "MS-windows" style of security.

      Windows has security?

      Windows-style security? You mean Windows has functionality built-in to allow a programmer (as opposed to the RIAA) to restrict where his data goes? Cool, I'll have to become a Windows programmer.

      Perhaps you are mistaking this for some of the ridiculous DRM schemes that have recently become fashionable. I don't think that's what the original poster intended. I read it as being about a way that the *programmer* could specify how his data could be used, as an additional safety-net in case he tried to do something dumb like spew a credit card number into the error logs. Which seems jolly sensible to me.

      And encryption does not automagically provide security. Your naivety here is touching, but dangerous.

        And Dr. Hyde mused:

        And encryption does not automagically provide security. Your naivety here is touching, but dangerous.

        What? Encryption does not provide security? Maybe not "automagically", but neither would some security method that he is describing, it would be nothing more than "flock", unless it used encryption.

        As far as the windows scheme to do it, I'm only hazarding a guess from memeory, because I don't even boot windows anymore. It's been years. But I remember hacking some registery entries, trying to find some software key, and windows had some sort of "encryption ring" in the registery, where software writers could put id's and keys ( and who knows what else) to prevent people from running programs without authorization. It could( and probably is) used to hide data from unauthorized access.

        But considering how easy the crackers come out with patches to bypass all this "security", I would say it's worthless, except to keep the "honest guy honest". It won't stop the person with bad intent.

        But proper PGP encryption of data is about as good as you will get, as long as you don't consider Tempest style snooping. (Which is probably more widespread than people want to admit.)

Re: 'Restricted' data, an additional security mechanism for Perl.
by exussum0 (Vicar) on Feb 08, 2004 at 13:35 UTC
    # Should there exist restricted data which cannot be cleaned? Eg, passwords or decryption keys?
    # Should there exist a hierachy of restricted information (Eg, 'Top Secret' data cannot be sent via a 'Secret' channel, but the reverse would be fine.), or should data simply be restrict/unrestricted, in the same way that data is either tainted/untainted.
    Should there be, could there be? If you are in my backyard, don't expect to 1. trip and break your ankle, 2. get shot at. That's the general perspective. But someone pointed out to me, during an entire java discussion here, it incures a cost to do that type of checking. It also incures an inconvenience. But I'm of the OOP camp and like the idea of "private data". Yeah, messing with my internals may get me to do a neat trick now, but when I chnage my internals in v2.0, your code breaks and thus, a money costing bug gets introduced by accident. That's my view.

    As a run-time directive, it'd be nice. sorta like perl -r (argh), for restrictive, but it'd create a cost for every access. Do people care? Yes and no. Will it happen? Who knows :)


    Play that funky music white boy..
Re: 'Restricted' data, an additional security mechanism for Perl.
by mattr (Curate) on Feb 09, 2004 at 07:29 UTC
    Abigail's comment sounds right on the mark, a magic security attribute might be useful. I also wonder if -T could be pressed into service without stir-frying XS, though that might not be so useful.

    To add something of my own, I once mentioned on PM when I was writing a shopping cart app that did realtime credit card billing, that I was disconcerted at being able to find the credit card numbers by grepping the linux swap file after perl had quit. People said, well yeah. I was able to solve this I think by overwriting strings with garbage of the same length and then undefing them.

    Also I wrote an easy to use wrapper I call QuickCrypt.pm which I sometimes use to quickly encrypt and websafepack form data with different algorithms.

    I am reminded of lazy loading in Class::DBI which, if it new which fields were sensitive, might be induced to keep them unread normally. Perhaps just adding some patches to common modules to let them know some data is sensitive might be useful.

    Anyway while developing channels to intentionally restrict your own actions is one thing, I wouldn't mind the converse as well, that is to restrict outsiders (say on a shared server) as much as possible from potentially viewing your data.

    There is a danger of being seduced by obfuscation and not getting real security, but some things that pop into mind are:
    - overwriting used data
    - providing an encrypted ipc cache in ram
    - transparently encrypting/decrypting sensitive scalars and lists so they are seldom visible (interpreter could generates a key when launched but that key will be in memory..)
    - maintaining an ongoing encrypted io stream which data could be injected into without being obvious
    - generating a noisy stream that is hard for traffic analyzers to pull apart.

    These things all have in common the idea of keeping an admin of a shared server (or a malicious piece of spyware) in the dark as much as possible, and to remove clues about running processes. I don't know if any of these really would work against anything but the simplest thieves though. Anyway it seems that as long as you keep both eyes open, everything is relative. So if you can get perl modules, the interpreter, the os or the underlying hardware/network to cooperate with you I'd say you have a fair chance of relative success. Probably I'd guess ease of use would be the second most important thing after adding some magic like Abigail suggests.

Re: 'Restricted' data, an additional security mechanism for Perl.
by bl0rf (Pilgrim) on Feb 10, 2004 at 03:14 UTC
    Methinks that this might have a useful application in some sphere ( perhaps a mutation of this idea? ) but the farthest it can go is a module and a tutorial explaining the idea to programmers. I do not beleive this is worth implementing into Perl itself, I also don't believe in preventing programmers from making mistakes - if I didn't make mistakes I'd go crazy.
    This could probably be implemented as an object that's like a cache for data - it encrypts it on the way in, and then you have to call a decrypt routine on the way out. This will prevent data turning up in error messages.
    I think what pjf wants is a system where the data will have to be explicitly used, instead of restricting the use (make the programmer completely aware of what he(she?) is doing).

    (Yes, I do realize that I denounced it and then provided a possible implementation... perhaps I am crazy already)

Re: 'Restricted' data, an additional security mechanism for Perl.
by dragonchild (Archbishop) on Feb 09, 2004 at 16:58 UTC
    simonm pointed out my first thought when I read this node - I have different items restricted to different pipes. CC numbers need to come in over the web, but not go out over the web. They need to go out to the CC provider, but not come in from that pipe. And, they may have to go back and forth over the DB connection.

    But, the DB user/password@sid should never go anywhere except to the database. (It shouldn't come back from the database, even.)

    I don't think this is really useful, as it stands. It also sounds like it's something that should be done at the application level, not at the language or OS level.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: 'Restricted' data, an additional security mechanism for Perl.
by mr_mischief (Monsignor) on Feb 09, 2004 at 20:00 UTC
    To keep sensitive data off the screen is the easy part -- the one-argument select() can do that. So can closing STDOUT (and maybe STDERR).

    The hard part is making sure things bound for output file 1 aren't going to output file 2.

    A rather simplistic form of this can be accomplished in plain Perl without modules so long as you only use a special restricted print sub for output. Here's an example:

    #!/usr/bin/perl -w use strict; my %allowed; my %file; my ( $foo, $bar, $baz ) = ( 'foo', 'bar', 'baz' ); my $eol = "\n"; $allowed{ \$foo } = 'a'; $allowed{ \$bar } = 'a'; $allowed{ \$baz } = 'b'; $allowed{ \$eol } = 'b'; $file{ 'a' } = *STDERR; $file{ 'b' } = *STDOUT; sub rp { my $fh = shift; for ( my $i = 0; $i < @_; $i++ ) { if ( $fh eq $file{ $allowed{ \$_[$i] } } ) { print $_[$i]; } else { print "\nAttempt to print unallowed data using restricted +print\n"; } } } rp (*STDERR, $foo, $bar, $baz, $eol ); rp (*STDOUT, $foo, $bar, $baz, $eol );

    Now, that's not very useful if someone throws a print() in the program instead of using the restricted printing sub. If you could throw that functionality into a moduie and use Safe or some other way to make sure that only your restricted printing module can issue a print, printf, sprintf, write, etc. then you have a good start. If one could override the built-in output statements, that'd work, too.

    Part of the problem is that you don't really want to restrict a particular variable in an application when security is of such import. You want to make sure that nothing can be output except to where explicitly allowed. If you disagree with that statement and really do want to allow by default and restrict explicitly, then the example above wouldn't be too difficult to change in that direction.

    I'm not really sure how well the idea will help secure applications, as I haven't thought about it yet. It shouldn't be too difficult to implement, though, even as a hack well above the core which wouldn't slow anything down when this idea isn't in use.

    I'd personally, like I did here, look at the output routines first. Wrapping it up in the filehandle somehow, whether through IO::Handle, layers, tie, or whatever could be an option, but that's back to explicit restrictions instead of explicit allow.



    Christopher E. Stith
Re: 'Restricted' data, an additional security mechanism for Perl.
by hardburn (Abbot) on Feb 09, 2004 at 14:28 UTC

    A quick brainstorm: A Tie::Scalar::SelfDestruct module. After FETCH is called a given number of times (default 1, but can be changed via a param passed to tie), the data inside is undefed. Of course, you have to be careful that you call FETCH only that number of times. Any more, and you'll just get undef back. Any less, and you were better off not using it at all (though a quick while($tied_scalar) { 0 } would take care of that if you had to). The usual problems with tie apply, of course.

    ----
    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      That would give a false sense of security. It'll only protect you by accident, and not at all in the following situation:
      my $super_secret = tie 'Tie::Scalar::SelfDestruct', 1; $super_secret = whatever (); print EMAIL_TO_BAD_GUY $super_secret; print DATABASE $super_secret;

      In fact, you are even worse off, because you don't know what you have send to the bad guy.

      Abigail

        Well, it's a matter of upholding the architecture. Nothing more. Some people don't value it, some do. It's the entire "backyard" thing.

        For most languages, that type of interpretation gets done at compile time. If you can play with pointers/change the permissions dynamically, it's easy to get around, you are right.


        Play that funky music white boy..