# 海豚cms(cookie欺骗可被绕过登录)

**URL:** <https://forum.90sec.com/t/topic/855>\
**Category:** 代码审计\
**Created:** [2020 年3 月 10 日 03:58 UTC](https://forum.90sec.com/t/topic/855 "2020-03-10T03:58:50Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

作者： ![Joseph](https://forum.90sec.com/letter_avatar_proxy/v4/letter/j/dc4da7/32.png) [@Joseph](https://forum.90sec.com/u/Joseph)\
发布日期： [2020 年3 月 10 日 03:58 UTC](https://forum.90sec.com/t/topic/855/1 "2020-03-10T03:58:50Z")

</div>

漏洞分析

```php
public function signout()
......此处代码省略
session(null);
cookie('uid', null);
cookie('signin_token', null);
$this->redirect('signin');
}

```

主要我们看在执⾏signout退出操作的时候对session以及cookie中对uid与signin\_token进⾏了清  
空,⽬前猜测signin\_token可能⽤于控制登陆,搜⼀下都有哪些地⽅使⽤

```php
function is_signin()
{
$user = session('user_auth');
if (empty($user)) {
// 判断是否记住登录
if (cookie('?uid') && cookie('?signin_token')) {
$UserModel = new User();
$user = $UserModel::get(cookie('uid'));
if ($user) {
$signin_token = data_auth_sign($user['username'].$user['id'].$user['last_login_time']);
if (cookie('signin_token') == $signin_token) {
// ⾃动登录
$UserModel->autoLogin($user);
return $user['id'];
}
}
};
return 0;
}else{
return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
}
}

```

检测是否登陆 ,当session的user\_auth为空时则⾛cookie验证流程,通过cookie中的uid获取具体  
的user信息,再通过data\_auth\_sign⽣成sign值

```php
function data_auth_sign($data = [])
{
// 数据类型检测
if(!is_array($data)){
$data = (array)$data;
}
// 排序
ksort($data);
// url编码并⽣成query字符串
$code = http_build_query($data);
// ⽣成签名
$sign = sha1($code);
return $sign;
}

```

就是很常规的拼接sha1⽣成签名

```php
if (cookie('signin_token') == $signin_token) {
// ⾃动登录
$UserModel->autoLogin($user);
return $user['id'];
}

```

这是很重要的⼀段,当cookie的值与⽣成出的签名符合时。则进⼊autoLogin⾃动登陆

```php
public function autoLogin($user, $rememberme = false)
{
// 记录登录SESSION和COOKIES
$auth = array(
'uid' => $user->id,
'group' => $user->group,
'role' => $user->role,
'role_name' => Db::name('admin_role')->where('id', $user->role)->value('name'),
'avatar' => $user->avatar,
'username' => $user->username,
'nickname' => $user->nickname,
'last_login_time' => $user->last_login_time,
'last_login_ip' => get_client_ip(1),
);
session('user_auth', $auth);
session('user_auth_sign', data_auth_sign($auth));
// 保存⽤户节点权限
if ($user->role != 1) {
$menu_auth = Db::name('admin_role')->where('id', session('user_auth.role'))->value('menu_auth');
$menu_auth = json_decode($menu_auth, true);
if (!$menu_auth) {
session('user_auth', null);
session('user_auth_sign', null);
$this->error = '未分配任何节点权限！';
return false;
}
}
// 记住登录
if ($rememberme) {
$signin_token = $user->username.$user->id.$user->last_login_time;
cookie('uid', $user->id, 24 * 3600 * 7);
cookie('signin_token', data_auth_sign($signin_token), 24 * 3600 * 7);
}
return $user->id;
}

```

直接将通过uid查询出来的user信息传⼊并启⽤有效的session，导致⽤户可在cookie许可的情况下直  
接登陆。再回顾看看技术的难点在哪⾥

```php
$user = $UserModel::get(cookie('uid'));
if ($user) {
$signin_token = data_auth_sign($user['username'].$user['id'].$user['last_login_time']);

```

uid可控，username以及id不可控，但是我们知道数据库排序是递增的，所以⼀般我们uid为1⼤多数的  
id都是为1，⽽username很好解决，因为海豚拥有⾃身的⼀个问题  
 ![image](https://forum.90sec.com/uploads/default/original/2X/3/3e250b4394ccb6b8fef1462ca7bd790e93b4dd0d.png)  
当输⼊不存在当⽤户名时会进⾏友好提示，默认安装时admin最默认管理员⽤户名并且id为1以及uid为1  
所以当admin存在的时候，我们的uid以及id以及username均已知。未知的则是last\_login\_time。  
我们跟⼀下login看last\_login\_time如何⽣成

```php
$user['last_login_time'] = request()->time();
$user['last_login_ip'] = request()->ip(1);
if ($user->save()) {
// ⾃动登录
return $this->autoLogin($this::get($uid), $rememberme);
}

```

跟⼊reques下的time

```php
public function time($float = false)
{
return $float ? $this->server('REQUEST_TIME_FLOAT') : $this->server('REQUEST_TIME');
}

```

获取登陆成功时请求时间并且执⾏save进⾏user表登陆⽤户last\_login\_time值更新。

---

<div class="post-metadata">

作者： ![1057878607](https://forum.90sec.com/letter_avatar_proxy/v4/letter/1/a88e57/32.png) [@1057878607](https://forum.90sec.com/u/1057878607)\
发布日期： [2020 年3 月 11 日 03:46 UTC](https://forum.90sec.com/t/topic/855/2 "2020-03-11T03:46:25Z")

</div>

> [@Joseph](#):
>
> last\_login\_time

这个时间戳就很难受，利用感觉有点困难啊

---

<div class="post-metadata">

作者： ![Joseph](https://forum.90sec.com/letter_avatar_proxy/v4/letter/j/dc4da7/32.png) [@Joseph](https://forum.90sec.com/u/Joseph)\
发布日期： [2020 年3 月 11 日 09:42 UTC](https://forum.90sec.com/t/topic/855/3 "2020-03-11T09:42:03Z")

</div>

是有点难受的！不过这种点的利用还是得看目标站是什么类型的，如果是那种经常维护的站！就爆破当天的时间就行了！还是有希望的！

---

<div class="post-metadata">

作者： ![1057878607](https://forum.90sec.com/letter_avatar_proxy/v4/letter/1/a88e57/32.png) [@1057878607](https://forum.90sec.com/u/1057878607)\
发布日期： [2020 年3 月 12 日 03:28 UTC](https://forum.90sec.com/t/topic/855/5 "2020-03-12T03:28:28Z")

</div>

哈哈，佛系日站

---

<div class="post-metadata">

作者： ![Joseph](https://forum.90sec.com/letter_avatar_proxy/v4/letter/j/dc4da7/32.png) [@Joseph](https://forum.90sec.com/u/Joseph)\
发布日期： [2020 年3 月 15 日 02:55 UTC](https://forum.90sec.com/t/topic/855/6 "2020-03-15T02:55:14Z")

</div>

差不多吧！一般特殊情况特殊对待，真没点可以突破的时候，这种点还是会考虑上
