本章代码来之各种php的cms历史漏洞源码,供小伙伴们学习, 本次三题
//检测旧密码是否正确
if($password != '')
{
$oldpassword = md5(md5($oldpassword));
$r = $dosql->GetOne("SELECT `password` FROM `#@__member` WHERE `username`='$c_uname'");
if($r['password'] != $oldpassword)
{
ShowMsg(msg: '抱歉,旧密码错误!', gourl: '-1');
exit();
}
}
$sql = "UPDATE `#@__member` SET";
if($password != '')
{
$password = md5(md5($password));
$sql .= "password='$password',";
}
@$sql .= "question='$question', answer='$answer', cnname='$cnname', enname='$enname', sex='$sex', birthtype='$birthtype', birth_year='$birth_year', birth_month='$birth_month', birth_day='$birth_day', astro='$astro', bloodtype='$bloodtype', trade='$trade', live_prov='$live_prov', live_city='$live_city', live_country='$live_country', home_prov='$home_prov', home_city='$home_city', home_country='$home_country', cardtype='$cardtype', cardnum='$cardnum', intro='$intro', email='$email', qqnum='$qqnum', mobile='$mobile', telephone='$telephone', address_prov='$address_prov', address_city='$address_city', address_country='$address_country', address='$address', zipcode='$zipcode' WHERE id='$id' AND `username`='$c_uname'";
if($dosql->ExecNoneQuery($sql))
{
ShowMsg(msg: '资料更新成功', gourl: '?c=edit');
exit();
}
第一个if判断的作用是“判断用户提交的新密码是否为空”,在用户提交的新密码不为空的情况下,才会进行‘旧密码的比对’,如果提交的旧密码和数据库的查询结果不一致,代码退出执行结束。第二个if判断的作用仍为“判断用户提交的新密码是否为空”,在用户提交的新密码不为空的情况下,对新密码进行哈希运算,随后进行SQL语句的拼接
一定要password有值才可以吗?如果设置为空,你会惊奇地发现sql语句为我们准备了,而且其他的参数一定程度上可控,随后也执行了,if条件语句好像没那么重要!,————由此可能会引发两个漏洞
一是在不知道旧密码的情况下修改密码
? ? ? ? 新密码设置为空,绕过两个if。在之后sql语句中找一个可控参数用sql拼接的方式将password字段加上。完成所有字段的更新
二是越权,我们不对password的字段进行处理,而是在后面的sql语句中将cnnam改成其他用用户的(对应用户的id也改变),sql语句执行是不是就把别人的信息改了!
<?php
require '../../inc/zzz_class.php';
$backurl=getform('backurl','get');
$path =is_mobile() ? SITE_PATH.'wap/' : SITE_PATH;
$url =conf('runmode')==1 ? $path.'index.php?location=user&backurl='.$backurl.'&act=' : $path.'?location=user&backurl='.$backurl.'&act=' ;
if ((get_session('uid')>0)){
echo('document.write(" <a href='.$url.'userinfo><i class=\'ico login\'></i> 会员中心</a><a href='.$url.'loginout><i class=\'ico reg\'></i> 登出</a>")');
}else{
echo('document.write(" <a href='.$url.'login><i class=\'ico login\'></i> 登录</a><a href='.$url.'reg><i class=\'ico reg\'></i> 注册</a>")');
}
?>
追入getform函数发现$backur是get传参,为可控参数。拼接到$url中,打印回显到前端,造成XSS漏洞
原句 <a href='.$url.'login>
document.write(" <a href=/zzzphp_jb51/?location=user&backurl=123&act=login><i class='ico login'></i> 登录</a><a href=/zzzphp_jb51/?location=user&backurl=123&act=reg><i class='ico reg'></i> 注册</a>")
攻击输出1 οnmοuseοver=alert(/document.domain/) y=
document.write(" <a href=/zzzphp_jb51/?location=user&backurl=1 οnmοuseοver=alert(/d0cument.domain/) y=&act=login><i class='ico login'></i> 登录</a><a href=/zzzphp_jb51/?location=user&backurl=1 οnmοuseοver=alert(/d0cument.domain/) y=&act=reg><i class='ico reg'></i> 注册</a>")
浏览器在执行document.write的时候会适当地增加引号
<?php
require '../../../inc/zzz_admin.php';
$CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents("config.json")), true);
$action = safe_word(getform('action','get'));
$upfolder = safe_word(getform('upfolder','get'));
switch ($action) {
case 'config':
$result = json_encode($CONFIG);
break;
/* 上传图片 */
case 'uploadimage':
$result =tojson(upload($_FILES['upfile'],'image',$upfolder));
break;
/* 上传涂鸦 */
case 'uploadscrawl':
$upfile=getform('upfile','post');
$result =tojson(up_base64($upfile,$upfolder));
break;
/* 上传文件 */
case 'uploadfile':
$result =tojson(upload($_FILES['upfile'],'file',$upfolder));
break;
/* 上传视频 */
case 'uploadvideo':
$result =tojson(upload($_FILES['upfile'],'video',$upfolder));
break;
/* 列出图片 */
case 'listimage':
$size=safe_word(getform('size','get'));
$start=safe_word(getform('start','get'));
$uporder=safe_word(getform('uporder','get'));
$end = $start + $size;
$allowFiles=str_replace(",","|",conf('imageext'));
$path = UPLOAD_DIR.$upfolder.'/';
$files = getfiles($path, $allowFiles);
foreach($files as $k=>$v){
$sizes[$k] = $v['size'];
$times[$k] = $v['mtime'];
$names[$k] = $v['name'];
}
switch($uporder){
case'size1' : array_multisort($sizes,SORT_DESC,SORT_STRING, $files);break;
case'size2' : array_multisort($sizes,SORT_ASC,SORT_STRING, $files);break;
case'name1' : array_multisort($names,SORT_DESC,SORT_STRING, $files);break;
case'name2' : array_multisort($names,SORT_ASC,SORT_STRING, $files);break;
case'mtime2' : array_multisort($times,SORT_ASC,SORT_STRING, $files);break;
default : array_multisort($times,SORT_DESC,SORT_STRING, $files);break;
}
if (! count($files)) {
return json_encode(array(
"state" => "no match file",
"list" => array(),
"start" => $start,
"total" => count($files)
));
}
$len = count($files);
for ($i =$start,$list = array(); $i <= $len-1 && $i <= $end; $i ++) {
$list[] = $files[$i];
}
$result = json_encode(array(
"state" => "SUCCESS",
"list" => $list,
"start" => $start,
"total" => count($files)
));
break;
/* 列出文件 */
case 'listfile':
$result = getfiles();
break;
/* 抓取远程文件 */
case 'catchimage':
$source=getform('source','post');
$list = array();
$state='ERROR';
foreach ($source as $imgUrl) {
$info =down_url(safe_url($imgUrl),$upfolder);
if ($info['state']=="SUCCESS"){
$state="SUCCESS";
array_push($list, array(
"state" => "SUCCESS",
"title" => $info["title"],
"url" => $info["url"],
"source"=>$imgUrl
));
}else{
array_push($list, array(
"state" => $info['state'],
"title" => $info["msg"]
));
}
}
$result = json_encode(array(
'state' =>$state,
'list' => $list
));
break;
default:
$result = json_encode(array(
'state' => '请求地址出错'
));
break;
}
/* 输出结果 */
if (isset($_GET["callback"])) {
if (preg_match("/^[\w_]+$/", $_GET["callback"])) {
echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
} else {
echo json_encode(array(
'state' => 'callback参数不合法'
));
}
} else {
echo($result);
}
?重要逻辑代码
$action = safe_word(getform('action','get'));
safe_word // 安全过滤字符串,仅仅保留 [a-zA-Z0-9_]
getform //get得到action参数返回
switch ($action) { //判断action执行流
/* 抓取远程文件 */
case 'catchimage':
$source=getform('source','post');
$list = array();
$state='ERROR';
foreach ($source as $imgUrl) {
$info =down_url(safe_url($imgUrl),$upfolder);
if ($info['state']=="SUCCESS"){
$state="SUCCESS";
array_push($list, array(
"state" => "SUCCESS",
"title" => $info["title"],
"url" => $info["url"],
"source"=>$imgUrl
));
post得到source 值,根据后面的foreach判断$source可为数组
safe_url() *// 使用正则表达式匹配允许的字符,/[a-zA-Z0-9,.:=@?_\/\s]/u 默认最大长度255
down_url 从远程下载文件并保存到本地,
重点关注文件扩展名的处理,进入down_url
重点关注$file_ext = file_ext( $url ) ?: 'jpg'; //如果无法获取到扩展名则默认为'jpg
后面对扩展名做了检测
$allext=conf('imageext').','.conf('fileext').','.conf('videoext');
if(!in_array($file_ext,splits($allext,','))){
return array( 'msg' => '创建文件失败,禁止创建'.$file_ext.'文件!', 'state' => 'ERROR', 'error' => 5 );
}
?后面一顿翻找最终找到了这个允许的全局类
//图片上传限制 'imageext'=>'jpg,jpeg,gif,png',
//附件上传限制 'fileext'=>'pdf,txt,doc,docx,xls,xlsx,zip,rar',
//视频上传限制 'videoext'=>'mp4,flv,swf',//请注意空间90%以上不允许上传视频,或不支持视频格式
这些文件都可以上传,有什么思考?
1.用pdf打xss,用swf打xss
2.用压缩包钓鱼,用docx钓鱼,压缩包炸弹
3.用文件打服务器空间
4.可以结合文件包含漏洞打入php马