The default timestamp was added for shell_history without timestamp (#4618)

If the shell history file does not contain a timestamps for the lines
osquery will miss the time in rows and will show an confusing error
about attempt to convert empty string to INTEGER.

```
% head -n 3 ~/.zsh_history
ls
cd source
ls
```

```
osquery> select * from shell_history limit 1;
I0621 11:56:37.804193 2629124992 virtual_table.cpp:292] Error casting time () to INTEGER
+------------+------+---------+-------------------------------+
| uid        | time | command | history_file                  |
+------------+------+---------+-------------------------------+
| 1868255265 |      | exit    | /home/akindyakov/.zsh_history |
+------------+------+---------+-------------------------------+
```
So, default value for the time in shell history can solve the problem.
This commit is contained in:
Alexander 2018-06-25 16:55:49 +01:00 committed by GitHub
parent 4270f75b94
commit 1179915350
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 1 deletions

View File

@ -20,6 +20,7 @@
#include <osquery/tables.h>
#include "osquery/core/conversions.h"
#include "osquery/tables/system/posix/shell_history.h"
#include "osquery/tables/system/system_utils.h"
namespace xp = boost::xpressive;
@ -77,6 +78,7 @@ void genShellHistoryForUser(const std::string& uid,
r["time"] = INTEGER(zsh_timestamp_matches["timestamp"]);
r["command"] = zsh_timestamp_matches["command"];
} else {
r["time"] = INTEGER(0);
r["command"] = line;
}

View File

@ -0,0 +1,27 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include <osquery/query.h>
#include <osquery/tables.h>
#include <string>
namespace osquery {
namespace tables {
void genShellHistoryForUser(const std::string& uid,
const std::string& gid,
const std::string& directory,
QueryData& results);
QueryData genShellHistory(QueryContext& context);
} // namespace tables
} // namespace osquery

View File

@ -0,0 +1,63 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include "osquery/tables/system/posix/shell_history.h"
#include <osquery/sql.h>
#include <boost/filesystem.hpp>
#include <gtest/gtest.h>
#include <fstream>
namespace fs = boost::filesystem;
namespace osquery {
namespace tables {
class ShellHistoryTests : public testing::Test {};
TEST_F(ShellHistoryTests, empty_timestamp) {
auto results = QueryData{};
auto directory =
fs::temp_directory_path() /
fs::unique_path("osquery.shell_history_tests.empty_timestamp.%%%%-%%%%");
ASSERT_TRUE(fs::create_directory(directory));
auto filepath = directory / fs::path(".sh_history");
auto const first_line = R"raw([\]^_`!a"b#c$d %e&f'g(h)i*j+k,l-m.n/o0p1q2)raw";
auto const second_line = R"raw(r 3 s4t5u6v7w8 x9y:9:z; {<|=}>~?)raw";
{
auto fout =
std::ofstream(filepath.native(), std::ios::out | std::ios::binary);
fout << first_line << '\n';
fout << second_line << '\n';
}
auto const uid = std::to_string(geteuid());
genShellHistoryForUser(
uid, std::to_string(getegid()), directory.native(), results);
ASSERT_EQ(results.size(), 2u);
const auto& first_row = results[0];
EXPECT_EQ(first_row.at("uid"), uid);
EXPECT_EQ(first_row.at("time"), "0");
EXPECT_EQ(first_row.at("command"), first_line);
EXPECT_EQ(first_row.at("history_file"), filepath.native());
const auto& second_row = results[1];
EXPECT_EQ(second_row.at("uid"), uid);
EXPECT_EQ(second_row.at("time"), "0");
EXPECT_EQ(second_row.at("command"), second_line);
EXPECT_EQ(second_row.at("history_file"), filepath.native());
fs::remove_all(directory);
}
} // namespace tables
} // namespace osquery

View File

@ -2,7 +2,7 @@ table_name("shell_history")
description("A line-delimited (command) table of per-user .*_history data.")
schema([
Column("uid", BIGINT, "Shell history owner", additional=True),
Column("time", INTEGER, "Entry timestamp"),
Column("time", INTEGER, "Entry timestamp. It could be absent, default value is 0."),
Column("command", TEXT, "Unparsed date/line/command history line"),
Column("history_file", TEXT, "Path to the .*_history for this user"),
ForeignKey(column="uid", table="users"),