Skip to content

hardening: prepared statements, PHP 7.4 idioms, and security fixes#8

Open
somethingwithproof wants to merge 3 commits intoCacti:developfrom
somethingwithproof:hardening/comprehensive
Open

hardening: prepared statements, PHP 7.4 idioms, and security fixes#8
somethingwithproof wants to merge 3 commits intoCacti:developfrom
somethingwithproof:hardening/comprehensive

Conversation

@somethingwithproof
Copy link
Copy Markdown

Consolidated hardening: migrate to prepared statements, null coalescing operators, PHP 7.4 str_starts_with replacement.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
… equivalents

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Copilot AI review requested due to automatic review settings April 9, 2026 06:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the WMI plugin by reducing SQL injection risk via prepared statements and tightening command/credential handling in the Linux WMI execution path.

Changes:

  • Converted several SQL calls to prepared statements (db_fetch_*_prepared, db_execute_prepared).
  • Hardened shell command construction by escaping the WMI hostname before execution.
  • Changed stored credential encoding from PHP serialize() to base64(JSON), while retaining legacy decode support.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
script/wmi-script.php Fetch WMI query metadata using a prepared statement.
poller_wmi.php Purge queries use prepared deletes keyed by host_id.
linux_wmi.php Escape hostname for shell execution; update password encode/decode format with legacy support.
functions.php Prepared query for data_input_fields lookup in XML export generation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread linux_wmi.php
Comment on lines 291 to +305
function decode($info) {
$info = base64_decode($info);
$info = unserialize($info);
$info = $info['password'];

return $info;
/*
* Legacy records were stored with serialize(). Detect and migrate on
* read so existing credentials survive the format change. New writes
* always use JSON (see encode()).
*/
if (substr($info, 0, strlen('a:')) === 'a:') {
$decoded = @unserialize($info, ['allowed_classes' => false]);
return is_array($decoded) ? ($decoded['password'] ?? '') : '';
}

$decoded = json_decode($info, true);
return is_array($decoded) ? ($decoded['password'] ?? '') : '';
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decode() assumes base64_decode($info) returns a valid string. If $info is NULL/empty/invalid, base64_decode() can emit warnings and return non-string values, and then substr()/json_decode() will also warn and may end up treating the password as empty. Consider validating the input type and using strict base64 decoding (second arg true) with an explicit failure path before attempting legacy unserialize() / json_decode().

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid. Will add a null/false check on base64_decode return.

Comment thread linux_wmi.php
Comment on lines +295 to +297
* Legacy records were stored with serialize(). Detect and migrate on
* read so existing credentials survive the format change. New writes
* always use JSON (see encode()).
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The block comment says legacy records are “migrated on read”, but the code only detects/decodes the legacy serialization format and does not write back the new JSON encoding. Either adjust the comment to avoid implying a database migration, or implement a real write-back migration when legacy data is successfully decoded.

Suggested change
* Legacy records were stored with serialize(). Detect and migrate on
* read so existing credentials survive the format change. New writes
* always use JSON (see encode()).
* Legacy records were stored with serialize(). Detect and decode them
* during reads so existing credentials continue to work after the format
* change. New writes always use JSON (see encode()).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. The migration is read-only by design. A separate batch migration script would be needed to convert all stored records.

Comment thread linux_wmi.php

return $a;
$a = ['password' => $info];
return base64_encode(json_encode($a));
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encode() does not handle json_encode() failure. When json_encode() returns false (e.g., invalid UTF-8 in the password), base64_encode() will end up encoding an empty string, which can silently wipe stored credentials. Add error handling (e.g., check json_last_error() / use JSON_THROW_ON_ERROR and fail or fall back) so credentials are never overwritten with an empty/invalid encoding.

Suggested change
return base64_encode(json_encode($a));
$encoded = json_encode($a);
if ($encoded === false) {
/*
* Do not base64-encode a failed json_encode() result, as that can
* silently store an empty/invalid credential blob. Fall back to the
* legacy serialize() format, which decode() already supports.
*/
$this->error = 'ERROR: Failed to JSON encode WMI credentials: ' . json_last_error_msg();
$encoded = serialize($a);
}
return base64_encode($encoded);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid. Will add json_encode failure check.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants