安全研发启蒙课:低成本实现的被动扫描工具

文章介绍了如何使用Yaklang编写脚本,在Yakit中实现被动扫描功能,通过MITM原理在后台运行,仅使用被动扫描,以减少前端性能消耗。详细解释了流程、函数和优化方法,并给出了示例脚本和Yaklang资源链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安全研发启蒙课:低成本实现的被动扫描工具

背景


之前有师傅提过,怎么在关闭Yakit时让Yak引擎在后台运行,只使用被动扫描功能,这样就可以节省前端的性能损耗。
这个需求用Yaklang就完全可以实现,实际上Yakit的大部分功能也是通过Yaklang编写的,下面就详细介绍下如何使用Yaklang编写一个被动扫描脚本。


被动扫描原理


被动扫描的流程如图,MITM指中间人,在被动扫描过程中起到类似HTTP代理的作用。在浏览器中将代理设置为MITM Server地址,那浏览器的所有Web请求都将请求到MITM Server,然后MITM去请求目标网站,再将网站响应返回给浏览器,完成一次代理请求。


MITM在代理浏览器请求目标网站,等待目标网站响应时,镜像了一份请求,发给Hook模块,Hook模块加载被动扫描插件,将请求参数传入扫描插件,对本次请求的网站做扫描。用户只需要通过浏览器访问目标网站即可实现漏洞扫描。


概览整个流程,MITM Server的作用只是获取到浏览器的请求,发送给Hook,那不使用这种HTTP代理的方式获取浏览器请求,抓网卡的HTTP流量,发送给Hook行不行?不行,因为HTTPS的请求是加密的,网卡抓到的流量是加密后的请求,无法解析。而MITM作为一个HTTP代理,既可以作为服务端与客户端交互(所以需要安装证书,解决HTTPS请求的问题),也可以作为客户端与目标网站交互,可以获取到整个流程的所有明文数据。


函数介绍


了解了被动扫描原理后,再看下Yaklang提供了那些库函数可以实现上述流程,如图是hook库和mitm库


mitm.Start()可以让我们启动一个mitm server,通过mitm.callback()设置回调,所有的流量都会经过这个回调函数,这样我们就可以获取所有请求流量,然后调用mitm插件做漏洞扫描。


hook.NewMixPluginCaller()方法会创建一个manager,暂且将这个manager理解为插件管理对象吧,刚创建的manager是空的,需要通过LoadPlugin方法通过插件名加载插件。


下一步就是获取到所有mitm插件。yakit的插件仓库的本地插件都存在本地数据库中,所以我们可以调用db.YieldYakScriptAll()方法获取所有插件。例

println("所有MITM插件")
yakScriptsChan = db.YieldYakScriptAll()
for yakscript = range yakScriptsChan{
    if yakscript.Type == "mitm"{
        println(yakscript.ScriptName)
    }
}
// 所有MITM插件
// 参数发现
// Dog
// 被动指纹检测
// 基础 XSS 检测
// 敏感信息获取
// 基础 SQL 注入检测:No Protection
// ThinkPHP RCE 被动扫描
// SSRF HTTP Public
// Spring Actuator 敏感信息泄漏
// Shiro 指纹识别 + 弱密码检测
// ......


编写脚本


有了上述库函数的支持,我们就可以开始编写脚本了
首先创建一个manager

// 创建manager
manager, err = hook.NewMixPluginCaller()
if err != nil {
    log.Info("build mix plugin caller failed: %s", err)
    die(err)
}


获取所有插件,并加载到manager

// 从数据库获取所有插件
yakScriptsChan = db.YieldYakScriptAll()
// 筛选mitm插件
for yakscript = range yakScriptsChan{
    if yakscript.Type == "mitm"{
        manager.LoadPlugin(yakscript.ScriptName)
    }
}


启动MITM Server,这里使用的默认证书,也就是yakit的证书,免得再装证书了。

// 启动MITM Server
mitm.Start(8083,mitm.useDefaultCA(true),mitm.callback(
    func(isHttps,url,req,rsp){
       log.info("检测到请求: %s",url)
    },
))



运行脚本测试下yak test.yak
浏览器设置代理并访问百度,如图收到请求


镜像流量


发现回调函数是同步运行的,回调函数内的代码运行会导致网页请求卡住。在介绍被动扫描原理时说过,这里应该是镜像一份流量发送给被动扫描插件,所以这里需要做一些优化,目标是不影响mitm server做代理。

channel = make(chan []var)
for i = 0; i < 30; i+=1{
    go fn(){
       for c = range channel{
            isHttps,url,req,rsp = c
            log.info("检测到请求: %s",url)
       }
    }()
}
// 启动MITM Server
mitm.Start(port,mitm.useDefaultCA(true),mitm.callback(
    func(isHttps,url,req,rsp){
        channel <- [isHttps,url,req,rsp]
    },
))

调用MITM插件


manager.MirrorHTTPFlowEx(isScanPort,isHttps,url,req,rsp,body)方法可以调用所有已经加载的MITM插件,设置第一个参数可以启用端口扫描,剩余参数和MITM插件的参数一样。

// 因为回调函数的req和rsp类型是go的原生类型*http.Request和*http.Response类型
req,err = http.dump(req)
if err!= nil{
    log.error(err)
    return
}
rsp,err = http.dump(rsp)
if err!= nil{
    log.error(err)
    return
}
body,err = str.ExtractBodyFromHTTPResponseRaw(rsp)
if err!= nil{
    log.error(err)
    return
}
manager.MirrorHTTPFlowEx(false,isHttps,url,req,rsp,body)

优化日志信息


调用插件时发现有些MITM插件的输出使用yakit_ouput方法,不能在控制台输出,实际上yakit_ouput也是通过hook,将参数传给Feedback方法输出信息。manager提供了一个SetFeedback方法,通过自定义Feedback就可以自定义输出信息,如下:

manager.SetFeedback(func(i){
    msg = json.loads(i.Message)
    data = msg.content.data
    level = msg.content.level 
    switch msg.content.level{
    case "info":
        log.info(data)
    case "error":
        log.error(data)
    default:
        log.info("收到信息,不支持的信息类型: [%s] %s",level,data)
    }
})



最终脚本

yakit.AutoInitYakit()
// 设置日志级别
loglevel("info")
// 参数
port = cli.Int("port", cli.setRequired(true),cli.setDefault(8083))

// 创建manager
manager, err = hook.NewMixPluginCaller()
if err != nil {
    log.Info("build mix plugin caller failed: %s", err)
    die(err)
}
// 设置feedback
manager.SetFeedback(func(i){
    msg = json.loads(i.Message)
    data = msg.content.data
    level = msg.content.level 
    switch msg.content.level{
    case "info":
        log.info(data)
    case "error":
        log.error(data)
    default:
        log.info("收到信息,不支持的信息类型: [%s] %s",level,data)
    }
})
// 加载插件
yakScriptsChan = db.YieldYakScriptAll()
for yakscript = range yakScriptsChan{
    if yakscript.Type == "mitm"{
        manager.LoadPlugin(yakscript.ScriptName)
    }
}
// 启动MITM Server
channel = make(chan []var)
for i = 0; i < 30; i+=1{
    go fn(){
       for c = range channel{
            isHttps,url,req,rsp = c
            req,err = http.dump(req)
            if err!= nil{
                log.error(err)
                return
            }
            rsp,err = http.dump(rsp)
            if err!= nil{
                log.error(err)
                return
            }
            body,err = str.ExtractBodyFromHTTPResponseRaw(rsp)
            if err!= nil{
                log.error(err)
                return
            }
            manager.MirrorHTTPFlowEx(false,isHttps,url,req,rsp,body)
       }
    }()
}
// 启动MITM Server
mitm.Start(port,mitm.useDefaultCA(true),mitm.callback(
    func(isHttps,url,req,rsp){
        channel <- [isHttps,url,req,rsp]
    },
))



测试脚本


运行脚本,默认代理开在8083端口。跑出来的漏洞可以在Yakit的风险与漏洞中看,如图


总结


这个简陋的脚本只是一个演示,除了可以调用mitm插件,manager.MirrorHTTPFlowEx还可以调用Nuclei插件、Yak插件、端口扫描插件等,师傅们可以按需调用相应插件。

Yak官方资源

Yak 语言官方教程:
https://yaklang.com/docs/intro/
Yakit 视频教程:
https://space.bilibili.com/437503777
Github下载地址:
https://github.com/yaklang/yakit
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
https://yaklang.com/products/download_and_install
Yakit使用文档:
https://yaklang.com/products/intro/
常见问题速查:
https://yaklang.com/products/FAQ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值