openharmony-security-review

安装量: 48
排名: #15383

安装

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

OpenHarmony system services run with high privileges and handle untrusted inputs via IPC and network interfaces. This skill provides a structured approach to identifying critical security vulnerabilities in four key areas: external input handling, multithreading race conditions, sensitive information leakage, and permission validation.

When to Use

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"];
}

Use this skill when:

  • Reviewing OpenHarmony C++ system service code (xxxService, xxxStub implementations)

  • Code handles IPC (MessageParcel) or network data (JSON/XML/Protobuf)

  • Code has multithreaded access to shared state

  • Code performs logging of user data or pointers

  • Code validates permissions or accesses protected resources

Do NOT use for:

  • Application-layer code (use standard secure coding practices instead)

  • Non-OpenHarmony C++ code (use general security review skills)

  • Performance optimization (use different skill)

Code Traversal Strategy

Header file input (.h/.hpp): Analyze corresponding xxxService.cpp and xxxStub.cpp Stub file input (xxxStub.cpp): Extend analysis to xxxService.cpp (core logic + shared state) External calls: Flag cross-component concurrency risks for separate review

Quick Reference: Critical Vulnerability Checklist

| IPC Deserialization | All MessageParcel reads checked for success | HIGH

| Logical Validation | Array lengths/indices validated AFTER deserialization | HIGH

| Integer Bounds | Size variables: 0 <= size <= MAX_ALLOWED_BUFFER | HIGH

| Object Lifecycle | RemoteObjects/fd validated before use (nullptr check) | HIGH

| Parser Security | Network parsers reject malformed input, prevent recursion attacks | HIGH

| Container Thread Safety | All container operations protected (read/write, write/write) | HIGH

| Iterator Invalidation** | No modification while iterating | HIGH

| Lock Consistency | All shared state access protected by mutex | HIGH

| Deadlock Risk | Nested locks acquired in consistent order | HIGH

| TOCTOU | State checks immediately followed by dependent action | HIGH

| PII in Logs | No phone numbers, contacts, SMS, biometrics in logs | HIGH

| Input Events in Logs** | No raw KeyEvents, touch coordinates, screen bounds | HIGH

| Pointer Addresses | No %p or &variable in logs (ASLR bypass) | HIGH

| Permission Check | All privileged operations validate caller permissions | HIGH

1. External Input Handling (IPC & Network)

1.1 IPC Deserialization Integrity

Rule: Every MessageParcel read operation must check return value.

Anti-pattern:

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

Required pattern:

// ✅ 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;
}

Verification: Confirm read data size matches expected type size. Stop processing immediately on read failure.

1.2 Post-Deserialization Logical Validation

Rule: After deserializing, validate values are within logical bounds BEFORE use.

Attack vector: Attacker sends size = 0xFFFFFFFF to cause memory exhaustion or integer overflow in new char[size].

Anti-pattern:

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

Required pattern:

// ✅ 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);

Validation targets: Array lengths, indices, loop counters, buffer sizes

1.3 Object Lifecycle & Ownership

Rule: Validate RemoteObjects and file descriptors before use.

Required pattern:

// ✅ 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 External Network Data

Rule: Network parsers must reject malformed input and prevent recursion attacks.

Checks:

  • JSON parsers configured to reject malformed input

  • Protection against "Zip Bomb" attacks

  • Limits on deeply nested recursion

2. Multithreading & Concurrency

2.1 Container Thread Safety (Highest Priority)

Rule: All concurrent container operations must be protected by locks.

Critical risks:

  • Read/Write: One thread reads while another writes

  • Write/Write: Multiple threads modify simultaneously

  • Iterator invalidation: One thread modifies while another iterates

Anti-pattern:

// ❌ 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
    }
}

Required pattern:

// ✅ 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
    }
}

Container types to scrutinize: std::vector, std::map, std::list, std::unordered_map, std::string

Scrutinize operations: push_back, insert, erase, operator[], at, iteration

2.2 Locking Mechanisms

Rule: All shared resources must be consistently protected.

Shared resources requiring protection:

  • Global/static variables

  • Class member variables

  • Heap-allocated objects shared between threads

Lock types: std::mutex, std::shared_mutex, SpinLock

Anti-pattern:

// ❌ 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];
    }
};

Required pattern:

// ✅ 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 Deadlock Prevention

Rule: Assess deadlock risk in nested lock scenarios.

Deadlock conditions:

  • Multiple locks acquired in different orders by different code paths

  • Lock held while calling external function that might acquire locks

Anti-pattern:

// ❌ 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
}

Required pattern:

// ✅ 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 (Time-of-Check to Time-of-Use)

Rule: State checks must be immediately followed by dependent action without gaps.

Anti-pattern:

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

Required pattern:

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

3. Sensitive Information Protection

3.1 Strict PII Redaction

Rule: Logging must redact all Personally Identifiable Information (PII).

PII requiring redaction:

  • User privacy: Phone numbers, contacts, SMS content, biometric data

  • Input events: Raw KeyEvents, touch coordinates (x, y), screen position bounds (Rect)

Anti-pattern:

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

Required pattern:

// ✅ 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");

Policy: Prefer complete suppression in release builds. Use %{private} format specifier only when absolutely necessary for debugging.

3.2 Memory Layout Leakage (ASLR Bypass)

Rule: Never log raw pointer addresses.

Anti-pattern:

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

Required pattern:

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

Rationale: Leaking heap/stack addresses helps attackers bypass ASLR (Address Space Layout Randomization).

4. Permission Validation

Rule: All privileged operations must validate caller permissions.

Anti-pattern:

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

Required pattern:

// ✅ 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());
}

Permission checks required for:

  • File system operations (read, write, delete)

  • System settings modifications

  • Hardware access (camera, microphone, location)

  • Inter-process communication

  • Network operations

Common Mistakes

| Forgetting to check MessageParcel return values | Uninitialized data use, crashes | Always check return value

| Validating size but not lower bound (negative) | Negative sizes pass validation | Check 0 <= size <= MAX

| Protecting write but not read on shared container | Race condition during reads | Protect ALL access

| Using iterator after container modification | Iterator invalidation, crashes | Hold lock during iteration

| Logging with %{public} for PII | Information leakage | Use %{private} or don't log

| Printing pointer addresses for debugging | ASLR bypass | Use opaque IDs

| Skipping permission check "because it's internal" | Privilege escalation if called externally | Always validate

Review Output Format

Flag violations with this format:

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

Location: <file_path>:<line_number>

Issue: <description>

Anti-pattern:
```cpp
<code>

Required fix:

<code>

Impact:

## 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
返回排行榜