前端时间在某社区看到有师傅发了,我就整理了一下,因为之前看过这套堡垒机的pythonweb,并把目前网上公开的漏洞分析了下,做个记录~~~
水平太cai,请大伙批评指正~~~
环境搭建(3.5.6-rc6版本)
在官网下载安装包,tar命令解压,进入目录,以管理员身份运行./setup.sh即可(直接enter选择默认路径)。
访问主机7190端口:
搭建环境遇到的问题:用的是centos7虚拟机搭建,遇到ping到主机却telnet不到7190端口的问题,查询资料后关闭centos7防火墙即可。
漏洞分析
逻辑缺陷
看webroot:
python的应用没怎么看过,不过应该是大同小异,路由结构在app/controller/__init__.py:看登录认证相关:
转到app.controller.auth.DoLoginHandler:
通过app.model.user.login判断返回信息,这里将username、password和oath参数带入,跟进app.model.user.login:
然后password判断(代码太长,没有展开):
逻辑缺陷在于,在用户密码password为空时,没有对应的控制逻辑,导致登录绕过。
正常请求的json为:
{"type":2,"username":"admin","password":"admin","captcha":"xcj9","oath":"","remember":false}
那么将password变为null,即可绕过:
{"type":2,"username":"admin","password":null,"captcha":"xcj9","oath":"","remember":false}
任意文件读取(后台)
在app.controller.audit.DoGetFileHandler中,对应路由为:
通过f参数获取filename信息:
跟踪filename:
filename直接就拼接到file,然后open:
但要满足下列条件:
if act is None or _type is None or rid is None or filename is None: self.set_status(400) # 400=错误请求 return self.write('invalid param, `rid` and `f` must present.') if act not in ['size', 'read']: self.set_status(400) return self.write('invalid param, `act` should be `size` or `read`.') if _type not in ['rdp', 'ssh', 'telnet']: self.set_status(400) return self.write('invalid param, `type` should be `rdp`, `ssh` or `telnet`.')
这个任意文件读取需要后台管理员权限,属于是鸡肋,且该系统用户均为具有一定权限的用户:
所以这个不深究了。
存储xss
这个是我在cve上搜到的,只有一句简单的描述(在老版本上存在):
对比3.1.0和3.5.6版本登录逻辑的区别,不难找到问题所在:
可以看到在3.5.6将<>进行实体编码,结合前端显示:
不难猜测是通过闭合<>达到存储xss的目的。
csrf漏洞
同样也是只有一句简单描述,那么只能自己看了。
在重置密码app.controller.user.DoResetPasswordHandler中:
可以通过mode控制执行的模式,重点看mode==2:
mode==2时,先鉴权,然后获取user_id和password,注意这里不需要传入旧密码,接着往下走就能看到先进行密码强度检查,然后就通过user_id和password重置密码了:
这里理论上可以制作钓鱼链接发给管理员,重置任意密码。
利用:
url:http://192.168.87.149:7190/user/do-reset-password
post:args={"mode":2,"id":2,"password":"[email protected]"}
(该漏洞在最新发行版本中仍存在)
未授权漏洞
看下app/controller/system.py,随便拿个路由来说,方法都会调用app.base.controller.TPBaseHandler.check_privilege鉴权:
不过app.controller.system.DoGetLogsHandler中没有进行鉴权:
通过路由可以找到该请求包:
正常请求(携带cookie):
删除cookie同样返回数据:
接着看下逻辑,调用了app.model.syslog.get_logs:
将sql_filter中key为log_user_name的值带入语句,这里则可以闭合"达到sqli。
总结
pythonweb看的不多,不过前段时间经常拿来写点什么小玩意~~~
自己没耐心了,感觉应该还有不少东西可以学习一下~~~
https://github.com/tp4a/teleport/issues/290
https://github.com/tp4a/teleport/issues/276
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=teleport+++tp4a