登录框不能只会弱口令——记一次从SPA路由到Swagger泄露的漏洞挖掘(二)

免责声明:
用途限定
本文档内容仅供网络安全技术人员及合规从业者于授权环境下进行学术交流、技术研讨与防御能力建设之用,旨在提升网络安全防护意识。
禁止行为
文中涉及的所有技术原理、操作步骤、代码示例及工具说明,严禁直接或间接用于以下任何行为:
未经授权的网络扫描、渗透测试或系统入侵;
非法获取、篡改、破坏或泄露他人数据信息;
干扰、瘫痪或恶意控制任何计算机系统、网络设施或物联网设备;
其他违反《中华人民共和国网络安全法》《中华人民共和国刑法》及相关国际公约的活动。
法律后果自担
任何个人或组织若将本文内容用于非法目的或未授权场景,其所产生的全部法律责任(包括但不限于行政处罚、民事赔偿及刑事责任)及衍生风险,均由使用者自行承担。
平台免责
文章作者、发布平台对上述违规使用行为不提供任何明示或默示的支持、鼓励或协助,且不对由此引发的任何直接、间接、偶然或惩罚性损害承担连带责任。
合规提醒
建议读者在实施任何技术操作前,确保已获得相应系统所有者的书面授权,并严格遵循所在组织的信息安全政策与法律法规。

之前写过一篇,到发现/admin/client/list/接口之后就停了,没有进行进一步测试,当时测的还没那么深入,因此这里再重新回顾一下,如何发现这个接口可以自行阅读第一篇文章


访问接口可以看到的内容如图所示:

image

图片里面的内容为OAuth2 客户端配置数据,字段含义如下:

字段名 字段说明 数据类型 取值/示例说明
id 主键ID Integer 数据库自增主键,例如:1, 2, 3...
clientId 客户端标识 String 用于唯一标识一个 OAuth2 客户端,例如:app, pig
clientSecret 客户端密钥 String 客户端的密码,通常以 {bcrypt} 等加密形式存储
scope 权限范围 String 客户端请求的权限范围,示例中均为 "server"
authorizedGrantTypes 授权模式 String 支持的 OAuth2 授权方式(逗号分隔),如 password, refresh_token
accessTokenValidity 访问令牌有效期 Integer Access Token 的有效时间,单位为秒
refreshTokenValidity 刷新令牌有效期 Integer Refresh Token 的有效时间,单位为秒
webServerRedirectUri Web重定向地址 String 授权码模式下,认证完成后重定向的 URL
additionalInformation 附加信息 String (JSON) 扩展字段,包含自定义配置,如 enc_flagcaptcha_flag
autoapprove 是否自动授权 String 用户授权时是否跳过确认页面,"true" 为自动授权
delFlag 删除标记 String 逻辑删除标识,"0" 表示正常,"1" 表示已删除
createTime 创建时间 Timestamp 记录创建的时间
updateTime 更新时间 Timestamp 记录最后一次修改的时间

其中additionalInformation里面的两个字段需要特别说明:

enc_flag(密码加密开关)

取值 含义 说明
"1" 开启密码加密 该客户端登录时,前端会使用 AES 算法对密码进行加密后再发送,网关层的 PasswordDecoderFilter 会自动解密后交由认证服务处理
"0" 关闭密码加密 该客户端登录时密码以明文形式传输,不经过加密/解密处理

captcha_flag(验证码开关)

取值 含义 说明
"1" 开启验证码校验 该客户端登录时需要输入验证码(图形验证码或短信验证码),网关层的 ValidateCodeGatewayFilter 会拦截并校验验证码有效性
"0" 关闭验证码校验 该客户端登录时跳过验证码校验,直接进行账号密码验证

以及clientid:

clientId 业务含义 典型使用场景
app APP端客户端 移动端 APP(iOS/Android)登录认证
daemon 守护进程/后台服务 后端微服务之间的内部调用与鉴权
gen 代码生成器 框架自带的代码生成工具模块
mp 小程序 微信/支付宝等原生小程序端
pig 管理系统 后台管理端(pig-admin)Web 页面
test 测试客户端 开发、测试环境或接口调试专用
customer 客户端 面向 C 端用户的业务客户端
deviceMini 设备小程序 物联网(IoT)设备配套的管理小程序
alipay-mini 支付宝小程序 支付宝端小程序专属认证
wechat-mini 微信小程序 微信端小程序专属认证

这样的话就可以找无需验证码校验的凭据构造数据包,因为这里是Pig4cloud,采用标准的认证端点:
/auth/oauth/token?grant_type=client_credentials&scope=server,构造如下数据包:

POST /auth/oauth/token?grant_type=client_credentials&scope=server HTTP/1.1
Host: xxxxxxx
Authorization: Basic Y3VzdG9tZXI6Y3VzdG9tZXI=  //base64编码的customer:customer
Accept: */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
Connection: close
Content-Length: 1

image

成功拿到对应的客户端应用token,这里还可以与需要验证码的进行校验,比如pig/pig,返回包如下:

image

可以看到是需要验证码的

有了token之后之前那些鉴权的接口就能进一步进行测试,这里以利用链为主就讲一个baseurl下的:
在swagger接口文档中有这么一个/device

image

然后就可以提取接口,可以放ApiHunter里面一把梭,但这个先放到后面来讲,先讲一个ApiHunter里面没有找出来的:plug-host

image

在文档中可以看到与接口有关的路径有26条,这里就放了一张图,找几个重点的路径,先是获得设备的id:

image

然后通过设备id就能读取相应配置信息:

image

并且可以进行写入安全配置,这里采取的方式为同值回写

image


然后就是ApiHunter里面梭出来的,这里可以读到/etc/passwd

image

这个接口能读文件的原理大致为管理后台的日志查看,后端会把相应文件读取出来,服务器端大致代码如下:

@GetMapping("/download/log")
  public void downloadLog(String filePath, HttpServletResponse resp) {
      File f = new File(BASE_DIR + filePath);      
      copy(new FileInputStream(f), resp.getOutputStream());
  }

漏洞出现的根因是filePath 参数没经过任何校验就拼进了文件路径——没有白名单目录、没有过滤,服务器直接进行输入内容的拼接。

然后尝试读取了一下别的文件,root权限的文件肯定读取不了,但是可以读取/proc/self路径下的有关文件,这里就不放出来了。


本次测试的核心问题在于OAuth2客户端配置接口/admin/client/list/未做严格的访问控制,导致攻击者可以获取所有客户端的凭据及配置信息。其中最关键的是captcha_flag字段,它控制着登录时是否需要验证码校验,当该字段为"0"时,客户端可以绕过验证码直接进行认证请求。利用customer这类关闭验证码校验的客户端,攻击者只需通过Basic认证携带base64编码的clientId:clientSecret即可成功获取到合法的访问令牌。

获取令牌后,原本需要鉴权才能访问的接口现在均可调用,包括Swagger文档中暴露的/device模块下的26个接口。通过这些接口,攻击者可以先获取设备ID,再读取设备配置信息,甚至写入安全配置。

其中日志下载接口/download/log存在路径遍历漏洞,根本原因是后端代码直接将用户输入的filePath参数拼接到基础路径后,未做任何白名单校验或过滤操作,便通过FileInputStream读取并返回文件内容。这导致攻击者可以利用该漏洞读取/etc/passwd等系统文件,虽然root权限的文件无法访问,但/proc/self路径下的进程相关信息依然可以被读取虽然这里也什么大用

整体来看,这是一条从信息泄露到权限绕过,再到未授权访问和文件读取的完整攻击链。修复的核心在于接口权限收敛、验证码强制校验、输入参数白名单过滤以及生产环境Swagger文档的访问控制。

posted @ 2026-09-09 15:43  ShoreKiten  阅读(82)  评论(0)    收藏  举报