环境搭建
要求php版本5.x,否则smarty无法正常渲染
目录结构
index.php
1 2 3
| define("IN_BLUE",true); require_once('include/common.inc.php'); require_once(BLUE_ROOT.'include/index.fun.php');
|
跟进一下common.inc.php
这里配置了全局过滤
1 2 3 4 5 6 7
| if(!get_magic_quotes_gpc()) { $_POST = deep_addslashes($_POST); $_GET = deep_addslashes($_GET); $_COOKIES = deep_addslashes($_COOKIES); $_REQUEST = deep_addslashes($_REQUEST); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function deep_addslashes($str) { if(is_array($str)) { foreach($str as $key=>$val) { $str[$key] = deep_addslashes($val); } } else { $str = addslashes($str); } return $str; }
|
里面除了一些小功能点和模板配置就是这段登录鉴权代码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| if(!$_SESSION['user_id']) { if($_COOKIE['BLUE']['user_id'] && $_COOKIE['BLUE']['user_name'] && $_COOKIE['BLUE']['user_pwd']) { if(check_cookie($_COOKIE['BLUE']['user_name'], $_COOKIE['BLUE']['user_pwd'])) { update_user_info($_COOKIE['BLUE']['user_name']); } } else if($_COOKIE['BLUE']['user_name']) { $user_name = $_COOKIE['BLUE']['user_name']; $user = $db->query("SELECT COUNT(*) AS num FROM ".table('user')." WHERE user_name='$user_name'"); if($user['num'] == 1) { $active = 0; } else { $active = 1; } } else { setcookie("BLUE[user_id]", '', -86400, $cookiepath, $cookiedomain); setcookie("BLUE[user_name]", '', -86400, $cookiepath, $cookiedomain); setcookie("BLUE[user_pwd]", '', -86400, $cookiepath, $cookiedomain); } } $smarty->assign('user_name', $_SESSION['user_name']);
if ($_CFG['gzip'] == 1 && function_exists('ob_gzhandler')) { ob_start('ob_gzhandler'); } else { ob_start(); }
|
check_cookie
1 2 3 4 5 6 7
| function check_cookie($user_name, $pwd){ global $db, $_CFG; $sql = "SELECT pwd FROM ".table('user')." WHERE user_name='$user_name'"; $user = $db->getone($sql); if(md5($user['pwd'].$_CFG['cookie_hash']) == $pwd) return true; else return false; }
|
getone($sql);
1 2 3 4 5
| function getone($sql, $type=MYSQL_ASSOC){ $query = $this->query($sql,$this->linkid); $row = mysql_fetch_array($query, $type); return $row; }
|
query($sql,$this->linkid);
1 2 3 4 5 6 7
| function query($sql){ if(!$query=@mysql_query($sql, $this->linkid)){ $this->dbshow("Query error:$sql"); }else{ return $query; } }
|
$_CFG
来自get_config
,可见这里的$_CFG['cookie_hash']
来自数据库原始的config
表,拿不到(后面宽字节可以注出来:hear_no_evil:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function get_config() { global $db; $config_arr = array(); $config_arr = read_static_cache('config.cache'); if($config_arr === false) { $sql = "SELECT * FROM ".table('config'); $arr = $db->getall($sql); foreach($arr as $key=> $val) { $config_arr[$val['name']] = $val['value']; } write_static_cache('config.cache', $config_arr); } return $config_arr; }
|
admin
进index.php
1
| require_once(dirname(__FILE__) . "/include/common.inc.php");
|
common.inc.php
存在admin
鉴权操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| if(empty($_SESSION['admin_id']) && $_REQUEST['act'] != 'login' && $_REQUEST['act'] != 'do_login' && $_REQUEST['act'] != 'logout'){ if($_COOKIE['Blue']['admin_id'] && $_COOKIE['Blue']['admin_name'] && $_COOKIE['Blue']['admin_pwd']){ if(check_cookie($_COOKIE['Blue']['admin_name'], $_COOKIE['Blue']['admin_pwd'])){ update_admin_info($_COOKIE['Blue']['admin_name']); } }else{ setcookie("Blue[admin_id]", '', 1, $cookiepath, $cookiedomain); setcookie("Blue[admin_name]", '', 1, $cookiepath, $cookiedomain); setcookie("Blue[admin_pwd]", '', 1, $cookiepath, $cookiedomain); echo '<script type="text/javascript">top.location="login.php?act=login";</script>'; exit(); } }elseif($_SESSION['admin_id']){ update_admin_info($_SESSION['admin_name']); }
|
check_cookie
还是过不去
文件包含
user.php
1 2 3 4 5 6 7 8 9 10
| elseif ($act == 'pay'){ include 'data/pay.cache.php'; $price = $_POST['price']; $id = $_POST['id']; $name = $_POST['name']; if (empty($_POST['pay'])) { showmsg('对不起,您没有选择支付方式'); } include 'include/payment/'.$_POST['pay']."/index.php"; }
|
deep_addslashes
转义了%00
1
| php<5.3.4 magic_quote为OFF
|
那么可用长度截断
1 2 3
| windows下目录路径最大长度为256字节 Linux下目录最大长度为4096字节 php<5.2.9
|
可以配合头像上传包含图片马拿shell了
文件上传
user.php
1 2 3 4
| if(isset($_FILES['face_pic2']['error']) && $_FILES['face_pic2']['error'] == 0){ $face_pic = $image->img_upload($_FILES['face_pic2'],'face_pic'); } $face_pic = empty($face_pic) ? '' : $face_pic;
|
img_upload($_FILES['face_pic2'],'face_pic');
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| private $allow_image_type = array('image/jpeg', 'image/gif', 'image/png', 'image/pjpeg'); private $extension_name_arr = array('jpg', 'gif', 'png', 'pjpeg');
function img_upload($file, $dir = '', $imgname = ''){ if(empty($dir)){ $dir = BLUE_ROOT.DATA.UPLOAD.date("Ym")."/"; }else{ $dir = BLUE_ROOT.DATA.UPLOAD.$dir."/"; } if(!in_array($file['type'],$this->allow_image_type)){ echo '<font style="color:red;">不允许的图片类型</font>'; exit; } if(empty($imgname)){ $imgname = $this->create_tempname().'.'.$this->get_type($file['name']); } if(!file_exists($dir)){ if(!mkdir($dir)){ echo '<font style="color:red;">上传过程中创建目录失败</font>'; exit; } } $imgname = $dir . $imgname;
if($this->uploading($file['tmp_name'], $imgname)){ return str_replace(BLUE_ROOT, '', $imgname); }else{ echo '<font style="color:red;">上传图片失败</font>'; exit; }
}
|
这里限制了文件后缀%00截断
或者用长度截断了
任意文件删除
link.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| elseif($act == 'do_edit'){ $link_name = !empty($_POST['link_name']) ? trim($_POST['link_name']) : ''; $link_site = !empty($_POST['link_site']) ? trim($_POST['link_site']) : ''; $show_order = !empty($_POST['show_order']) ? intval($_POST['show_order']) : 0;
if (!empty($_POST['link_logo'])){ if (strpos($_POST['link_logo'], 'http://') != false && strpos($_POST['link_logo'], 'https://') != false){ showmsg('只支持本站相对路径地址'); } else{ $link_logo = trim($_POST['link_logo']); } }else{ if(file_exists(BLUE_ROOT.$_POST['link_logo2'])){ @unlink(BLUE_ROOT.$_POST['link_logo2']); } }
|
$_POST['link_logo2']
1 2
| /admin/link.php link_logo2=/../../../../../../aaa.txt&act=do_edit
|
文件读取/写入
tpl_manager.php
主要看这两块
任意文件读取
1 2 3 4 5 6 7 8 9 10 11 12
| elseif($act == 'edit'){ $file = $_GET['tpl_name']; if(!$handle = @fopen(BLUE_ROOT.'templates/default/'.$file, 'rb')){ showmsg('打开目标模板文件失败'); } $tpl['content'] = fread($handle, filesize(BLUE_ROOT.'templates/default/'.$file)); $tpl['content'] = htmlentities($tpl['content'], ENT_QUOTES, GB2312); fclose($handle); $tpl['name'] = $file; template_assign(array('current_act', 'tpl'), array('编辑模板', $tpl)); $smarty->display('tpl_info.htm'); }
|
任意文件写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| elseif($act == 'do_edit'){ $tpl_name = !empty($_POST['tpl_name']) ? trim($_POST['tpl_name']) : ''; $tpl_content = !empty($_POST['tpl_content']) ? deep_stripslashes($_POST['tpl_content']) : ''; if(empty($tpl_name)){ return false; } $tpl = BLUE_ROOT.'templates/default/'.$tpl_name; if(!$handle = @fopen($tpl, 'wb')){ showmsg("打开目标模版文件 $tpl 失败"); } if(fwrite($handle, $tpl_content) === false){ showmsg('写入目标 $tpl 失败'); } fclose($handle); showmsg('编辑模板成功', 'tpl_manage.php'); }
|
deep_stripslashes($_POST['tpl_content'])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function deep_stripslashes($str) { if(is_array($str)) { foreach($str as $key => $val) { $str[$key] = deep_stripslashes($val); } } else { $str = stripslashes($str); } return $str; }
|
stripslashes:
返回一个去除转义反斜线后的字符串(' 转换为 ‘ 等等)。双反斜线(\)被转换为单个反斜线(**)
啊这….直接把$_POST = deep_addslashes($_POST);
的作用清除了,这不随便写?
果然没有被转义
xss
ad_js.php
1 2 3 4 5 6 7 8 9 10 11 12
| define('IN_BLUE', true); require_once dirname(__FILE__) . '/include/common.inc.php';
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : ''; if(empty($ad_id)) { echo 'Error!'; exit(); }
$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
|
1
| Error:Query error:SELECT * FROM blue_ad WHERE ad_id =<script>alert(1)</script><br><br>
|
user.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| elseif ($act == 'do_add_news') { include_once 'include/upload.class.php'; $image = new upload(); $title = !empty($_POST['title']) ? htmlspecialchars(trim($_POST['title'])) : ''; $color = !empty($_POST['color']) ? htmlspecialchars(trim($_POST['color'])) : ''; $cid = !empty($_POST['cid']) ? intval($_POST['cid']) : ''; if(empty($cid)){ showmsg('新闻分类不能为空'); } $author = !empty($_POST['author']) ? htmlspecialchars(trim($_POST['author'])) : $_SESSION['admin_name']; $source = !empty($_POST['source']) ? htmlspecialchars(trim($_POST['source'])) : ''; $content = !empty($_POST['content']) ? filter_data($_POST['content']) : ''; $descript = !empty($_POST['descript']) ? mb_substr($_POST['descript'], 0, 90) : mb_substr(html2text($_POST['content']),0, 90); if(isset($_FILES['lit_pic']['error']) && $_FILES['lit_pic']['error'] == 0){ $lit_pic = $image->img_upload($_FILES['lit_pic'],'lit_pic'); } $lit_pic = empty($lit_pic) ? '' : $lit_pic; if(!empty($lit_pic)){ $lit_pic = $image->small_img($lit_pic, 200, 115); }
|
filter_data($_POST['content'])
1 2 3 4 5
| function filter_data($str) { $str = preg_replace("/<(\/?)(script|i?frame|meta|link)(\s*)[^<]*>/", "", $str); return $str; }
|
可以用a,img标签
1
| <a href=javascript:alert(1)>yunying</a>
|
1
| <img src=1 onerror=alert(1)>
|
注册
注册页面的邮箱用bp绕过前台也可以打xss
SQL注入探索
无引号型
uploads/install/include/common.inc.php
下用了GBK,全局查找一下包含它的文件,发现只有在安装环境时有…….没啥用(后面发现没用的是我)
1 2 3 4
| define('BLUE_PRE','blue_'); define('BLUE_CHARSET', 'gb2312'); define('BLUE_VERSION', 'v1.6'); define('BLUE_UPDATE_NO', '20100210');
|
无单引号保护那就意味着不需要闭合。。。忽然有了希望
ad_js.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| define('IN_BLUE', true); require_once dirname(__FILE__) . '/include/common.inc.php';
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : ''; if(empty($ad_id)) { echo 'Error!'; exit(); } $ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id); if($ad['time_set'] == 0) { $ad_content = $ad['content']; } else { if($ad['end_time'] < time()) { $ad_content = $ad['exp_content']; } else { $ad_content = $ad['content']; } } $ad_content = str_replace('"', '\"',$ad_content); $ad_content = str_replace("\r", "\\r",$ad_content); $ad_content = str_replace("\n", "\\n",$ad_content); echo "<!--\r\ndocument.write(\"".$ad_content."\");\r\n-->\r\n";
|
正常注入就可以
宽字节注入
admin.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| elseif($act == 'do_login'){ $admin_name = isset($_POST['admin_name']) ? trim($_POST['admin_name']) : ''; $admin_pwd = isset($_POST['admin_pwd']) ? trim($_POST['admin_pwd']) : ''; $remember = isset($_POST) ? intval($_POST['rememberme']) : 0; if($admin_name == ''){ showmsg('用户名不能为空'); } if($admin_pwd == ''){ showmsg('用户密码不能为空'); } if(check_admin($admin_name, $admin_pwd)){ update_admin_info($admin_name); if($remember == 1){ setcookie('Blue[admin_id]', $_SESSION['admin_id'], time()+86400); setcookie('Blue[admin_name]', $admin_name, time()+86400); setcookie('Blue[admin_pwd]', md5(md5($admin_pwd).$_CFG['cookie_hash']), time()+86400); } }else{ showmsg('您输入的用户名和密码有误'); } showmsg('欢迎您 '.$admin_name.' 回来,现在将转向管理中心...', 'index.php'); }
|
check_admin($admin_name, $admin_pwd)
1 2 3 4 5 6 7 8 9 10 11 12 13
| function check_admin($name, $pwd) { global $db; $row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$name' and pwd = md5('$pwd')"); if($row['num'] > 0) { return true; } else { return false; } }
|
:smile:
尽管我的数据库显示UTF8但是网站配置数据库时设置的GB2312当然会在全局生效……
而且在index.php中的配置文件也设置了数据库GB2312
1 2 3 4
| $fp = @fopen(BLUE_ROOT . 'data/config.php', 'wb+'); if (!$fp){ install_showmsg('打开配置文件失败'); }
|