wazuh-modules-sca
wazuh中安全配置评估模块主线程执行wm_sca_main最后在wm_sca_start中循环执行,不会返回
// Module main function. It won't return
#ifdef WIN32
DWORD WINAPI wm_sca_main(void *arg) {
wm_sca_t *data = (wm_sca_t *)arg;
#else
void * wm_sca_main(wm_sca_t * data) {
#endif
// If module is disabled, exit
if (data->enabled) {
minfo("Module started.");
} else {
minfo("Module disabled. Exiting.");
pthread_exit(NULL);
}
if (!data->policies || data->policies[0] == NULL) {
minfo("No policies defined. Exiting.");
pthread_exit(NULL);
}
data->msg_delay = 1000000 / wm_max_eps;
data->summary_delay = 3; /* Seconds to wait for summary sending */
data_win = data;
/* Reading the internal options */
// Default values
data->request_db_interval = 300;
data->remote_commands = 0;
data->commands_timeout = 30;
data->request_db_interval = getDefine_Int("sca","request_db_interval", 1, 60) * 60;
data->commands_timeout = getDefine_Int("sca", "commands_timeout", 1, 300);
#ifdef CLIENT
data->remote_commands = getDefine_Int("sca", "remote_commands", 0, 1);
#else
data->remote_commands = 1; // Only for agents
#endif
/* Maximum request interval is the scan interval */
if(data->request_db_interval > data->scan_config.interval) {
data->request_db_interval = data->scan_config.interval;
minfo("The request_db_interval option cannot be higher than the scan interval. It will be redefined to that value.");
}
int i;
for(i = 0; data->policies[i]; i++) {
if(data->policies[i]->enabled){
minfo("Loaded policy '%s'", data->policies[i]->policy_path);
} else {
minfo("Policy '%s' disabled by configuration.", data->policies[i]->policy_path);
}
}
/* Create Hash for each policy file */
for(i = 0; data->policies[i]; i++) {
os_realloc(cis_db, (i + 2) * sizeof(OSHash *), cis_db);
cis_db[i] = OSHash_Create();
if (!cis_db[i]) {
merror(LIST_ERROR);
pthread_exit(NULL);
}
OSHash_SetFreeDataPointer(cis_db[i], (void (*)(void *))wm_sca_free_hash_data);
/* DB for calculating hash only */
os_realloc(cis_db_for_hash, (i + 2) * sizeof(cis_db_hash_info_t), cis_db_for_hash);
/* Last summary for each policy */
os_realloc(last_summary_json, (i + 2) * sizeof(cJSON *), last_summary_json);
last_summary_json[i] = NULL;
/* Prepare first ID for each policy file */
os_calloc(1,sizeof(cis_db_info_t *),cis_db_for_hash[i].elem);
cis_db_for_hash[i].elem[0] = NULL;
}
/* Create summary hash for each policy file */
for(i = 0; data->policies[i]; i++) {
os_realloc(last_sha256, (i + 2) * sizeof(char *), last_sha256);
os_calloc(1,sizeof(os_sha256),last_sha256[i]);
}
#ifndef WIN32
data->queue = StartMQ(DEFAULTQUEUE, WRITE, INFINITE_OPENQ_ATTEMPTS);
if (data->queue < 0) {
merror("Can't connect to queue.");
}
#endif
request_queue = queue_init(1024);
w_rwlock_init(&dump_rwlock, NULL);
#ifndef WIN32
w_create_thread(wm_sca_request_thread, data);
w_create_thread(wm_sca_dump_db_thread, data);
#else
w_create_thread(NULL,
0,
(void *)wm_sca_dump_db_thread,
data,
0,
NULL);
#endif
wm_sca_start(data);
#ifdef WIN32
return 0;
#else
return NULL;
#endif
}
1. 检查模块是否开启,否则退出模块主线程
2. 对于agents模式,remote_commands = 1
3. 配置最大扫描间隔 data->request_db_interval = data->scan_config.interval;
4. 加载每一个policy文件(.yml或者yaml),为每一个policy文件创建一个hash,到data结构指针中cis_db_for_hash[i],与data[i]通过下标对应起来
5. 创建一个写类型的队列data->queue = StartMQ(DEFAULTQUEUE, WRITE, INFINITE_OPENQ_ATTEMPTS);
6. w_create_thread(wm_sca_request_thread, data); 接收扫描请求,检查处理发送到队列中
7. w_create_thread(wm_sca_dump_db_thread, data); 从队列中消费请求,
8. wm_sca_start(data) -> wm_sca_read_files()按照每一个policy进行扫描 -> rules扫描核心函数wm_sca_do_scan() -> wm_sca_read_command()
8.1 wm_sca_read_files()函数读policy监控文件到buffer,将buffer中yaml结构转换为json结构
8.2 检查policy是否满足要求
8.3 设置一个唯一的id为每个扫描
8.4 检查文件完整性是否改变,改变则清理
8.5 调用wm_sca_do_scan()做扫描
8.6 发送扫描汇总信息wm_sca_send_summary()
9. wm_sca_do_scan()
char *value = wm_sca_get_value(rule_cp_ref, &type);得到不同的type 例如:WM_SCA_TYPE_FILE,WM_SCA_TYPE_COMMAND,WM_SCA_TYPE_DIR等做不同的处理
已, 以WM_SCA_TYPE_COMMAND类型为例将调用wm_sca_read_command()处理
10. wm_sca_read_command()
static int wm_sca_read_command(char * command,
char * pattern,
wm_sca_t * data,
char ** reason,
w_expression_t * regex_engine)
{
if (command == NULL) {
mdebug1("No Command specified Returning.");
return RETURN_NOT_FOUND;
}
if (!pattern) {
mdebug1("No pattern given. Returning FOUND.");
return RETURN_FOUND;
}
mdebug1("Executing command '%s', and testing output with pattern '%s'", command, pattern);
char *cmd_output = NULL;
int result_code;
switch (wm_exec(command, &cmd_output, &result_code, data->commands_timeout, NULL)) {
case 0:
mdebug1("Command '%s' returned code %d", command, result_code);
break;
case WM_ERROR_TIMEOUT:
os_free(cmd_output);
mdebug1("Timeout overtaken running command '%s'", command);
if (*reason == NULL) {
os_malloc(snprintf(NULL, 0, "Timeout overtaken running command '%s'", command) + 1, *reason);
sprintf(*reason, "Timeout overtaken running command '%s'", command);
}
os_free(cmd_output);
return RETURN_INVALID;
default:
if (result_code == EXECVE_ERROR) {
mdebug1("Invalid path or wrong permissions to run command '%s'", command);
if (*reason == NULL) {
os_malloc(snprintf(NULL, 0, "Invalid path or wrong permissions to run command '%s'", command) + 1, *reason);
sprintf(*reason, "Invalid path or wrong permissions to run command '%s'", command);
}
} else {
mdebug1("Failed to run command '%s'. Returned code %d", command, result_code);
if (*reason == NULL) {
os_malloc(snprintf(NULL, 0, "Failed to run command '%s'. Returned code %d", command, result_code) + 1, *reason);
sprintf(*reason, "Failed to run command '%s'. Returned code %d", command, result_code);
}
}
return RETURN_INVALID;
}
if(!cmd_output) {
mdebug2("Command yielded no output. Returning.");
return RETURN_NOT_FOUND;
}
char **output_line;
output_line = OS_StrBreak('\n', cmd_output, 256);
if(!output_line) {
mdebug1("Command output could not be processed. Output dump:\n%s", cmd_output);
os_free(cmd_output);
return RETURN_NOT_FOUND;
}
os_free(cmd_output);
int i;
int result = RETURN_NOT_FOUND;
for (i=0; output_line[i] != NULL; i++) {
char *buf = output_line[i];
os_trimcrlf(buf);
result = wm_sca_pattern_matches(buf, pattern, reason, regex_engine);
if (result == RETURN_FOUND){
break;
}
}
free_strarray(output_line);
mdebug2("Result for (%s)(%s) -> %d", pattern, command, result);
return result;
}
10. wm_sca_send_policies_scanned(data);发送管理端数据库中被清理的policy