当前位置:   article > 正文

安全能力基座Yakit,端口扫描又快又准!_yakit帮助文档

yakit帮助文档

安全能力基座Yakit,端口扫描又快又准!

背景

借助Yakit这个集成化工具平台的端口扫描相关能力,实现了准确快速且全面的端口扫描。并将过程在这里分享一下,望在诸君用到之时能有所帮助。

资产膨胀解决

我们在端口扫描的过程中,经常会遇到某些防火墙在单个ip上开放成百上千个端口,对扫描系统造成不小的压力,因此,在端口扫描工具设计之初就需要解决端口资产膨胀的问题。 而我对于这个问题的解决分两步:

1. 头尾冷门端口阈值

2. 常见端口开放数量阈值

第一步是对头尾冷门端口进行扫描,我选取的是1-5, 65530-65535。当开放的数量大于配置的阈值后,默认是存在防火墙端口膨胀情况。

  1. //扫描头尾,添加端口开放ip到排除名单
  2. println("\n--扫描头尾端口开放大于edgeAlive为排除项")
  3. exsyn := []string{}
  4. //内网ip
  5. if ipPriv != nil{
  6. res, err := synscan.Scan(ipPriv, "1-5,65530-65535",synscan.excludeHosts(exip),synscan.wait(3))
  7. die(err)
  8. for result := range res {
  9. exsyn = append(exsyn, result.Host)
  10. }
  11. }
  12. //外网ip
  13. if ipPub != nil{
  14. res, err := synscan.Scan(ipPub, "1-5,65530-65535",synscan.excludeHosts(exip),synscan.wait(3))
  15. die(err)
  16. for result := range res {
  17. exsyn = append(exsyn, result.Host)
  18. }
  19. }

第二步是对常见端口进行syn快速扫描。经过多次测试后,我选取了35+端口组成了top20,当top20开放数量大于配置阈值后,默认是存在防火墙端口膨胀情况。

  1. //syn扫描top20开放数量大于等于maxAlive添加到新排除项
  2. println("\n--扫描top20端口开放数量大于maxAlive为排除项")
  3. newh := 0
  4. exsyn := []string{}
  5. if ipPriv != nil{
  6. res, err := synscan.Scan(ipPriv, t20, synscan.excludeHosts(newexip),synscan.excludePorts(exPorts),synscan.wait(3))
  7. die(err)
  8. for result := range res {
  9. exsyn = append(exsyn,result.Host)
  10. }
  11. }
  12. if ipPub != nil{
  13. res, err := synscan.Scan(ipPub, t20, synscan.excludeHosts(newexip),synscan.excludePorts(exPorts),synscan.wait(3))
  14. die(err)
  15. exports := 0
  16. for result := range res {
  17. exsyn = append(exsyn,result.Host)
  18. }
  19. }

当初始化扫描匹配到了上述阈值后仅进行Top20 TCP扫描以减小端口膨胀造成的压力。

准确是第一目标

端口扫描过程中,准确肯定是扫描器的追求之一,尤其是对于Top端口来说,为了达到不漏掉关键端口,我对Top20,Top100分别进行TCP connect扫描。速度较SYN扫描来说偏慢,但是准确度较高。

  1. //top20 tcp扫描
  2. println("\n--top20 tcp扫描")
  3. res, err := servicescan.Scan(ips,t20,
  4. servicescan.active(true),
  5. //servicescan.all(),
  6. servicescan.web(),
  7. servicescan.proto("TCP"),
  8. servicescan.concurrent(cc),
  9. servicescan.excludeHosts(exip),
  10. servicescan.excludePorts(exPorts))
  11. die(err)

  1. //top100 tcp扫描
  2. println("\n--top100 tcp扫描")
  3. res, err := servicescan.Scan(ips,t100,
  4. servicescan.active(true),
  5. //servicescan.all(),
  6. servicescan.web(),
  7. servicescan.proto("TCP"),
  8. servicescan.concurrent(cc),
  9. servicescan.excludeHosts(newexip),
  10. servicescan.excludePorts(t20+","+exPorts))
  11. die(err)

快而全也要一手抓

快而全则是端口扫描的另一个追求,在较快的速度下发现开放的冷门端口。 针对top1000与全端口我采用了SYN+TCP的扫描模式,先使用SYN进行端口开放情况扫描,再使用TCP进行端口指纹识别。

  1. //top1000 扫描
  2. println("\n--top1000 SYN扫描")
  3. openResults := []
  4. if ipPriv != nil{
  5. res, err := synscan.Scan(ipPriv, t1000,
  6. synscan.excludeHosts(newexip),
  7. synscan.wait(5),
  8. synscan.excludePorts(t100+","+exPorts))
  9. die(err)
  10. for result := range res {
  11. openResults = append(openResults, result)
  12. //result.Show()
  13. }
  14. }
  15. if ipPub != nil{
  16. res, err := synscan.Scan(ipPub, t1000,
  17. synscan.excludeHosts(newexip),
  18. synscan.wait(5),
  19. synscan.excludePorts(t100+","+exPorts))
  20. die(err)
  21. for result := range res {
  22. openResults = append(openResults, result)
  23. //result.Show()
  24. }
  25. }

  1. println("\n--top1000 tcp扫描")
  2. res, err := servicescan.ScanFromSynResult(openResults,
  3. servicescan.active(true),
  4. //servicescan.all(),
  5. servicescan.web(),
  6. servicescan.proto("TCP"),
  7. servicescan.concurrent(cc))
  8. die(err)

命令行参数

扫描器需要足够的可控,所以设置了较多命令行参数,其中包括输入,排除,配置等。

  1. Usage:
  2. ___ ___ ___
  3. | | |\/| | | |__| | | |__
  4. | | | | |/\| | | | | |___
  5. Common Usage:
  6. yak.exe scan.yak --l ip.txt --xif xip.txt --xpf xports.txt
  7. yak.exe scan.yak --l ip.txt --xif xip.txt --xpf xports.txt --t 50
  8. yak.exe scan.yak --l ip.txt --xif xip.txt --xpf xports.txt --maxAlive 15 --edgeAlive 5
  9. yak.exe scan.yak --l ip.txt --xif xip.txt --xpf xports.txt --o output
  10. yak.exe scan.yak --l ip.txt
  11. yak.exe scan.yak --l ip.txt --jf
  12. yak.exe scan.yak --l ip.txt --lv t1000
  13. yak.exe scan.yak --l ip.txt --lv t1000 --p 1111,18822
  14. yak.exe scan.yak --i 127.0.0.1/24 --xif xip.txt
  15. yak.exe scan.yak --i 127.0.0.1/24 --x 127.0.0.1
  16. 扫描逻辑:
  17. 防止目标膨胀:
  18. 头尾扫描 --> top20syn --> 过滤
  19. 精确扫描重点端口:
  20. top20tcp --> top100tcp
  21. 快速扫描:
  22. top1000syn --> top1000tcp
  23. fullsyn --> fulltcp
  24. 常用结果提取:
  25. ipport|service|url|web_title|status_code|ssl_cert
  26. [OPTIONS]
  27. Flags:
  28. -h, --help Show help information
  29. --i string 扫描ip
  30. --l string 扫描ip文件
  31. --o string 输出文件夹, 默认为result
  32. --x string 排除的ip
  33. --xif string 排除的ip文件
  34. --xpf string 排除的端口文件
  35. --t int 扫描tcp并发数, 默认100
  36. --maxAlive int 最多允许top20的开放端口数(不包含), 避免防火墙造成的端口膨胀, 默认10
  37. --edgeAlive int 最多允许头尾10个端口开放数量(不包含), 避免防火墙造成的端口膨胀, 默认1
  38. --lv string 端口扫描级别: full, t20, t100, t1000, none, 默认为full, none仅扫描自定义端口
  39. --jf 跳过膨胀过滤扫描项
  40. --p port 指定目标端口,不能与--lv full一起使用

输出格式

对于端口扫描来说,好的输出格式一定是利于后续处理的。我选择生成三个文件,一个csv两个txt。 csv在常用端口信息的基础上加入https证书信息的获取:

而两个txt是最常用的ip:port 以及url:

url是在端口识别为http或ssl后才会生成

风险指纹识别

最后,在完成脚本的过程中发现,其实result里是可以轻松获取到http相关的返回值而无需进行再次请求的。那么,为何不把result内的http header/body 数据拿出来做一个风险指纹的匹配呢,既不会增加太多扫描时间,又能精确初步定位到一些高风险资产。

在设计中,为了快速进行匹配,我采取的指纹的数据结构为(*map*[string("特征")]string("名称")), 分别对header与body建立指纹库,在端口扫描识别到为web资产后进行指纹的匹配。

具体核心代码如下:

  1. //指纹库定义,仅列出两个举例
  2. BODY = make(map[string]string)
  3. BODY["Error 404--Not Found"] = "Weblogic"
  4. BODY["servletContextInitParams"] = "Spring env"
  5. HEADER = make(map[string]string)
  6. HEADER["deleteMe"] = "Shiro"
  7. HEADER["X-Jenkins"] = "Jenkins"
  8. //指纹识别函数
  9. getFp := func(hd,bd){
  10. fp := ""
  11. tmp_fp := []string{}
  12. for k,v := range HEADER{
  13. if str.Contains(hd, k){
  14. tmp_fp = append(tmp_fp,v)
  15. }
  16. }
  17. for k,v := range BODY{
  18. if str.Contains(bd, k){
  19. tmp_fp = append(tmp_fp,v)
  20. }
  21. }
  22. tmp_fp = str.RemoveRepeat(tmp_fp)
  23. fp = str.Join(tmp_fp,"|")
  24. return fp
  25. }

  1. //调用函数进行识别(注:result为端口扫描的结果result := range res)
  2. fp = ""
  3. parsehttp,e := str.ParseStringToHTTPResponse(result.Fingerprint.Banner)
  4. if e == nil{
  5. hd,_ := http.dumphead(parsehttp)
  6. bd := http.GetAllBody(parsehttp)
  7. fp = getFp(string(hd),string(bd))
  8. }

扫描结果的展示情况如下:

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/788116
推荐阅读
  

闽ICP备14008679号