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

I would like to first apologise if I have posted this in the wrong section--it has been a long time since I have graced (or shamed, depends on your outlook) the gates of this monastery. Even the last time I was here, I was a little confused as to where to post a question like this :)

Okay, before we delve into the code behind this, lets look at this background. For a school web design project, I have decided to do a Content Management System (CMS), and get graded on that, as my knowledge is fairly advanced. Now before we get to the "we don't do your homework here" posts, I would like to state that because what I am doing is a little more advanced than what the Teacher can handle, and it was HIM that asked me to post this question online. This mostly because he is more of a network guy, rather than a coder, or web designer. The course itself is little nothing more than a "how to use Dreamweaver to crank out webpages," and I am only taking it, because I would be in the computer lab anyways--might as well be doing something useful.

Now before the posts of "you don't know how big a CMS project is" are passed about, I would like to state that I know perl almost fluently (though, I can asure you, a few jephs will still confuse me), and even can concoct ways to have entire scripts not contain a control statement other than goto, and act as though there are controll statements in there (do not have a demo, but it involves a LOT of && and || operators). I also understand slightly how the perl interpretor works as I've played with it for a little while, and even have done a small ammount of work on a modified Forth interpretor--I just stay away from the perl source code, as it works fine the way it is, and there are definitly a lot more people more capable than me, and versed in programming theory, that can add the new features. I on the other hand, am having fun with a Forth interpretor, which is just slightly less sophisticated than perl (and by slightly I mean.. er... I am sure you know what I mean).

Sorry for the disclaimer, I have been to some web communities with some really unproductive and unhelpful members, and I just had to stop the above off topic posts before they started. I have not been lurking let alone posting, so I honestly do not know how this site currently stands. It is probably better to be paranoid, than rushed off to burn unit due to excessive flaming.

Anyways back on topic:
I have decided to have the CMS be able to connect to several different file storage solutions. Mostly SQLs, and will default to a flat file. Now the problem is some SQL servers only allow a fixed ammount of connections to them--which can massively slow down a website. One work around to this, that is commonly used in the servlette community (please, that was not meant as a flamebait), is what is called a server pool. Where a seperate server, occupies all of the connections allowed to the SQL server, and basically serves as a middleperson. I am not too educated on the theory here, but supposedly it is to not waste the SQL server's time opening and closing limited sockets. It is used in the Java community, so it probably works.

However, seeing as how it is to default to a flat file, I did not want to have to make my own implementation of the SQL3 standard--as the standard, in paper form, is a few inches thick (I've already needed the deadline extended once). So I decided that the information being sent to the server would be in an object format, and simply serialized into a flat file--that is where the problem comes in. More on the background first.

I recently decided to base the server pool on the FTP RFC, though the code has not really realised that new decision. The object format, is in a format I created called WOMF--Web Object Model Format, and is named that mostly due to laziness to come up with a better acronym. There is a whole story to ripping off the name to Intel's infamous Object Model Format, a format outdated by the time of DOS3.x, but that is off topic.

The purpose of the WOMF file, is to abstract the data, so that it might be rendered in XML, SQL, HTML, Lisp, and an assortment of other areas. It is perl based, and not XML based, as I am not XML's biggest fan (or atleast not anymore). The stuff that would require doing it in XML are just insane, and it would make this project's code a wasteland of fugliness. The user of the CMS should be able to, in latter versions of the site, get the information they want, in a format they want simply by changing the extension, form .html, to say, .el, or .xml, or whatever.

The WOMF object when sent, is just put through Data::Dumper, and sent down the tubes to where it is going.

The code I am about to give is probably filled with loads of syntactical errors, let alone logic errors. This mostly because I want to get as much of the code down before I start debugging (most of it is interconnected anyways). Note than where I have '$main::error_handler("blah")', it will most likely be getting changed to '$main::handlers->error->error("blah")'

Anyways the security errors are in the files that put onto the server, once the user has logged in (all use authenticating is done by the server pool--the rest of the code only sees if it is the correct username and password)... the code will look something like this in the final product:

sub put { my($self,$index,$socket_id,@args) = @_; my $type = ref($self) || $main::error_handler("$self is not an obj +ect"); my $uid = $self->{users}->{uids}->[$index]; my $url = shift(@args); my $object; eval('$object = '.join('\t',@args)); $object->isa('WOMF::object') || $self->{user_handler}->kill($self- +>{user_handler}->get_user_by_socket_id($socket_id),'Please, lets not +send crap'); if($self->has_write_permissions($index,$socket_id,$url)) { $main::handlers->db->add_object($object); $main::handlers->socket->add_send($socket_id,"object putted\n\r\0"); } else { $main::handlers->socket->add_send($socket_id,"insufficient permissions +\n\r\0"); } }
Now, I have to the brains to perform an 'isa' on the object to make sure it won't screw up with storage interfaces. Most of the functions should be self explainitory (I do a flush on the sockets in the main code loop). The server names stuff based on URLs--a fairly decent unique naming scheme, and one that is simple to submit back and forth.

I have the handlers as globals, as they controll things that I would prefer to be able to be accessed across functions, due to problems I anticipate would happen with scope. It also allows me to keep tabs on what is open, and what isn't--thus allowing for easier shutdown. Commands, until I get better aquainted with the FTP RFC, are terminated with \n\r\0, to show that they are ended. That most likely will change once I implement FTP more into this project.

It will not be a true FTP, as some commands will be scrapped, only WOMF objects are to be sent, and new, nonstandard commands will be added. Sorry, if some of you do not like that, this is just meant to be similar to FTP, not a full fledge two ported FTP server.

The main code I am worried about--the security question is line number seven of that function:eval('$object = '.join('\t',@args)); It would be WAY too easy to send that statement something that will send the client the /etc/shadow or /etc/passwd files. Which is definately a good thing.

I definately want an abstract format that will get sent to and from this server pool to th CMS, but I do not like XML, as getting that to work would require too much work (create a schema, create a DTD, create the code to access the data, create a code to generate the data XML, create the code to generate the SQL template, etc.)... XML is out of the picture.

I am just curious if there is any more secure way of doing this, without causing such a nice gaping security hole of doom into the server pool server. Also without having to fall back onto.. ugh... XML.

If you are curious about the rest of the source code it is located at http://sb-agssh.sourceforge.net/sourceTree/. Just note that it has not been commented, as I plan to document it later in the implementation section of the docs--the code is so volatile right now, that comments would just confuse people anyways. However, I try my best to write the code in a completely unobfusticated way, that it SHOULD be easy to figure out based on the functions called and their naming. If you feel a section of code should be commented, feel free to ask, I'd be more than happy to help, as it would mean I am getting help.

Also, please, stay away from the rest of the site--it has not been updated for god only knows how long, and is as fugly as shell world itself.

Thank you all for your time, you have been great enough just to read this babbling,
Jamie DA Payne

Replies are listed 'Best First'.
Re: CGI/FTP security question
by hardburn (Abbot) on Dec 10, 2003 at 21:38 UTC

    Using DBI with DBD::CSV may solve your problem. You'd still be writing to a flat-file, but doing with SQL.

    Also, I wonder if you might be better off using TFTP (perhaps over a TCP connection and using some of the extentions for authentication). If all you want to do is upload and download files (not even get directory listings), TFTP might be easier to implement than even a simplified FTP server.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      Thanks, I check those modules out...

      But I thought TFTP was meant to be done over UDP? Some files might be too big to be sent back and forth reliably with UDP. Or am I thinking of another FTP variant? Or is it acceptable to do TFTP over TCP, like you suggested?

        Yes, TFTP is normally done over UDP, but there's nothing that says it must be. In fact, IIRC, the RFC explicitly states that other transport layers are OK. Be sure to check out some the extentions to it that can improve efficiency.

        ----
        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

Re: CGI/FTP security question
by rinceWind (Monsignor) on Dec 11, 2003 at 15:51 UTC
    While it's not a full blown CMS, you might like to look at the collaborative wiki work which is happening (which I am involved with). This has several things in common with your approach: multiple types of data store (MySQL, Postgres, DBD::SQLite), different formatters, etc.

    see the following:

    --
    I'm Not Just Another Perl Hacker

      I honestly do not know what a Wiki is (Sad, I've been on the internet this long, and still have not figured it out). I thought it was some manner of dictionary before :/. Could you clue me in?

      Anyways, looking at what you appear to be doing, it seems to be similar, but a completely different style from what I am doing. I am working on creating something that would require little, or no, training for the average end user to use. Most likely in the style of Angelfire. Just make sure that some manner of storage is up, and work from there.

        See this entry on the Everything2 encyclopaedia (which itself is not a wiki, but shares many of the characteristics of a wiki). The writeup by "Ponder" is written by me.

        I often have to explain to people what a wiki is. In principle, a wiki is a website with user editable content. Most wikis are open to everyone - it is usually not mandatory for people to register before they add material to the wiki.

      • Ward'sWiki - the original Wiki.
      • Wikipedia - now multilingual
      • UseModWiki
      • OpenGuides - A set of wikis for cities

      Hope this helps

      --
      I'm Not Just Another Perl Hacker