php-general Digest 27 Aug 2005 09:53:43 -0000 Issue 3648
Topics (messages 221450 through 221465):
Re: Sort table by column and pagination
221450 by: Philip Hallstrom
221453 by: Aaron Greenspan
Re: PHP Move Uploaded File
221451 by: Richard Lynch
[off T] c++ mailing list
221452 by: pedro mpa
Re: Newbie: Safe function call to a .inc file outside the web folder
221454 by: Richard Lynch
221460 by: Edward Vermillion
Re: Computer name?
221455 by: Richard Lynch
Re: PHP Security
221456 by: Richard Lynch
Re: Easier way to clean GET Variables ?
221457 by: Richard Lynch
Re: invert
221458 by: Richard Lynch
Re: creating of html-archive
221459 by: Richard Lynch
Re: PHP CMS
221461 by: Joshua D. Drake
221462 by: Jasper Bryant-Greene
[suspicious - maybe spam] Need advice or code
221463 by: Death Gauge
Re: php vulnerability
221464 by: Raj Shekhar
[suspicious - maybe spam] Re: [suspicious - maybe spam] Need advice or code
221465 by: Sunny Boy
Administrivia:
To subscribe to the digest, e-mail:
[EMAIL PROTECTED]
To unsubscribe from the digest, e-mail:
[EMAIL PROTECTED]
To post to the list, e-mail:
php-general@lists.php.net
----------------------------------------------------------------------
--- Begin Message ---
We have quite a complex product all written in PHP and our own mySQL
wrapper. We initially wanted to use smarty, but due to time constraints, we
couldn't re-write everything, so it never got implemented.
Two feature requests we get a lot are the ability to sort the tabular data
by column heading (click once for ascending and again for descending) and
the second is pagination.
My guess is finding code that does this that you can integrate is going to
take longer than just doing it yourself. It's not that bad...
Just add some variables that either get kept in a session or passed around
via URL's to store the $offset and $order_by.
Then in your code set your $limit.
Then it's just a matter of adjusting your SQL to add "ORDER BY
$order_by LIMIT $limit OFFSET $offset" when relevant. For your array,
it's the same thing, but use array_slice.
To go to the next page just have the link set $offset to $offset + $limit.
Similarly for previous.
Then add the boundary checks, etc.
Good luck!
--- End Message ---
--- Begin Message ---
Daevid,
Lampshade, an API we've put together (as a commercially-backed
alternative to PEAR) does table pagination and column sorting for you.
It's free for non-commercial use, there's a lot of documentation, and
I'm always around to answer questions:
http://www.thinkcomputer.com/software/lampshade/index.html
All you have to do is include the Lampshade files, set up a $table array
in your page, and then call the table() function. You can integrate it
with your current stylesheets, too.
Let me know if you have any other questions.
Aaron
Aaron Greenspan
President & CEO
Think Computer Corporation
http://www.thinkcomputer.com
--- End Message ---
--- Begin Message ---
On Thu, August 25, 2005 10:24 pm, germ wrote:
I'm cc-ing php-general since this belongs there, not in direct email.
> Hi. I read your comment on php.net about handilng file uploads. You
> seem to be one of the few to recognize the security issues regarding
> uploaded files.
Actually, I'm one of many -- I'm probably just more vocal about it
than most. :-)
> I was wondering if you could help me with an issue of
> mine: how to secure an upload directory on a shared server?
>
> My shared server gives my owner as "loginname" group as "loginname".
> So, far I have not been able to find a way to change ownership and
> group names of directories.
Only 'root' can change ownership/group on a file.
And that's good, because otherwise you could write a nasty script
suexec/world-executable, change the owner to somebody else, and then
wreak havoc with their data.
So you can just stop trying to find a way to chown/chgrp
files/directories. If you did manage to make that happen, you've got
MUCH bigger problems than the PHP scripts.
> The public_html directory is 755. I have the upload.php script there.
Fine.
> I am uploading all files to public_html/upload. I also need to do some
> image editing on the files in public_html/upload. But I can't have the
> files write to its child directory, unless i give it that upload
> directory 777. So is there a way to pw protect this directory so that
> only the script in the parent directory that knows the login info can
> write to the child directory?
Do *NOT* use public_html/upload
You probably currently have something like this:
public_html/ (with .htm, .php, and 'upload')
cgi-bin/
[some other directories, maybe]
Make it like this:
public_html/
cgi_bin/
upload/
So now, if somebody manages to upload something nasty with PHP (or
Perl or Python, or...), they CANNOT surf to it, so the web-server
won't just execute it unless you take MORE steps to move it into your
public_html.
There may be files, after due consideration, that you DO move into
public_html, but that should only be after they've sat in ~/upload for
awhile, as a staged process, and, in particular, you're as certain as
you can be that the files are not malicious.
> Also, if you have any alternatives, please let me know. But remember I
> can't change ownership or group names.
Your files/directories are owned by 'loginname'
Let's assume, for the sake of argument, that the Apache User (which is
what runs PHP) is 'www-runner'
It's often 'nobody', or 'www', or 'apache', or something similar, but
we'll use 'www-runner' as an example here.
Here is one thing you can do:
Step 1.
TEMPORARILY make your new 'upload' directory be 777
chmod 777 ~/upload
Step 2.
Write a PHP script to create a directory inside ~/upload for your
specific application:
<?php
umask('022'); //So the new directory will be chmod 755
//You may want to use '027' to achieve 750
//This will mean ONLY 'www-runner' can see what's in the directory
mkdir("/full/path/to/your/home/directory/upload/foo_images") or
die("Can't make foo_images");
?>
Surf to the PHP script above.
Because you surfed there, that script will run as the PHP User
'www-runner' (or whatever it is on your server)
Step 3.
Change your upload directory back to some sane settings.
chmod 755 ~/upload
Step 4.
If you now do:
ls -als ~/upload
you will see that you have made Apache/PHP create a directory owned by
'www-runner' which is correctly set at 755
You also should do this to be 100% certain nobody snuck something in
there during the brief period while it was 777, as unlikely as that
is.
This does not, of course, COMPLETELY eliminate access to your data --
Most shared hosting services have the same PHP user for all customers.
So if other customers write a PHP script to look at your
~/upload/foo_images, they will be able to see what is in there, and
even change it.
There's really no way to fix that unless your host creates a different
PHP User for each customer, and runs a separate pool of HTTP servers
for each -- which reduces the number of customers they can cram onto
one box, since the sharing of Apache children and other resources is
fragmented.
So most hosts don't do this, as it cuts into their bottom line, and
very very very few people shopping for a webhost have this Feature on
their shopping list -- and if they did, even fewer webhosts have this
Feature on their bullet-point list where they describe their package.
Which is a pity.
Maybe we just need a really cool-sounding Marketing bullet-point NAME
for this, so the good hosts have something to point to on their
bullet-point for potential customers. :-)
Anyway, the above process *DOES* keep out the casual user from a
command-line (shell) since they are not 'www-runner' ; they are
'loginname2' or somesuch.
Now, of course, you have all these images that aren't in the
public_html, so you can't make an IMG tag to get to them.
You could write a PHP script to display images. There are a few
zillion examples out there, but the simplest script would be:
<?php
$filename = $_GET['filename'];
readfile("/full/path/to/your/home/dir/upload/foo_images/$filename");
?>
If you want to have more browser-compatibility with ancient and very
broken browsers, you can use the PATH_INFO trick I've posted on
php-general a few times.
You could also run some quick checks in this script to be certain that
the image you are sending out is legitimate.
You could, for example, check:
1. Is the image in a list of known uploaded images in your database?
This means that somebody else on your shared server would have to hack
into your database somehow *AND* get an image into that directory, all
without going through your formal upload process, to get something
that bypasses your Security check-points.
2. Does the image return reasonable values from
http://php.net/getimagesize
This would make sure that at least the first few dozen bytes of the
file LOOK like an image.
That doesn't guarantee that somebody couldn't craft a malicious file
whose first few dozen bytes LOOKED like a valid image, but that's much
harder than just crafting a malicious file and getting your server to
spit it out.
If your server is too busy to have PHP as a gate-keeper for images,
*AFTER* the upload has completed, and *AFTER* you have thoroughly
checked the file uploaded to be certain it is NOT malicious using
move_uploaded_file and basic tests/checks above, you can move it with
http://php.net/rename from the upload directory to
~/public_html/uploaded_safe_images or something.
You might also want to run it through image magick (aka 'convert') to
make a thumbnail, just to make sure that the whole image "seems" valid
enough that it can be processed -- Even if you just throw away the
thumbnail, the fact that Image Magick was able to process the whole
image gives you a very good probability that it's not a malicious
file.
The point of all this is to make sure you examine the images as
carefully as you can before those images get into your public website,
or get spit out by your server via PHP as if they were valid images.
The downside is that images that "seem" to be valid, to the Gimp, to
the browser, etc, may very well be "damaged" in some non-obvious way
that makes Image Magick or getimagesize "hiccup" -- This usually
occurs because the image isn't completely valid, but Gimp and the
browser are more forgiving.
Or, in an extreme example, less experienced users might take an AOL
"ART" format image, change the extension to "jpg" and it "works" in
some browsers and for some image editors.
Mainly because the "ART" format is nothing more than a
thinly-disguised wrapper around a JPEG or a GIF, whichever is smaller.
To save a few bytes on their caching servers (ugh!) AOL converts each
GIF/JPEG to a JPEG/GIF and takes the smaller file size, and crams it
into an "ART" file format they made up out of thin air. The only way
to un-package an "ART" file I am aware of is to install AOL (blech!)
and then run it, and use the close box to dismiss the "logon" dialog,
and then you'll have a Tools menu or somesuch you can use to open,
edit, and "Save as..." the "ART" image to a real JPEG (or GIF).
I've personally also noticed that EXIF data sometimes seems to confuse
PHP, Image Magick, and getimagesize. This may be a versioning issue
where newer versions of everything would handle the EXIF data. But I
generally am quite happy to just strip out the EXIF data, which rarely
contains content I personally find useful in the first place.
You may not need to do all of this, of course -- If the only person
who uploads images is the site owner or trusted people, you probably
don't need to worry about them sabotaging their own site, and can just
blithely copy the images around without checking that they are valid,
though you still want to avoid 777 permsissions in your public_html,
or anywhere else, for that matter.
If, however, you have employees who might become former employees,
possibly even disgruntled former employees, and they are the ones
uploading the images, maybe you should do all this.
If you have an e-commerce site, and you are on a shared server, and
your PHP User is the same as other customers on that server, maybe you
shouldn't even allow uploaded images/files -- Or you should make your
tests of valid files be VERY stringent, or perhaps the process should
include a human review of each image to be certain it *IS* an image
before it gets moved into your public_html.
Security is not an on/off switch -- It's a gradient and a frame of mind.
You can't do this sort of thing as one-size-fits-all or even JUST
following "Standard Practices", though obviously you want to follow
the standards to some degree. You have to actually turn your brain on
and think. :-)
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
Hello
Sorry for this OT post but is there a c++ mailing list like this one?
~Pedro.
--- End Message ---
--- Begin Message ---
On Fri, August 26, 2005 5:55 am, Edward Vermillion wrote:
> Chris Shiflett wrote:
>
>> Because $_SERVER['SERVER_NAME'] can be manipulated by the user in
>> some
>> cases, you must consider $temp tainted at this point.
>>
>
> I was under the the impression that the non-'HTTP_*' keys in the
> $_SERVER array came from the server itself. Obvoiusly I'm wrong, but
> I'm
> curoius how 'SERVER_NAME' could be manipulated by the client. Is there
> anything in the $_SERVER array that *can* be considered safe?
Here is what little info I have in my brain on this topic... :-)
When your browser requests:
http://example.com/index.php
what really happens is a more like doing this from a command shell:
telnet example.com 80
[wait for a prompt, type the following]
GET /index.php HTTP/1.0
Host: example.com
[hit return again here]
This last one, the "Host:" headers, is used by VirtualHost settings in
Apache to determine which URL you actually want.
But there's nothing to stop Bad Guy from doing this:
telnet php.net 80
GET /index.php HTTP/1.0
Host: example.com
At that point, if php.net responds at all, I *THINK*
$_SERVER['SERVER_NAME'] might, depending on Apache configuration, be
'example.com'
Or maybe not.
But when you stop to think about all the sites that are hosted on
multiple server farm setups, where a single domain is actually
serviced by an army of computers due to the sheer volume, you realize
that the 'SERVER_NAME' cannot POSSIBLY be the actual honest-to-god
there-is-only-one IP address of a single computer that is responding.
So odds are really good that in *SOME* situations,
$_SERVER['SERVER_NAME'] is not particularly reliable.
That may not be your situation ; It might be 100% reliable in YOUR
situation.
But do you really want to write code that might maybe someday get
thrown into a different situation that has vulnerabilities in it?
Disclaimer: I really have no idea how it could harm you, but if Chris
Shifflett warns against it, don't do it. :-)
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
Richard Lynch wrote:
Disclaimer: I really have no idea how it could harm you, but if Chris
Shifflett warns against it, don't do it. :-)
That was the assumption I was running under, which is why I was very
curious about it. ;)
Thanks for the explanation. I'm still not 100% on how a request for
someothersite.com would be directed to mysite.com, outside of a server
glitch or mis-configuration. But a server glitch is something to watch
out for any way.
So to paraphrase, "Is nothing safe anymore?". :D
--- End Message ---
--- Begin Message ---
On Fri, August 26, 2005 2:53 am, Jasper Bryant-Greene wrote:
> Adrian Cid Almaguer wrote:
>> You can find the IP and find with it the name.
>
> Certainly, you can. But do you realise what sort of slowdown doing a
> DNS
> lookup for (I am assuming here) every request would cause? Better to
> store the IPs and run some sort of tool on the logs later to get the
> names, maybe at a time when there's hardly any load on the server
Not only when there's a lower load on the server, but also...
A) On a different machine entirely, dedicated to DNS lookups
B) Using a tool that caches DNS results, so it doesn't lookup the same
IP address 1,000 times
DNS lookups usually (by default) take 30 seconds to time-out. You
really don't want every page on your site to take 30 seconds to find
out that some dial-up user has no domain name for their IP address
because there simply is no domain name for that IP.
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
On Fri, August 26, 2005 12:32 am, Chris Shiflett wrote:
> Of course, if you ever see a news story that describes PHP as a web
> service protocol, you probably want to stop reading immediately. :-)
The actual text is:
"...in a Web service protocol FOR PHP"
^^^
[emphasis mine]
The subject of the sentence is XMLRPC, and thus it does not
technically call PHP a "web service protocol" -- It labels XMLRPC as a
"web service protocol" which, in my limited understanding of RPC,
would not be considered inaccurate.
Granted, the article is plastered with PHP all over it, to garner
attention, when the Truth is that the flaw is in older versions of
XMLRPC.
Granted, the sentence construction throughout is very carefully
constructed to blame PHP while being technically correct in
assignation of blame on XMLRPC to the careful reader.
Granted the same bug would presumably manifest in XMLRPC for any other
language using that same code-base.
Still, it DOES seem to be technically correct, and has useful
information such as A) an upgrade to correct the issue B) credits to
the people who worked to find and fix the problem.
Seems like I've seen a LOT worse anti-PHP articles.
PS To the original poster: Forget trying to convince your school
admin to install PHP. Rent space on a decent PHP host, and put a
re-direct page in your school's computer to your REAL site. Make your
site infinitely better than everybody else in your school. The problem
will then solve itself.
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
On Thu, August 25, 2005 9:54 pm, Chris Shiflett wrote:
> Proper filtering is necessarily tedious. There is no way to filter a
> last name, a server name, a file name, an IP address, a ZIP code, and
> a
> comment with the same function. Those who try wind up creating a
> "lowest
> common denominator" filtering function, or they confuse filtering with
> escaping (as demonstrated by some of the replies).
>
> As a good friend of mine likes to say, you have to get your hands
> dirty.
Can anybody point to a good resource of a collection of filtering for
common inputs such as those listed by Chris above?...
I've searched for that and generally found one of two things:
1. Nothing useful.
2. A system so baroque and complex and with so much other baggage, it
would be impossible to integrate. See 1.
I'm looking more for code snippets or specific Regex functions for
each item, rather than a monolithic Borg-like "filtering package" and
have never one I liked.
That could be mostly my fault due to peculiar requirements, but there
it is.
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
On Thu, August 25, 2005 2:38 pm, George B wrote:
>> mysql_query('SELECT * FROM table ORDER BY increment_field DESC');
Remember when I told you that you should consistently use:
mysql_query(...) or die(mysql_error());
so that MySQL would TELL you what the error was?
I meant it when I said that.
Because otherwise you're going to post to this list EVERY time you
make a simple mistake in SQL, and people will stop ignoring you
because you don't listen to what we tell you :-)
> If I do that... then i get this error
> Warning: mysql_fetch_array(): supplied argument is not a valid MySQL
> result resource in myfile name on line 30
>
> and on line 30 it says
>
> while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
Although it's also possible in this case that you simply didn't put:
$result = mysql_query(...);
so $result has *NOTHING* in it.
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
On Thu, August 25, 2005 1:05 pm, Rory Browne wrote:
> At the risk of making a complete and utter ass of myself, I'm going to
> disagree with Richard.
>
> I'm going to justify this, by the fact that file_get_content function
> is written in C, and performs function required, that is currently
> performed by wget.
I may be reading more into it than was there, but I *THOUGHT* Michelle
was using wget to not just snag one URL, but all the crap (images,
JavaScript, CSS) required to render that URL, but not the links to
external sites/resources.
That URL computation, with absolute and relative, and domain names,
and sub-domains, and which resources are needed, and snarfing all of
the ones you need, but not the other ones, is what I wouldn't try to
re-invent in PHP, when wget does it *SO* well.
If you only need the contents of ONE URL, file_get_contents is a beauty.
If those contents require SSL or Cookie access, http://php.net/curl is
your answer.
If you need, as I believe Michelle does, to suck down all the relevant
junk from a whole page of HTML, I still believe wget +
http://php.net/exec is going to out-perform (not to mention be MUCH
easier to maintain) a PHP solution that does all that.
--
Like Music?
http://l-i-e.com/artists.htm
--- End Message ---
--- Begin Message ---
Joseph Oaks wrote:
Guys I'm doing some research trying to find a good PHP based CMS. As
there a quite a few, I would really like to get your opinions so I can
narrow the search down.
If you don't mind non-opensource but php based you could take
a look at:
http://www.commandprompt.com/products/cms
We were using Webedit Pro, but have found it a pain not to be able to
use Firefox with it.
Thanks for your input.
Trell
--- End Message ---
--- Begin Message ---
Joshua D. Drake wrote:
Joseph Oaks wrote:
Guys I'm doing some research trying to find a good PHP based CMS. As
there a quite a few, I would really like to get your opinions so I can
narrow the search down.
If you don't mind non-opensource but php based you could take
a look at:
http://www.commandprompt.com/products/cms
This question comes up quite often on this list. Try the following
website, which lets you try out most of the CMSs live on the website.
Personally I have had very good experience with Drupal, but others have
had difficulties getting it to work. YMMV.
http://www.opensourcecms.com/
Disclaimer: unlike the previous poster, I don't have a vested interest
in giving you this link...
--
Jasper Bryant-Greene
Freelance web developer
http://jasper.bryant-greene.name/
If you find my advice useful, please consider donating to a poor
student! You can choose whatever amount you think my advice was
worth to you. http://tinyurl.com/7oa5s
--- End Message ---
--- Begin Message ---
I've made a site with 5 sites in it and has about 6 MySQL/PHP News
databases. A while back I tried to use drop-down combo boxes to make a
single page that linked all 6 news scripts so I could pick one from the
drop-down enter the news and hit submit to add it to the site. The down side
is that it didn't work and deactivated the submit button. Is there a way to
make a drop-down combo box so that when I pick the item name it loads the
said page under the combo box and then lets you submit and pick another one
if you need to post to another database. I have 6 scripts that post to each
database. Any help, code, or advice would be greatly appreciated.
--Death Gauge
"How do you gauge your death?!"
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today - it's FREE!
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
--- End Message ---
--- Begin Message ---
Shafiq Rehman <[EMAIL PROTECTED]> writes:
> Hi all,
>
> Thanx to all of you. My server is running on Linux and there is not any
> phpbb running on it. If vulnerability is in my code.. Is there any way that
> I can find the buggy code on my server which allowed that trojan to write
> into all the index files.
>
> I analyzed the apache logs but did not found any thing wrong. My server is
> protected with firewar and only port 80 is opened.
- If you have a backup of your data (which was taken before you detected
the crack on your server), it would be a good idea to reload linux on
your box and populate it with the sane data.
- How did you analyze your apache logs ?
- Check out
http://public.yahoo.com/~radwin/talks/one-year-of-php-oscon2003.htm
especially the "security" part.
--
Raj Shekhar
blog : http://rajshekhar.net/blog home : http://rajshekhar.net
Disclaimer : http://rajshekhar.net/disclaimer
--- End Message ---
--- Begin Message ---
Death Gauge wrote:
I've made a site with 5 sites in it and has about 6 MySQL/PHP News
databases. A while back I tried to use drop-down combo boxes to make a
single page that linked all 6 news scripts so I could pick one from the
drop-down enter the news and hit submit to add it to the site. The down
side is that it didn't work and deactivated the submit button. Is there
a way to make a drop-down combo box so that when I pick the item name it
loads the said page under the combo box and then lets you submit and
pick another one if you need to post to another database. I have 6
scripts that post to each database. Any help, code, or advice would be
greatly appreciated.
--Death Gauge
"How do you gauge your death?!"
_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today - it's
FREE! http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/
Maybe try a bit of XmlHTTPRequest and some Javascript. When the first
item is selected (and maybe a submit button is pressed) it goes to the
XmlHTTPRequest script, gets the data from a php script and echos the
output. I'm only a beginner on XmlHTTPRequest, so I can't help you
code-wise. Sorry.
--- End Message ---