Skip to content

Commit

Permalink
fix: Fix a crash in firefox_addons
Browse files Browse the repository at this point in the history
Add a return when the "addons" member in the extensions JSON
is present but it's not an array,
to avoid accessing uninitialized memory.

Also check that the "addons" member elements are all objects
when trying to access its nested members.
  • Loading branch information
Smjert committed Dec 22, 2023
1 parent c396d07 commit 32c3d3a
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions osquery/tables/applications/browser_firefox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <osquery/utils/conversions/tryto.h>

namespace fs = boost::filesystem;
namespace pt = boost::property_tree;

namespace osquery {

Expand Down Expand Up @@ -61,17 +60,23 @@ bool isMemberTrue(const char* member_name, const rapidjson::Value& from) {
return member != from.MemberEnd() ? JSON::valueToBool(member->value) : false;
}

rapidjson::Value::ConstMemberIterator findNestedMember(
std::optional<rapidjson::Value::ConstMemberIterator> findNestedMember(
const std::string& member_name, const rapidjson::Value& value) {
auto child_members = osquery::split(member_name, ".");

rapidjson::Value::ConstMemberIterator member_it;
const rapidjson::Value* current_value = &value;
for (const auto& child_member : child_members) {
/* Verify that we are accessing an object at every nested level,
except the last */
if (!current_value->IsObject()) {
return std::nullopt;
}

member_it = current_value->FindMember(child_member);

if (member_it == current_value->MemberEnd()) {
return member_it;
return std::nullopt;
}

current_value = &member_it->value;
Expand Down Expand Up @@ -120,28 +125,35 @@ void genFirefoxAddonsFromExtensions(const std::string& uid,
TLOG << "Unrecognized format for the 'addons' member in the extensions "
"file at: "
<< extensions_path << ", it's not an array";
return;
}

for (const auto& addon : addons.GetArray()) {
if (!addon.IsObject()) {
continue;
}

Row r;
r["uid"] = uid;
// Most of the keys are in the top-level JSON dictionary.
for (const auto& it : kFirefoxAddonKeys) {
const auto member_it = findNestedMember(it.first, addon);
const auto opt_member_it = findNestedMember(it.first, addon);

if (member_it == addon.MemberEnd()) {
if (!opt_member_it.has_value()) {
continue;
}

const auto value = JSON::valueToString(member_it->value);
if (!value.has_value()) {
const auto& member_it = *opt_member_it;

const auto opt_value = JSON::valueToString(member_it->value);
if (!opt_value.has_value()) {
TLOG << "Failed to convert member '" << member_it->name.GetString()
<< "' to a string, in JSON extensions file at: "
<< extensions_path;
continue;
}

r[it.second] = SQL_TEXT(*value);
r[it.second] = SQL_TEXT(*opt_value);
}

// There are several ways to disabled the addon, check each.
Expand Down

0 comments on commit 32c3d3a

Please sign in to comment.