Actual Sync-server GoCardless服务敏感数据泄露漏洞分析

本文详细分析了Actualbudget中GoCardless组件存在的敏感数据泄露漏洞,该漏洞导致承载令牌、账户号码等敏感信息被记录到日志中,存在严重的信息泄露风险。

漏洞详情

包信息

  • 包管理器: npm
  • 包名称: @actual-app/sync-server
  • 受影响版本: <= 25.10.0
  • 已修复版本: 无

漏洞描述

概述

Actualbudget中的GoCardless组件使用console.logconsole.debug将响应以解析格式记录到STDOUT。这导致敏感信息暴露在日志文件中,包括但不限于:

  • GoCardless承载令牌
  • 账户IBAN和银行账号
  • 账户持有人的个人身份信息(PII)
  • 交易详情(收款人银行信息、收款人账号、交易ID等)

详细情况

当GoCardless响应请求时,有效载荷会被打印到调试日志中:

1
// 文件位置:packages/sync-server/src/app-gocardless/banks/integration-bank.js#L25-L27

这会记录以下信息到Docker日志中(此处所有值已移除,这些字段可能因每个机构返回的内容而异):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
  "account": {
    "resourceId": "",
    "iban": "",
    "bban": "",
    "currency": "",
    "name": "<银行中的完整法定名称>",
    "product": "",
    "status": "",
    "bic": "",
    "usage": "",
    "id": "",
    "created": "",
    "last_accessed": "",
    "institution_id": "",
    "owner_name": "",
    "institution": {
      "id": "",
      "name": "",
      "bic": "",
      "transaction_total_days": "",
      "countries": [""],
      "logo": "",
      "max_access_valid_for_days": "",
      "supported_features": ["", "", ""],
      "identification_codes": []
    }
  }
}
1
// 文件位置:packages/sync-server/src/app-gocardless/banks/integration-bank.js#L83-L85

这是前10笔交易中的第一笔:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
  "top10Transactions": [{
    "transactionId": "",
    "entryReference": "",
    "bookingDate": "",
    "valueDate": "",
    "transactionAmount": {
      "amount": "",
      "currency": ""
    },
    "creditorName": "",
    "creditorAccount": {
      "bban": ""
    },
    "debtorName": "",
    "debtorAccount": {
      "bban": ""
    },
    "remittanceInformationUnstructured": "",
    "remittanceInformationStructuredArray": [
      {"reference": "", "referenceType": ""}
    ],
    "additionalInformation": "",
    "proprietaryBankTransactionCode": "",
    "debtorAgent": "",
    "internalTransactionId": "",
    "payeeName": "",
    "date": ""
  }]
}

此外,在GoCardless的错误处理中,存在一个针对未分类错误的捕获所有异常处理程序,它将整个堆栈跟踪打印到控制台:

1
// 文件位置:packages/sync-server/src/app-gocardless/app-gocardless.js#L263-L264

当银行因维护而离线时,会从GoCardless抛出503错误。整个响应有效载荷被转储到控制台,其中包括用于访问GoCardless的承载令牌:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Something went wrong ServiceError: Institution service unavailable
    at handleGoCardlessError (file:///app/src/app-gocardless/services/gocardless-service.js:59:13)
    at Object.getTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:530:7)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.getNormalizedTransactions (file:///app/src/app-gocardless/services/gocardless-service.js:267:26)
    at async file:///app/src/app-gocardless/app-gocardless.js:186:13 {
  details: h [AxiosError]: Request failed with status code 503
      at te (file:///app/node_modules/nordigen-node/dist/index.esm.js:13:914)
      at IncomingMessage.<anonymous> (file:///app/node_modules/nordigen-node/dist/index.esm.js:17:16315)
      at IncomingMessage.emit (node:events:529:35)
      at endReadableNT (node:internal/streams/readable:1400:12)
      at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
    code: 'ERR_BAD_RESPONSE',
    config: {
      transitional: {
        silentJSONParsing: true,
        forcedJSONParsing: true,
        clarifyTimeoutError: false
      },
      adapter: [ 'xhr', 'http' ],
      transformRequest: [ [Function (anonymous)] ],
      transformResponse: [ [Function (anonymous)] ],
      timeout: 0,
      xsrfCookieName: 'XSRF-TOKEN',
      xsrfHeaderName: 'X-XSRF-TOKEN',
      maxContentLength: -1,
      maxBodyLength: -1,
      env: {
        FormData: [Function: _] {
          LINE_BREAK: '\r\n',
          DEFAULT_CONTENT_TYPE: 'application/octet-stream'
        },
        Blob: [class Blob]
      },
      validateStatus: [Function: validateStatus],
      headers: T [AxiosHeaders] {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'User-Agent': 'Nordigen-Node-v2',
        'Authorization': 'Bearer eyJ0eXAi... (完整令牌在响应中)',
        'Accept-Encoding': 'gzip, compress, deflate, br'
      },
      method: 'get',
      url: URL {
        href: 'https://bankaccountdata.gocardless.com/api/v2/accounts/<账户ID在此处>?date_from=2024-12-22',
        origin: 'https://bankaccountdata.gocardless.com',
        protocol: 'https:',
        username: '',
        password: '',
        host: 'bankaccountdata.gocardless.com',
        hostname: 'bankaccountdata.gocardless.com',
        port: '',
        pathname: '/api/v2/accounts/<账户ID在此处>/transactions',
        search: '?date_from=2024-12-22',
        searchParams: URLSearchParams { 'date_from' => '2024-12-22' },
        hash: ''
      },
      data: undefined
    },

复现步骤

  1. 在Docker中设置Actualbudget服务器,使用仓库中发布的Docker Compose脚本
  2. 将GoCardless账户链接到Actualbudget并同步银行账户
  3. 使用docker logs actual-actual_server-1 -f观察容器,发现敏感详细信息被记录到控制台并被Docker摄取

影响

信息泄露。这些服务既可在本地使用,也可在不受最终用户控制的环境中使用,例如提供此应用程序作为托管解决方案的第三方提供商。

参考链接

  • GHSA-xvp7-8vm8-xfxx
  • actualbudget/actual@97482a0
  • 相关代码文件链接

安全评分

  • 严重程度: 中等
  • CVSS总体评分: 4.2/10
  • CVSS v3基础指标: AV:L/AC:L/PR:H/UI:R/S:U/C:H/I:N/A:N

弱点标识

  • CWE-209: 生成包含敏感信息的错误消息
  • CWE-219: 在Web根目录下存储包含敏感数据的文件

信用

报告者:StoobertB

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计