Want to read Slashdot from your mobile device? Point it at m.slashdot.org and keep reading!

 



Forgot your password?
typodupeerror
×
Security PHP Programming IT

PHP Security Expert Resigns 386

juct writes "PHP security holes have a name — quite often it was Stefan Esser who found and reported them. Now Esser has quit the PHP security team. He feels that his attempt to make PHP safer "from the inside" is futile. Basic security issues are not addressed sufficiently by the developers. Zeev Suraski, Zend's CTO of course disagrees and urges Stefan to work with the PHP development team instead of working against it. But given the number of remote code execution holes in PHP apps this year, Esser might have a point. And he plans to continue his quest for security holes in PHP. Only that from now on, he will publish them after reasonable time — regardless if a patch is available or not." Update: 10/30 12:57 GMT by KD : Zeev Suraski wrote in to protest: "I'm quoted as if I 'point fingers at inexperienced developers,' and of course, there's no link to that — because it's not true! The two issues — security problems in Web apps written in PHP, and security problems in PHP itself — are two distinct issues. Nobody, including myself, is saying that there are no security problems in PHP — not unlike pretty much any other piece of software. Nobody, I think, argues the fact that there have been many more security problems at the application level, then there were at the language level. I never replied to Stefan's accusations of security problems in PHP saying 'that's bull, it's all the developers' fault,' and I have no intention to do it in the future."
This discussion has been archived. No new comments can be posted.

PHP Security Expert Resigns

Comments Filter:
  • Couple thoughts (Score:2, Insightful)

    First, the language is wide open for editing. It might help to be someone who not only finds bugs but fixes them.

    Second, it's PHP. Add another API or something.
    • First, the language is wide open for editing.

      It's wide open for monkey patching, good luck if you want to:

      • Try to get into the source code, it's mostly unreadable
      • Try to get your patches accepted by Zend, you're headed for Funny Time

      Second, it's PHP. Add another API or something.

      I'd advise to switch to a language designed by a human, not a zombie.

    • Re: (Score:3, Insightful)

      Second, it's PHP. Add another API or something.

      Hahaha! Awesome! I'd suggest a few more functions in the global namespace as well. Maybe stop_hacking_attempts() and stop_hacking_attempts_l33t() ... with its parameters reversed of course!
  • by mrshoe ( 697123 ) on Thursday December 14, 2006 @02:03AM (#17233374) Homepage
    PHP Security Expert...

    Isn't that an oxymoron?

  • by phantomcircuit ( 938963 ) on Thursday December 14, 2006 @02:03AM (#17233376) Homepage
    On second thought I would have to agree that the majority of PHP flaws are due to unskilled programming.

    just have a look [milw0rm.com]
    • by Jessta ( 666101 )
      A programming language should attempt to prevent a programmer from making these kinds of mistakes. By making the mistakes obvious in the syntax.
    • by kv9 ( 697238 )

      On second thought I would have to agree that the majority of PHP flaws are due to unskilled programming.

      exactly. yet the flamy blurb seems to be contradicting itself:

      Basic security issues are not addressed sufficiently by the developers. Zeev Suraski, Zend's CTO of course disagrees and points his finger at inexperienced programmers. But given the number of remote code execution holes in PHP apps this year, Esser might have a point. And he plans to continue his quest for security holes in PHP.

      so it's

      • so it's the apps, stupid. how many buffer overflows do we find every day in C/C++ applications? lots. yet I dont hear many people slamming the language.

        Well, maybe you should be. C is a horrible language to use for writing an entire application with. Plenty of safe, higher-level languages with simple to use FFIs exist that are much better suited to such things.
        • Re: (Score:3, Insightful)

          by kv9 ( 697238 )

          Well, maybe you should be. C is a horrible language to use for writing an entire application with. Plenty of safe, higher-level languages with simple to use FFIs exist that are much better suited to such things.

          you keep telling yourself that. meanwhile, in the real world, C/C++ will remain the workhorse of the IT industry.
      • Re: (Score:3, Insightful)

        by /ASCII ( 86998 )
        Actually, I hear lots and lots of people slamming C/C++ because it forces the programmer to do explicit memory managment, something humas are bad at, which leads to bugs and security issues. These people invariably advocate the use of more high level languages that automate and simplify common tasks, such as Java, Python or... PHP.

        The blame for the PHP security mess should be shared between the language design, which makes it a hassle to write secure code, and the language popularity, which means that PHP i
  • by 93 Escort Wagon ( 326346 ) on Thursday December 14, 2006 @02:12AM (#17233412)
    We have a large group of students, staff, and faculty that all have varying degrees of write access to a departmental Apache web server. Every few weeks someone asks why we're not giving people PHP access. Users love PHP because it's so easy; it makes them feel like they're clever programmers. But it seems like security knowledge is never imparted alongside the PHP training. People seem to think it's as benign as plain old HTML. When they ask for PHP I tell them we have a policy about not giving scripting-level access to users without good justification, and they have no idea why that applies to them since "we don't want to do any scripting; we just want to make PHP web pages".

    But even leaving all that aside - it seems like every SANS newsletter has multiple announcements either about a bug in some popular bit of PHP-based software, or else in PHP in general. Until that changes, we're sticking to Perl and Python. It's funny, in a way, since the first time I saw PHP I immediately thought of the days when I was writing Active Server Pages on IIS4, because structurally it is so similar - and now we all realize the similarities on the security side (or lack thereof) as well.
  • by Anonymous Coward on Thursday December 14, 2006 @02:28AM (#17233484)
    It's widely acknowledged that open source programs are inherently insecure. Whether the cause is the availability of the "internal blueprints", the free-for-all repository commit access, or the rampant theft of patents, one wonders. By contrast, Microsoft's .NET platform, including the widely praised C#, doesn't have this problem. The guarding of the internal source code, the standards-adhering developers, and the rock-solid legality of its software patents gives Microsoft an advantage versus the haphazard "open source" languages like PHP and Java. One wonders if this is a harbinger of future defections in the open source language camp. Speaking as a patent lawyer, I advise all developers to switch to .NET and Microsoft's enterprise-class C#.
    • I've always had a problem with the "LOLOL M$ SUXX" crowd, but this is stupid. The Apache code is also available, and it doesn't have these problems. The problem is the basic design of PHP, compounded by the large number of "developers" that have taken it up as the language du jour instead of using better-designed platforms like Python, Ruby or Java. Or yes, any of the .NET languages and ASP/IIS.

      As I finished typing this I realized I'm probably feeding the troll ("patent lawyer", right) but oh well...

    • I'd love to justify your arguments by actually addressing them, but they just don't deserve it. Instead I'll just say that you, sir, are an idiot.
    • Re: (Score:3, Insightful)

      >open source programs are inherently insecure

      Let's lock this person in a room with the OpenBSD developers.

      Not a bad troll though.
  • Actual announcement (Score:5, Interesting)

    by kjart ( 941720 ) on Thursday December 14, 2006 @02:36AM (#17233516)

    Here's the announcement from the source himself, via his blog [php-security.org]. Based on that post I'd say he sounds pretty disgruntled with how his efforts towards security were received i.e. "he PHP Group will jump into your boat as soon you try to blame PHP's security problems on the user but the moment you criticize the security of PHP itself you become persona non grata"

    • Re: (Score:3, Interesting)

      by Bogtha ( 906264 )

      he sounds pretty disgruntled with how his efforts towards security were received

      I'm not surprised. If you read the article, you come across this gem:

      Suraski expressed his regret at Esser's resignation from the security team and hoped that Esser might come to his senses and return. He also hoped that Esser would not turn against the PHP project. The "Month of PHP security bugs" proposed by Esser for 2007 would harm the project.

      That's right, the PHP team think that dedicating a month to finding

  • by Anonymous Coward on Thursday December 14, 2006 @02:47AM (#17233556)
    When I looked at Zend's introduction to PHP, the first sample PHP program was Hello World, and the second was a cross-site scripting vulnerability. Right, I'm going to trust these people.
  • As a PHP user.... (Score:5, Interesting)

    by MasterC ( 70492 ) <cmlburnett@gm[ ].com ['ail' in gap]> on Thursday December 14, 2006 @02:59AM (#17233584) Homepage
    As a PHP user, I have attempted to better the thing by reporting what I think are bugs. I can't name a single one that wasn't closed with a WONTFIX and a terse, non-thankful "that is a feature, not a bug." I honestly have zero disbelief that those same programmers would turn against Esser when he blamed the language, not the user, for the security problem.

    In particular, the late static binding issue (if B extends A then A::staticFunc() ran as B::staticFunc() is ran under class A not B). It's like how it took MySQL took a decade to get stored procedures and views despite many people asking for it. Many people complain about the late static binding issue but last I knew it was still "it's a feature, not a bug."

    Regardless, thanks for your work Mr. Esser...
    • by Shados ( 741919 ) on Thursday December 14, 2006 @03:02AM (#17233594)
      non-thankful "that is a feature, not a bug."
      Oh boy...Microsoft bought out PHP...
    • by Jesus_666 ( 702802 ) on Thursday December 14, 2006 @04:37AM (#17233978)
      Someone should fork PHP and do a major rewrite. Drop features like HTML embedding, introduce properly defined packages and make all functionality available in both procedural and OO fashions. Clean up the function names so they're predictable. And make some of the more dangerous functions safer.
      PHP could be turned into a decent general purpose scripting language if someone would fork it. Unfortunately that means that we'd need someone who knows the codebase, has time and is fed up with the current PHP development process. Maybe we could talk Esser into it...
      • Those are the times I wish I'd knew more C/C++ to support such a fork.

        So long, I am currently switching most of my PHP projects to python (which is a PITA if you are used to php's mysql-handling and regexp-support..., but a major step towards a more reliable webserver enviroment). Unfortunately, clients tend to persist on PHP ("Build it, we'll find a 15-year-old scriptkiddy to do the support and extensions...")
        • Re: (Score:3, Interesting)

          by gbjbaanb ( 229885 )
          perhaps a better idea than forking PHP would be to add these desirable sections to python instead.

          Then a php to python coverter, and then we could start to forget about magic_quotes and safe mode.
          • Unfortunately, Python and PHP have vastly different principles behind them and Python isn't everyone's cup of tea. If one would change Python to include those things most liked about PHP the result wouldn't be anything near what Python is supposed to be.
      • Re: (Score:3, Informative)

        PHP's niche in the web ecosystem is as "the stupid, easy to host scripting language". If you forked it like that, you'd basically have mod_perl, and everyone would still be using the original, awful PHP.
        • That's why I said "general purpose scripting language". I use PHP for shell scripting and it's pretty useful (you can crank out a decent script for just about anything in no time and if you know what you're doing it's no less safe than a Python or Perl script would be). However, I have to agree that PHP is egregiously designed, from the inconsistent way of doing just about anything to the fact that even shell scripts invoking PHP via #! require the <? ?> tags.

          A sanitized (in the meaning of "made mor
          • I don't think PHP merits being put on the command line, even if it were cleaned up. Instead of mod_perl, you'd just have a grotty Perl dialect without CPAN and, really, Perl itself is already deprecated. I only use it at work because I have to. All my personal projects are done in Ruby or Haskell. I'd probably be using Python, too, if the users I routinely run into on the net weren't such zealots.
      • Why would you go to all that effort just to recreate perl?
    • Re:As a PHP user.... (Score:5, Informative)

      by Splab ( 574204 ) on Thursday December 14, 2006 @07:25AM (#17234618)
      Amen to that.

      I had a fun one where one of my scripts would cause a segmentationfault, after hours of debug I found that they don't check the return from malloc when you call a function, so a very deep recursive function will result in a segfault. Now I had the problem with an actual system with 1000s of lines, so I made the simplest possible:

      function foo($a){
          echo $a . "\n";
          foo($a+1);
      }
      foo(1);

      Now this is of course a stupid function since it will never terminate, but it illustrates the point of the segmentation fault, I don't mind that deep recursive functions can exhaust the memory available, but I do mind the way the system handles the problem.

      The bug got rejected, and that was that. I don't do PHP anymore, so I don't really care about that any more.
  • by aaronwormus ( 716976 ) on Thursday December 14, 2006 @03:30AM (#17233702)
    The "news" is that Stefan Esser unsubscribed from the security@php.net mailing list.

    Stefan Esser will continue to work on PHP security through maintaining the Hardened PHP project [1] which is a patchset to PHP which enables some low level security features into the language, as well as the suhosin extension [2] for PHP which can be used without patching PHP and "protects servers and users from known and unknown flaws in PHP applications and the PHP core".

    I am personally of the "full disclosure" security mindset, so if there was indeed an issue with the response time of the "PHP Security Response Team" then some outside pressure would be a good thing.

    More about this on Zeev's blog [3].

    [1] http://www.hardened-php.net/ [hardened-php.net]
    [2] http://www.hardened-php.net/suhosin.127.html [hardened-php.net]
    [3] http://www.suraski.net/blog/index.php?/archives/15 -Stefan-Esser-quits-securityphp.net.html [suraski.net]
    • The "news" is that Stefan Esser unsubscribed from the security@php.net mailing list.

      That may be how Suraski is describing it, but if you read you'll find a slightly different story. [php-security.org]

    • From your reference (my emphasis)

      "it appears he'll now attempt to become even more aggressive, do his best to ignore the best interests of PHP by disclosing unpatched holes, and in general trying to expose as many security holes in PHP."

      How can anyone possibly think that disclosing and exposing security holes in an open source project is a bad thing and against the best interests of the language ?

      PHP is essentially the lingua franca of web development but the rise of Rails and Django simply highligh

  • by cheros ( 223479 ) on Thursday December 14, 2006 @03:40AM (#17233740)
    Wow, stunningly insightful response "that's caused by inexperienced programmers". He's a clue: it doesn't matter what the origin of the problem is (other than to fix it longterm) - IT STILL NEEDS ADDRESSING. I got news for you: the concept of covering large security related cracks in code with prime bullshit is probably already patented by Microsoft.

    Personally I would wonder if Essers' 'abrasive style' is not a result rather than a reason for not being listened to and if this flags up a major problem in the way PHP is coded and maintained I'm all for this move. There is no excuse for sloppiness.

    So, the reaction discloses the attitude - seems Esser made the right move..
  • by pembo13 ( 770295 ) on Thursday December 14, 2006 @03:51AM (#17233782) Homepage
    can someone explain how it is that the apperently consensus is that PHP is insecure by design, asside from just poor programming? Thank you.
    • Re: (Score:2, Interesting)

      by aaronwormus ( 716976 )
      The "PHP Way" has always been to give the user sufficient power to shoot himself in the foot. The benefit is that the language itself is not slowed down by "features" which exists only to keep stupid programmers from hurting themselves. There are projects (like hardened php and suhosin) which add these security features to the language itself. There have also been "features" such as register_globals, the Get/Post/Cookie quoting and safe_mode which were prone to attack when not used correctly.
    • Re: (Score:2, Offtopic)

      by nicklott ( 533496 )
      They, can't, they're all just curmudgeonly, aging perl hippies, bitter and twisted cos the web left them behind around the time of HTML 3.2. Viva la Revolution!
    • by gbjbaanb ( 229885 ) on Thursday December 14, 2006 @05:44AM (#17234252)
      One of the biggest 'problems' is the way PHP is generally executed as an apache module. You get a lot of shared webhosts that run php as a module, and so the apache user runs the code. Fine, except that if you want to give your PHP script access to your data, you're effectively giving it access to everyone else's data too. So features like open_basedir were added to restrict this.

      Then there is features like safe_mode that turns off many system functions that an attacker could use to get round the other restrictions, and register_globals which is a feature designed to work around an inherently insecure system of passing variables to php pages.

      and so on, and so forth.. possibly the biggest problem is the ease of coding it, the barrier to entry is so low you will attract coders who (to be polite) don't know as much as they could about programming. So you get a lot of PHP code that is poor quality, makes too many assumptions on things that they should have tightened up (eg, not initialising variables to prevent an attacker from passing them in with their desired values), or checking input to functions from the form or url.

      Its the same issue as VB - it was so easy to code VB apps, my boss could do it. So he did. And they looked, performed and crashed as if a manager had coded them :(
    • by dysfunct ( 940221 ) on Thursday December 14, 2006 @06:14AM (#17234328)
      I actually do a bunch of security consulting for PHP based stuff. A great deal of the issues stems from the very beginning of the PHP language itself. Being designed to be as easy as possible without regard to security has kind of made it the Microsoft of scripting langages. They have not built on insecure code, but rather entire concepts that are inherently insecure (fopen() wrappers that open nearly every data connection they're fed, register globals, SQL string concatenation) and have even for a long time endorsed and taught users those concept.

      Instead of changing concepts midway through they have added security layers and APIs that need to be *explicitly* set - meaning that like Windows (was?) they have a policy of being open per default and having to be explicitly made secure, instead of closed by default and enabling only what you need.

      That's what I think Stefan Esser means when he says "safer from the inside". Many things in PHP are inherently flawed and can only be remedied through changes in concept and nothing else.

      Add to that stuff like $GLOBALS overwrite (more details here [hardened-php.net]) that are/were essentially a WONTFIX. No wonder Essner is getting frustrated.

    • Re: (Score:3, Insightful)

      by Jamu ( 852752 )

      It's impossible to write secure code elegantly in PHP. PHP is an inflexible language in which security features have been added using various options and functions. Any secure PHP code is going to be overly-difficult to read, and this can lead to insecurity via coding errors.

      This inflexibility of the PHP code language is partially solved by the use of numerous extensions (There are gaps: For example, none of the extensions can parse HTML in a natural way). The more API functions and extensions required to

    • by kestasjk ( 933987 ) * on Thursday December 14, 2006 @07:26AM (#17234626) Homepage
      I've written lots of PHP code [sf.net] in my spare time, and have written an article [kuliukas.com] on creating "rootkits" to covertly inject into PHP scripts (phpBB2 in particular), so I thought I'd chime in. This'll probably be a long post but hopefully it'll give people some things to look out for.

      Here are the most common security problems you run into in PHP:
      • magic_quotes: This adds slashes to all input so that you don't have to sanitize it before it gets inserted into SQL. The problem is that developers write their code with magic_quotes on, but don't realize that it's often turned off elsewhere, which leads to gaping holes.
      • register_globals: Variables can be placed directly into the global namespace. If you don't explicitly set all variables before using them anything can be injected into them, which brings me on to:
      • Only critical errors are reported: If you use a variable which isn't set it'll just return null, with no error (unless you specifically turn up the error_reporting level). This means that someone who isn't familiar with the problem won't know that a variable in their script can be written to by anyone until it's being exploited, functions which you would expect to return an error and halt the script if they fail can carry on without giving any indication of failure.
      • fopen_urls: By default you can include scripts hosted on other websites! This often makes remote PHP execution, which would otherwise require eval(), much easier.
        Who would have thought "<?php include($var.'/include.php'); ?>" will run any PHP on any server, anyhere? (The attack in the article above leveraged entry using this, coupled with register_globals.)
      • Inconsistencies: What one function does can never be applied to what another function does; you can never assume anything with the PHP library and always have to keep a browser window with the PHP manual handy. Using a function without carefully reading up what it does, even when it's very similar to another function you're familiar with, is asking for trouble in PHP.
        The same goes for just about everything; are you checking whether some input equals some harmless number before passing it on to a SQL query or the browser? Don't forget that (5 == "5 UNION SELECT secret FROM ..."), null == 0 == "" == false, "a" == 4 == true; generally you just have to be on your toes.
      • Input checking is difficult: Do you want htmlentities() or htmlspecialchars() ? Have you remembered to strip_slashes() if magic_quotes is on? Remember the user can input arrays too, are you checking that the input isn't an array? Have you remembered to escape queries with mysql_real_escape_string() ? mysql_escape_string() doesn't account for the character set being used, and so isn't good enough, trying to escape input for yourself is also dangerous. What about null bytes? Remember that the user can input binary data; PHP allows null bytes, and will add a slash to them, but when you send a string with null bytes to some functions, but not others, the null bytes will be silently dropped leaving only slashes.
        To check input in PHP you have to be absolutely rigorous and take no half measures, people who aren't aware of the dangers don't stand a chance.

      To be honest I'm a big fan of PHP, it's very flexible and lets you develop very quickly and easily; if you have the knowledge and self discipline it's an excellent language. But allowing fast, easy development at the cost of security is insane for a server-side web scripting language!
      I was hoping that PHP6 was all about doing a 180 degree turn on security, but this article doesn't bode well..
      • Correction: When I said "a" == 4 == true I mean "a" == true, 4 == true, "a" != 4
      • Re: (Score:3, Informative)

        by 1110110001 ( 569602 )
        Let's take a look at the "php.ini-recommended" (could be the name means you should use it).
        magic_quotes

        magic_quotes_gpc = Off
        magic_quotes_runtime = Off
        magic_quotes_sybase = Off

        register_globals

        register_globals = Off

        Only critical errors are reported

        error_reporting = E_ALL

        include($var.'/include.php');

        allow_url_include = Off

        The last one should get a fix in PHP 5.2.1 for data-URIs.

        Input checking is difficult: ... htmlentities() ... htmlspecialchars() ... strip_slashes()
        Which of these functions

      • Re: (Score:3, Informative)

        by AnyoneEB ( 574727 )

        Don't forget that (5 == "5 UNION SELECT secret FROM ..."), null == 0 == "" == false, "a" == 4 == true; generally you just have to be on your toes.

        Correct, the semantics of == are different in PHP than in most other C-like languages. The operator you are looking for is === [php.net]. As a further note, I usually explicitly cast values to int if expect them to be integers, so random strings just become zero.

  • by Anonymous Coward
    Variables are untyped, so if you do $a + $b, it's not clear what the result might be. Variables do not have to be declared before use, so if I have code like:

    $authorized = callAuthFunction();
    if(! $authoorized) logoutUser(); // note the misspelling
    mysql_query("UPDATE account SET ...."); // you get the idea

    Woops! Languages that have a permissive syntax make it easy for bugs to hide. And security flaws are just a particular subset of bugs. At a higher level, we have problems such as widespread use of di

    • by solidox ( 650158 )

      Variables are untyped, so if you do $a + $b, it's not clear what the result might be.

      There is a section of the manual which describes the behaviour to expect when types are mixed.
      See... Type juggling [php.net]

      You should always be developing with error_reporting(E_ALL|E_STRICT);
      This would throw a Notice warning about the use of an undeclared variable when the code tries to access it.
      Error reporting should more than likely be disabled for your production enviroment however.

      (E_STRICT is PHP5, E_ALL on its own will still

  • by Beryllium Sphere(tm) ( 193358 ) on Thursday December 14, 2006 @04:22AM (#17233904) Journal
    >bugs were sometimes not correctly fixed or were re-introduced. This was often not noticed because there was no test-rig for exploits and the idea of having one was categorically rejected.

    If that's accurate, and if there wasn't some unimaginable compelling reason, any security person would be unhappy.
  • by ajs318 ( 655362 ) <sd_resp2.earthshod@co@uk> on Thursday December 14, 2006 @05:20AM (#17234166)
    A bad worker blames their tools and a bad boss blames their workers.

    There's no denying that PHP has things wrong with it. It started out as a bastard son of Perl, tried to be a bit more n00b-friendly and tripped over its own cleverness. The beauty of Perl is its very inconsistency. The functions you use most have the shortest names, and there is no need to clutter things up with unnecessary brackets around arguments. Regular expressions, which you are going to use all the time, have a distinct syntax. Number and string data types can be interchanged with such wild abandon, there have to be separate operators for addition and string concatenation (JavaScript, I'm looking at you). There are constructs to populate arrays quickly. All things are subordinate to the goal of letting a programmer get a job done. Easy things are easy, hard things are possible. Perl is so broad-minded, it even has the Principle of Equivalence built in!

    PHP lures you in, with obviously_named_function($par1, $par2) ..... then trips you up with anotherobviouslynamedfunction($par2, $par1). You could say it's not all PHP's fault, as the functions originate from different shared libraries, and PHP is only providing an interface to them by their original name and with something like their original syntax. But it still smacks of laziness on the PHP developers' part. Short aliases for commonly-used functions (a context-sensitive editor can always expand them for the benefit of the anal retentive), and differently-named work-alikes for functions that take their parameters in a different order than you might expect, wouldn't have hurt. Would they?

    Still, you've got two choices, I suppose. Learn to put up with the idiosyncracies or learn another language. And never forget the Principle of Equivalence; "All Means to the same End are equally valid", nor its corollary, "Means which are not equally valid serve different Ends".
  • by maroberts ( 15852 ) on Thursday December 14, 2006 @05:25AM (#17234184) Homepage Journal
    Would a suitable headline be "Goaded, Esser Back"?

    Apologies to Douglas R. Hofstadter
  • If PGP... (Score:4, Funny)

    by Alioth ( 221270 ) <no@spam> on Thursday December 14, 2006 @06:06AM (#17234310) Journal
    If PGP stands for 'Pretty Good Privacy', I wonder if PHP should really stand for 'Pretty Hopeless Privacy'...

Seen on a button at an SF Convention: Veteran of the Bermuda Triangle Expeditionary Force. 1990-1951.

Working...