mcpField
O
openharmony-security-review

openharmony-security-review

github.com/openharmonyinsight安全35140 次安装11 周前更新
代码仓库

关于 openharmony-security-review

openharmony-security-review 是用于 OpenHarmony C++ 系统服务的结构化安全审查 Skill,面向代码审查人员。它重点检查 IPC 与网络输入、并发、敏感数据日志及权限验证风险。

主要功能

  1. 01检查 IPC 反序列化与边界
  2. 02审查共享状态锁与竞态
  3. 03识别死锁和 TOCTOU 风险
  4. 04检查日志中的敏感数据泄露
  5. 05审查权限验证

适用场景

  1. 01审查处理 MessageParcel 数据的 OpenHarmony 服务
  2. 02审计服务状态的并发访问
  3. 03检查服务日志是否暴露隐私数据
  4. 04评估特权操作的权限检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openharmonyinsight/openharmony-skills --skill openharmony-security-review

安装后在 Claude Code 中输入/openharmony-security-review确认已加载。

详细介绍

OpenHarmony 安全审查

概述

OpenHarmony 系统服务以高权限运行,并通过 IPC 和网络接口处理不可信输入。本技能提供了一套结构化方法,用于识别四个关键领域中的严重安全漏洞:外部输入处理、多线程竞态条件、敏感信息泄露和权限校验。

适用场景

digraph when_to_use {
    "Reviewing OpenHarmony code?" [shape=diamond];
    "Is it C++ system service?" [shape=diamond];
    "Handles IPC/network data?" [shape=diamond];
    "Has shared state?" [shape=diamond];
    "Logs data?" [shape=diamond];
    "Use this skill" [shape=box];
    "Different skill needed" [shape=box];

    "Reviewing OpenHarmony code?" -> "Different skill needed" [label="no"];
    "Reviewing OpenHarmony code?" -> "Is it C++ system service?" [label="yes"];
    "Is it C++ system service?" -> "Different skill needed" [label="no"];
    "Is it C++ system service?" -> "Handles IPC/network data?" [label="yes"];
    "Handles IPC/network data?" -> "Use this skill" [label="yes"];
    "Handles IPC/network data?" -> "Has shared state?" [label="no"];
    "Has shared state?" -> "Use this skill" [label="yes"];
    "Has shared state?" -> "Logs data?" [label="no"];
    "Logs data?" -> "Use this skill" [label="yes"];
    "Logs data?" -> "Different skill needed" [label="no"];
}

在以下场景中使用本技能:

  • 审查 OpenHarmony C++ 系统服务代码(xxxService、xxxStub 实现)
  • 代码处理 IPC(MessageParcel)或网络数据(JSON/XML/Protobuf)
  • 代码以多线程方式访问共享状态
  • 代码会记录用户数据或指针
  • 代码会校验权限或访问受保护资源

请勿用于:

  • 应用层代码(请改用标准安全编码实践)
  • 非 OpenHarmony C++ 代码(请改用通用安全审查技能)
  • 性能优化(请改用其他技能)

代码遍历策略

输入为头文件(.h/.hpp): 分析对应的 xxxService.cpp 和 xxxStub.cpp 输入为 Stub 文件(xxxStub.cpp): 将分析范围扩展到 xxxService.cpp(核心逻辑和共享状态) 外部调用: 标记跨组件并发风险,供单独审查

快速参考:严重漏洞检查清单

类别关键检查项严重性
IPC 反序列化检查所有 MessageParcel 读取操作是否成功HIGH
逻辑校验反序列化后校验数组长度/索引HIGH
整数边界大小变量:0 <= size <= MAX_ALLOWED_BUFFERHIGH
对象生命周期使用前校验 RemoteObjects/fd(检查 nullptr)HIGH
解析器安全网络解析器拒绝格式错误的输入,并防止递归攻击HIGH
容器线程安全保护所有容器操作(读/写、写/写)HIGH
迭代器失效**遍历时不得修改容器HIGH
锁一致性通过互斥锁保护所有共享状态访问HIGH
死锁风险按一致顺序获取嵌套锁HIGH
TOCTOU状态检查后立即执行依赖该状态的操作HIGH
日志中的个人身份信息日志中不得包含电话号码、联系人、短信、生物识别信息HIGH
日志中的输入事件**日志中不得包含原始 KeyEvents、触摸坐标、屏幕边界HIGH
指针地址日志中不得包含 %p 或 &variable(可能绕过 ASLR)HIGH
权限检查所有特权操作都必须校验调用方权限HIGH

1. 外部输入处理(IPC 和网络)

1.1 IPC 反序列化完整性

规则: 每个 MessageParcel 读取操作都必须检查返回值。

反例:

// ❌ VULNERABLE: No validation
parcel.ReadInt32(val);
int32_t size = parcel.ReadInt32();

必需模式:

// ✅ SECURE: Always check return value
if (!parcel.ReadInt32(val)) {
    HILOG_ERROR("Failed to read value");
    return ERR_INVALID_DATA;
}
if (!parcel.ReadInt32(size)) {
    HILOG_ERROR("Failed to read size");
    return ERR_INVALID_DATA;
}

验证: 确认读取的数据大小与预期类型的大小一致。读取失败时立即停止处理。

1.2 反序列化后的逻辑校验

规则: 反序列化后、使用前,校验值是否处于合理范围内。

攻击向量: 攻击者发送 size = 0xFFFFFFFF,导致内存耗尽,或在 new char[size] 中引发整数溢出。

反例:

// ❌ VULNERABLE: No bounds validation
int32_t size = parcel.ReadInt32();
std::vector<char> buffer(size);  // May allocate gigabytes or overflow

必需模式:

// ✅ SECURE: Validate bounds immediately
int32_t size = 0;
if (!parcel.ReadInt32(size)) {
    return ERR_INVALID_DATA;
}
constexpr int32_t MAX_ALLOWED_BUFFER = 1024 * 1024;  // 1MB
if (size < 0 || size > MAX_ALLOWED_BUFFER) {
    HILOG_ERROR("Invalid size: %{public}d", size);
    return ERR_INVALID_DATA;
}
std::vector<char> buffer(size);

校验目标: 数组长度、索引、循环计数器、缓冲区大小

1.3 对象生命周期与所有权

规则: 使用 RemoteObjects 和文件描述符前,必须对其进行校验。

必需模式:

// ✅ SECURE: Validate before use
if (remoteObject == nullptr) {
    HILOG_ERROR("Received null RemoteObject");
    return ERR_NULL_OBJECT;
}
if (fd < 0) {
    HILOG_ERROR("Invalid file descriptor");
    return ERR_INVALID_FD;
}
1.4 外部网络数据

规则: 网络解析器必须拒绝格式错误的输入,并防止递归攻击。

检查项:

  • 配置 JSON 解析器以拒绝格式错误的输入
  • 防范“Zip Bomb”攻击
  • 限制深层递归

2. 多线程与并发

2.1 容器线程安全(最高优先级)

规则: 所有并发容器操作都必须使用锁保护。

关键风险:

  • 读/写: 一个线程读取时,另一个线程写入
  • 写/写: 多个线程同时修改
  • 迭代器失效: 一个线程修改时,另一个线程进行迭代

反模式:

// ❌ VULNERABLE: Unprotected concurrent access
std::vector<int> items_;

void AddItem(int item) {
    items_.push_back(item);  // Unsafe if called concurrently
}

void ProcessItems() {
    for (auto& item : items_) {  // Iteration
        // If AddItem called here, iterator invalidates → CRASH
    }
}

必需模式:

// ✅ SECURE: All access protected
std::vector<int> items_;
std::mutex itemsMutex_;

void AddItem(int item) {
    std::lock_guard<std::mutex> lock(itemsMutex_);
    items_.push_back(item);
}

void ProcessItems() {
    std::lock_guard<std::mutex> lock(itemsMutex_);
    for (auto& item : items_) {
        // Safe - lock held during iteration
    }
}

需要仔细检查的容器类型: std::vector、std::map、std::list、std::unordered_map、std::string

需要仔细检查的操作: push_back、insert、erase、operator[]、at、迭代

2.2 锁定机制

规则: 所有共享资源都必须始终受到保护。

需要保护的共享资源:

  • 全局/静态变量
  • 类成员变量
  • 在线程间共享的堆分配对象

锁类型: std::mutex、std::shared_mutex、SpinLock

反模式:

// ❌ VULNERABLE: Inconsistent protection
class Service {
    std::map<int, Data> dataMap_;
    std::mutex mutex_;

    void Update(int key, const Data& data) {
        std::lock_guard<std::mutex> lock(mutex_);
        dataMap_[key] = data;
    }

    Data Lookup(int key) {
        // ❌ NO LOCK - race condition with Update
        return dataMap_[key];
    }
};

必需模式:

// ✅ SECURE: Consistent protection
class Service {
    std::map<int, Data> dataMap_;
    std::mutex mutex_;

    void Update(int key, const Data& data) {
        std::lock_guard<std::mutex> lock(mutex_);
        dataMap_[key] = data;
    }

    Data Lookup(int key) {
        std::lock_guard<std::mutex> lock(mutex_);
        return dataMap_[key];
    }
};
2.3 死锁预防

规则: 评估嵌套锁场景中的死锁风险。

死锁条件:

  • 不同代码路径以不同顺序获取多个锁
  • 持有锁时调用可能获取锁的外部函数

反模式:

// ❌ VULNERABLE: Deadlock risk
void Path1() {
    std::lock_guard<std::mutex> lock1(mutex1_);
    std::lock_guard<std::mutex> lock2(mutex2_);  // Order: 1 then 2
}

void Path2() {
    std::lock_guard<std::mutex> lock2(mutex2_);
    std::lock_guard<std::mutex> lock1(mutex1_);  // Order: 2 then 1 → DEADLOCK
}

必需模式:

// ✅ SECURE: Consistent lock order
void Path1() {
    std::lock_guard<std::mutex> lock1(mutex1_);
    std::lock_guard<std::mutex> lock2(mutex2_);  // Order: 1 then 2
}

void Path2() {
    std::lock_guard<std::mutex> lock1(mutex1_);  // Same order: 1 then 2
    std::lock_guard<std::mutex> lock2(mutex2_);
}
2.4 TOCTOU(检查时与使用时)

规则: 状态检查后必须立即执行依赖该状态的操作,中间不能有间隔。

反模式:

// ❌ VULNERABLE: TOCTOU window
if (fileExists(path)) {
    // Attacker can delete/replace file here
    file = openFile(path);  // May open different file
}

必需模式:

// ✅ SECURE: Atomic check-and-use
file = openFile(path);
if (file.isValid()) {
    // Use file
}

3. 敏感信息保护

3.1 严格清除个人身份信息

规则: 日志必须清除所有个人身份信息(PII)。

需要清除的 PII:

  • 用户隐私: 电话号码、联系人、SMS 内容、生物识别数据
  • 输入事件: 原始 KeyEvents、触摸坐标(x、y)、屏幕位置边界(Rect)

反模式:

// ❌ VULNERABLE: Logs PII
HILOG_INFO("Phone: %{public}s", phoneNumber.c_str());
HILOG_ERROR("Touch at (%{public}d, %{public}d)", x, y);

必需模式:

// ✅ SECURE: Redact or suppress
HILOG_INFO("Phone: %{private}s", phoneNumber.c_str());  // Redacted
// Better: Don't log PII at all
HILOG_INFO("Processing phone number");

策略: 在发布版本中优先完全禁用相关日志。仅在调试确有必要时使用 %{private} 格式说明符。

3.2 内存布局泄露(绕过 ASLR)

规则: 绝不记录原始指针地址。

反模式:

// ❌ VULNERABLE: Leaks addresses for ASLR bypass
HILOG_INFO("Object at %p", &object);
HILOG_DEBUG("Buffer address: %{public}p", buffer);

必需模式:

// ✅ SECURE: No address logging
HILOG_INFO("Object created");
// Use opaque IDs instead of pointers
HILOG_INFO("Object ID: %{public}d", object.id_);

原因: 泄露堆/栈地址会帮助攻击者绕过 ASLR(地址空间布局随机化)。

4. 权限验证

规则: 所有特权操作都必须验证调用方权限。

反模式:

// ❌ VULNERABLE: No permission check
int32_t Service::DeleteFile(const std::string& path) {
    // Any caller can delete any file!
    return unlink(path.c_str());
}

必需模式:

// ✅ SECURE: Validate permissions
int32_t Service::DeleteFile(const std::string& path) {
    // Verify caller has permission to access this path
    if (!HasPermission(callerToken_, path, Permission::DELETE)) {
        HILOG_ERROR("Permission denied for path: %{private}s", path.c_str());
        return ERR_PERMISSION_DENIED;
    }

    // Verify path is within allowed sandbox
    if (!IsPathInSandbox(path)) {
        HILOG_ERROR("Path outside sandbox: %{private}s", path.c_str());
        return ERR_INVALID_PATH;
    }

    return unlink(path.c_str());
}

以下操作必须检查权限:

  • 文件系统操作(读取、写入、删除)
  • 系统设置修改
  • 硬件访问(摄像头、麦克风、位置)
  • 进程间通信
  • 网络操作

常见错误

错误后果修复方法
忘记检查 MessageParcel 返回值使用未初始化数据、崩溃始终检查返回值
验证大小但未检查下限(负数)负数大小通过验证检查 0 <= size <= MAX
保护共享容器的写入操作,却不保护读取操作读取时发生竞态条件保护所有访问
容器修改后继续使用迭代器迭代器失效、崩溃迭代期间持有锁
使用 %{public} 记录 PII信息泄露使用 %{private} 或不记录
为调试打印指针地址绕过 ASLR使用不透明 ID
以“这是内部调用”为由跳过权限检查被外部调用时可能导致权限提升始终进行验证

审查输出格式

按以下格式标记违规:

**[HIGH SECURITY RISK] <Category>**

Location: <file_path>:<line_number>

Issue: <description>

Anti-pattern:
```cpp
<code>

必需的修复:

<code>

影响:<利用后攻击者可实施的操作>


## Real-World Impact

**Container race conditions:** Use-after-free crashes, privilege escalation through corrupted state
**IPC validation failures:** Remote code execution via deserialization exploits, memory exhaustion DoS
**PII leakage:** Privacy violations, GDPR compliance failures
**ASLR bypass:** Enables exploitation of memory corruption vulnerabilities
**Missing permission checks:** Unauthorized access to sensitive data, system modification

评论

支持 Markdown