脚本实践
计算阶乘,根据结果写入不同的日志,并实时触发事件
根据前面的脚本,稍微作一点修改,来理解一下logger和event:
moduleFactor;
export{
redef enumLog::ID +={LOG};
type Info: record{
num: count &log;
factorial_num: count &log;
};
global log_factor:event(rec:Info);
}
function factorial(n:count):count{
if(n==0)
return1;
else
return(n*factorial(n-1));
}
function check(id:Log::ID,path:string,rec:Info):string{
if(rec$factorial_num%5==0)
return"mod5";
else
return"non5";
}
event log_factor(rec:Info){
print fmt("log_factor triggered: num=%d, factorial_num=%d",rec$num,rec$factorial_num);
}
event zeek_init()
{
Log::create_stream(LOG,[$columns=Info,$ev=log_factor]);
local filter:Log::Filter=[$name="diff",$path_func=check];
Log::add_filter(LOG,filter);
Log::remove_filter(LOG,"default");
}
event zeek_done(){
local numbers : vector of count = vector(1,2,3,4,5,6,7,8);
for(i in numbers)
Log::write(LOG,[$num=numbers[i],$factorial_num=factorial(numbers[i])]);
}
1.zeek_init
事件:在 Zeek 启动时触发。•Log::create_stream(LOG, [$columns=Info, $ev=log_factor]);
:•这里创建了一个新的日志流 LOG
,并定义了该流的列类型为 Info
。并将 log_factor
事件与这个日志流关联起来,当日志流写入数据时,log_factor
事件会被触发,处理与该流相关的记录。2.zeek_done
事件:在 Zeek 完成后触发,每当 Zeek 会话结束时都会执行。•Log::write(LOG, [$num=numbers[i], $factorial_num=factorial(numbers[i])]);
:•对于vector numbers
中的每个数字,Log::write
被调用。每次写入一个新记录时,都会触发 log_factor
事件。•log_factor
事件会打印出该记录中的 num
和 factorial_num
。
•创建日志流:在 zeek_init
中调用 create_stream
,将 log_factor
事件与日志流 LOG
关联。这是系统启动时的配置,确保此事件在关联的日志流活动时被调用。•写入日志:在 zeek_done
事件中,通过循环遍历每个数字调用 Log::write
。每次调用写入新记录时,都会触发 log_factor
事件,输出相关信息。
Webshell 和后门通信检测
这里模拟一个攻击场景,攻击者上传一个webshell,并通过http访问。
攻击者可能通过以下步骤发起多阶段攻击:
1.上传一个 Webshell 文件,通过 HTTP 请求激活 Webshell。2.使用 Webshell 建立后门通信,例如通过自定义协议与外部服务器通信。3.后门流量中包含数据泄露或控制命令。
这个场景需要:
•检测到 Webshell 激活。•跟踪该 HTTP 会话的后续活动。•进一步分析后门流量,确认其中的命令或敏感数据。
moduleWebshellBackdoorDetection;
export{
const suspicious_extensions =/.(php|jsp|aspx)$/;
const backdoor_keywords =/(cmd|ls|cat|pwd|whoami|system)/;
global webshell_activations: table[string] of count;
}
event http_header(c: connection, is_orig:bool, name:string, value:string){
if(is_orig){
print fmt("Header -> %s: %s", name, value);
}
}
event http_entity_data(c: connection, is_orig:bool, length: count, data:string){
if(is_orig){
print fmt("POST Data: %s", data);
}
}
event http_request(c: connection, method:string, original_URI:string,
unescaped_URI:string, version:string){
if(method =="POST"&& original_URI !=""){
if(suspicious_extensions in original_URI){
print fmt("n=== Webshell Activity Detected ===");
print fmt("Timestamp: %s", strftime("%Y-%m-%d %H:%M:%S", network_time()));
print fmt("Connection Info:");
print fmt(" - Source IP: %s", c$id$orig_h);
print fmt(" - Source Port: %d", c$id$orig_p);
print fmt(" - Destination IP: %s", c$id$resp_h);
print fmt(" - Destination Port: %d", c$id$resp_p);
print fmt("nHTTP Request Info:");
print fmt(" - Method: %s", method);
print fmt(" - URI: %s", original_URI);
print fmt(" - HTTP Version: %s", version);
if( c?$http ){
if( c$http?$user_agent )
print fmt(" - User-Agent: %s", c$http$user_agent);
if( c$http?$referrer )
print fmt(" - Referrer: %s", c$http$referrer);
if( c$http?$host )
print fmt(" - Host: %s", c$http$host);
}
print fmt("nConnection Details:");
print fmt(" - Total bytes sent: %s", c$orig$size);
print fmt(" - Total bytes received: %s", c$resp$size);
print fmt("===============================n");
webshell_activations[original_URI]=1;
}
}
}
event http_reply(c: connection, version:string, code: count, reason:string){
for( uri in webshell_activations ){
print fmt("n=== Webshell Response Detected ===");
print fmt("Response Code: %d %s", code, reason);
print fmt("HTTP Version: %s", version);
print fmt("===============================n");
}
}
event tcp_packet(c: connection, is_orig:bool, flags:string, seq: count,
ack: count, len: count, payload:string){
if(len >0&& backdoor_keywords in payload){
print fmt("n=== Suspicious Command Detected ===");
print fmt("Timestamp: %s", strftime("%Y-%m-%d %H:%M:%S", network_time()));
print fmt("nPacket Details:");
print fmt(" - Direction: %s", is_orig ?"Outbound":"Inbound");
print fmt(" - TCP Flags: %s", flags);
print fmt(" - Sequence Number: %d", seq);
print fmt(" - ACK Number: %d", ack);
print fmt(" - Payload Length: %d bytes", len);
print fmt("nConnection Info:");
print fmt(" - Source: %s:%d", c$id$orig_h, c$id$orig_p);
print fmt(" - Destination: %s:%d", c$id$resp_h, c$id$resp_p);
print fmt("nPayload Preview:");
print fmt("----------------------------------------");
local clean_payload = gsub(payload[0:500],/[x00-x1Fx7F-xFF]/,".");
print fmt("%s", clean_payload);
print fmt("----------------------------------------n");
if( c?$http ){
print fmt("nHTTP Context:");
if( c$http?$method )
print fmt(" - Method: %s", c$http$method);
if( c$http?$uri )
print fmt(" - URI: %s", c$http$uri);
if( c$http?$user_agent )
print fmt(" - User-Agent: %s", c$http$user_agent);
}
print fmt("===============================n");
}
}
event connection_state_remove(c: connection){
if(c$id$resp_p ==80/tcp || c$id$resp_p ==443/tcp){
print fmt("n=== Connection Summary ===");
print fmt("Connection ID: %s", c$uid);
print fmt("Duration: %.2f seconds", c$duration);
print fmt("Total bytes sent: %d", c$orig$size);
print fmt("Total bytes received: %d", c$resp$size);
print fmt("=======================n");
}
}
验证步骤
部署脚本:
在mac中创建一个webshell文件,写入如下内容,模拟被上传webshell的场景:
<?php
if(isset($_POST['cmd'])){
echo "Command received: ". $_POST['cmd']."n";
system($_POST['cmd']." 2>&1");
}else{
echo "Welcome to test page";
}
?>
开启http server:
用Kali VM模拟攻击:
最终触发告警:
原文始发于微信公众号(Crush Sec):Zeek0x03_Zeek脚本实践
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论