zabbix身份验证流程解析&绕过身份验证的方法
2015-11-05 16:01
246 查看
由于实验室产品的监控模块的需求,需要绕过zabbix的验证模块,实现从二级平台到zabbix的无缝接入。
测试发现,zabbix的身份验证并不是想象的那么简单,为了实现功能,遂进行源码分析。
主要逻辑如下:
检查该用户登陆尝试次数是否超出限制
根据查询的userid验证用户权限,将页面是否允许访问存入guiAccess
登陆方式选择(ldap、数据库)
开始新的session: 生成sessionId,将(sessionId、userid、当前时间、激活状态)插入数据库
根据第3步的guiAccess判断是否结束并抛出异常
成功登陆后,清除访客的session
将新的sessionId存入cookie
对该次用户登录做审计
从数据库里删除该登出用户对应的所有状态为PASSIVE的session记录
将cookie中得到的这个sessionId对应的session记录的状态修改为PASSIVE
从cookie里删除该sessionId
然而,从一个静态URL想要绕过登陆直接跳转到zabbix的某个监控页面,肯定是不能走这个常规流程,所以,我们以zabbix的监控图表界面对应的charts.php代码来理清zabbix对于URL跳转这类请求的验证流程。
该函数位于
具体流程如下:
从cookie中取出
如果该sessionId不为空,根据这个sessionId查询出对应的用户userid、autologout字段和处于ACTIVE状态session的lastaccess字段,如果sessionId为空,以访客模式调用login函数并得到新的sessionId,该sessionId对应的GUEST特殊用户将不能通过后面的权限认证
如果步骤2没有查出记录,那么会报错
调用
如果查出的记录的
更新数据库中当前sessionId和userId对应的session记录的最近访问是时间(lassaccess)字段
检查该用户的页面访问权限(检查gui_access,与login流程的验证guiAccess一样)
将userid,sessionid,gui_access存入data变量中
如果gui_access为GROUP_GUI_ACCESS_DISABLED,即禁用,抛异常,退出。
将sessionId保存到cookie中
用sessionId为API设置验证令牌
分析得出结论,如果要实现在任何环境下的一次URL跳转都能成功以管理员的权限进入zabbix,关键在于以上流程的第2步,不能以访客模式进入zabbix,即需要让sessionId不为空且可用,自然得出的办法就是,提前保存好一个可用的sessionId到cookie中。
多番测试后,证实了以上方案是可行的,于是,实施方案如下:
手动在zabbix增加一个session记录,每次直接请求URL的时候,先调用一个自定义php,存入这个session的id,再继续访问,bingo!
后续发现问题,会回来更新。
测试发现,zabbix的身份验证并不是想象的那么简单,为了实现功能,遂进行源码分析。
zabbix常规登陆验证流程:
分析./include/classes/user/CWebUser.php中的login和logout可以了解到zabbix的常规验证流程。
主要逻辑如下:
login
查询出对应用户名密码的user对象检查该用户登陆尝试次数是否超出限制
根据查询的userid验证用户权限,将页面是否允许访问存入guiAccess
登陆方式选择(ldap、数据库)
开始新的session: 生成sessionId,将(sessionId、userid、当前时间、激活状态)插入数据库
根据第3步的guiAccess判断是否结束并抛出异常
成功登陆后,清除访客的session
将新的sessionId存入cookie
对该次用户登录做审计
logout
从cookie里得到sessionId从数据库里删除该登出用户对应的所有状态为PASSIVE的session记录
将cookie中得到的这个sessionId对应的session记录的状态修改为PASSIVE
从cookie里删除该sessionId
然而,从一个静态URL想要绕过登陆直接跳转到zabbix的某个监控页面,肯定是不能走这个常规流程,所以,我们以zabbix的监控图表界面对应的charts.php代码来理清zabbix对于URL跳转这类请求的验证流程。
URL跳转验证流程
包括chart.php的几乎每一个zabbix的展示页面的php代码都会在开头包含一个config.inc.php,且并无其他验证相关代码存在,
config.inc.php中只有一行主要代码
Z::getInstance()->run(),追踪到这个run函数里,就能找到疑似的验证流程入口
$this->authenticateUser()。
该函数位于
./include/classes/core/ZBase.php中。
checkAuthentication
ZBase.php中的函数,是对./include/classes/user/CWebUser.php中同名函数的封装,CWebUser.php中的checkAuthentication又是对zabbix API即
./include/classes/api/services/CUser.php中的同名函数的封装。
具体流程如下:
从cookie中取出
zbx_sessionid的值存入sessionId
如果该sessionId不为空,根据这个sessionId查询出对应的用户userid、autologout字段和处于ACTIVE状态session的lastaccess字段,如果sessionId为空,以访客模式调用login函数并得到新的sessionId,该sessionId对应的GUEST特殊用户将不能通过后面的权限认证
如果步骤2没有查出记录,那么会报错
Session terminated, re-login, please
调用
check_perm2system检查该用户的权限,若有问题,报错
No permissions for system access
如果查出的记录的
autologout> 0, 删除数据库中对应用户的过期的session
更新数据库中当前sessionId和userId对应的session记录的最近访问是时间(lassaccess)字段
检查该用户的页面访问权限(检查gui_access,与login流程的验证guiAccess一样)
将userid,sessionid,gui_access存入data变量中
如果gui_access为GROUP_GUI_ACCESS_DISABLED,即禁用,抛异常,退出。
将sessionId保存到cookie中
用sessionId为API设置验证令牌
分析得出结论,如果要实现在任何环境下的一次URL跳转都能成功以管理员的权限进入zabbix,关键在于以上流程的第2步,不能以访客模式进入zabbix,即需要让sessionId不为空且可用,自然得出的办法就是,提前保存好一个可用的sessionId到cookie中。
多番测试后,证实了以上方案是可行的,于是,实施方案如下:
手动在zabbix增加一个session记录,每次直接请求URL的时候,先调用一个自定义php,存入这个session的id,再继续访问,bingo!
后续发现问题,会回来更新。
相关文章推荐
- C#中Excel文件转换为SQLite文件并在Unity3D中读取遇到的一些坑
- 语法树
- jquery鼠标事件
- Eclipse生成jar文件
- AngularJS的directive(指令)配置选项说明
- EFI memory type
- 白盒测试
- html5 placeholder ie版本兼容
- 聚类算法实践(2)——谱聚类、Chameleon聚类
- EditText属性
- 我还在,只是
- java 多线程 实现窗口买票功能
- LNMP(linux+nginx+mysql+php)环境搭建
- 让spark运行在mesos上 -- 分布式计算系统spark学习(五)
- VS产生sdf和ipch文件太大处理方案
- 浅谈iOS开发的协议(protocol)和代理(delegate)
- angularJS常见问题汇总
- 字符串哈希模板
- Android开发中Bundle用法包裹数据
- 动画三 Android属性动画深入分析:让你成为动画牛人