如何搭建企业自己的扫描器(三)Tsunami 编写插件

29 篇文章 3 订阅

1、如何搭建企业自己的扫描器(一)谷歌 Tsunami(海啸)
2、如何搭建企业自己的扫描器(二)Tsunami 使用
从上面的教程中知道,tsunami扫描命令为:

java -cp "./tsunami-security-scanner/main/build/libs/tsunami-main-0.0.4-SNAPSHOT-cli.jar:/root/tsunami/tsunami-security-scanner-plugins/google/build/plugins/*" \
            -Dtsunami.config.location=./tsunami-security-scanner/tsunami.yaml \
        com.google.tsunami.main.cli.TsunamiCli \
        --ip-v4-target=127.0.0.1 \
        --scan-results-local-output-format=JSON \
    --scan-results-local-output-filename=./tsunami-result.json

其中/root/tsunami/tsunami-security-scanner-plugins/google/build/plugins/*为扫描插件所在目录,每个插件为一个jar包,默认插件如下(其中混入了一个我编写的):在这里插入图片描述
插件的主要类有两个,一个是MyWebserviceExposedUiDetector,另一个是MyWebserviceExposedUiDetectorBootstrapModule。

具体项目例子见https://github.com/5wimming/5wimming-security-scanner-plugins/tree/main/google/detectors/mine/mywebservice

先看下MyWebserviceExposedUiDetector,关键函数做了注释

/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.tsunami.plugins.detectors.exposedui.mywebservice;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.tsunami.common.net.http.HttpRequest.get;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.GoogleLogger;
import com.google.protobuf.util.Timestamps;
import com.google.tsunami.common.data.NetworkServiceUtils;
import com.google.tsunami.common.net.http.HttpClient;
import com.google.tsunami.common.net.http.HttpResponse;
import com.google.tsunami.common.time.UtcClock;
import com.google.tsunami.plugin.PluginType;
import com.google.tsunami.plugin.VulnDetector;
import com.google.tsunami.plugin.annotations.PluginInfo;
import com.google.tsunami.proto.DetectionReport;
import com.google.tsunami.proto.DetectionReportList;
import com.google.tsunami.proto.DetectionStatus;
import com.google.tsunami.proto.NetworkService;
import com.google.tsunami.proto.Severity;
import com.google.tsunami.proto.TargetInfo;
import com.google.tsunami.proto.Vulnerability;
import com.google.tsunami.proto.VulnerabilityId;
import java.io.IOException;
import java.time.Clock;
import java.time.Instant;
import javax.inject.Inject;

/** A {@link VulnDetector} that detects unauthenticated my webservice shell page. */
// 插件说明
@PluginInfo(
    type = PluginType.VULN_DETECTION,
    name = "MyWebserviceExposedUiDetector",
    version = "0.1",
    description =
        "This detector checks whether a unauthenticated my webservice is exposed. ",
    author = "5wiming",
    bootstrapModule = MyWebserviceExposedUiDetectorBootstrapModule.class)
public final class MyWebserviceExposedUiDetector implements VulnDetector {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private final Clock utcClock;
  private final HttpClient httpClient;

  @Inject
  public MyWebserviceExposedUiDetector(@UtcClock Clock utcClock, HttpClient httpClient) {
    this.utcClock = checkNotNull(utcClock);
    this.httpClient = checkNotNull(httpClient).modify().setFollowRedirects(false).build();
  }

  // 关键函数,检测入口
  @Override
  public DetectionReportList detect(
      TargetInfo targetInfo, ImmutableList<NetworkService> matchedServices) {
    logger.atInfo().log("Starting exposed ui detection for my webservice");
    return DetectionReportList.newBuilder()
        .addAllDetectionReports(
            matchedServices.stream()
                .filter(NetworkServiceUtils::isWebService) //判断是否为web服务
                .filter(this::isServiceVulnerable) //判断是否有漏洞
                .map(networkService -> buildDetectionReport(targetInfo, networkService)) //打印报告
                .collect(toImmutableList()))
        .build();
  }
  
  //漏洞检测函数
  private boolean isServiceVulnerable(NetworkService networkService) {
    String targetUri =
        NetworkServiceUtils.buildWebApplicationRootUrl(networkService) + "hello";
    try {
      // This is a blocking call.
      HttpResponse response =
          httpClient.send(get(targetUri).withEmptyHeaders().build(), networkService);
      return response.status().isSuccess()
          // TODO(b/147455413): checking string is not needed once we have plugin
          // matching logic.
          && response
              .bodyString()
              .map(
                  body ->
                      body.contains("5wimming"))
              .orElse(false);
    } catch (IOException e) {
      logger.atWarning().withCause(e).log("Unable to query '%s'.", targetUri);
      return false;
    }
  }

  //打印报告
  private DetectionReport buildDetectionReport(
      TargetInfo scannedTarget, NetworkService vulnerableNetworkService) {
    return DetectionReport.newBuilder()
        .setTargetInfo(scannedTarget)
        .setNetworkService(vulnerableNetworkService)
        .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(utcClock).toEpochMilli()))
        .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED)
        .setVulnerability(
            Vulnerability.newBuilder()
                .setMainId(
                    VulnerabilityId.newBuilder()
                        .setPublisher("5wimming")
                        .setValue("MY_WEBSERVICE_EXPOSED_UI"))
                .setSeverity(Severity.CRITICAL)
                .setTitle("my webservice Exposed Ui")
                // TODO(b/147455413): determine CVSS score.
                .setDescription("my webservice is not password or token protected"))
        .build();
  }
}

还有一个为引导类MyWebserviceExposedUiDetectorBootstrapModule,写上就行了,记得类名对上:

/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.tsunami.plugins.detectors.exposedui.mywebservice;

import com.google.tsunami.plugin.PluginBootstrapModule;

/** A {@link PluginBootstrapModule} for {@link MyWebserviceExposedUiDetector}. */
public final class MyWebserviceExposedUiDetectorBootstrapModule extends PluginBootstrapModule {

  @Override
  protected void configurePlugin() {
    registerPlugin(MyWebserviceExposedUiDetector.class);
  }
}

然后修改文件settings.gradle,即为你的插件jar包名字

rootProject.name = 'my_webservice_detect'

最后运行

./gradlew jar

可以在build/libs目录下找到该插件jar包。

扫描
在本地创建一个hello文件,然后内容含有5wimming字符串,并在同目录下启动一个web服务:

python3 -m http.server 8080

然后使用如下命令进行扫描,注意将刚才制造的插件jar包放在/root/tsunami/tsunami-security-scanner-plugins/google/build/plugins/下

java -cp "./tsunami-security-scanner/main/build/libs/tsunami-main-0.0.4-SNAPSHOT-cli.jar:/root/tsunami/tsunami-security-scanner-plugins/google/build/plugins/*" \
            -Dtsunami.config.location=./tsunami-security-scanner/tsunami.yaml \
        com.google.tsunami.main.cli.TsunamiCli \
        --ip-v4-target=127.0.0.1 \
        --scan-results-local-output-format=JSON \
    --scan-results-local-output-filename=./tsunami-result.json

扫描结果如下:

{
  "scanStatus": "SUCCEEDED",
  "scanFindings": [{
    "targetInfo": {
      "networkEndpoints": [{
        "type": "IP",
        "ipAddress": {
          "addressFamily": "IPV4",
          "address": "127.0.0.1"
        }
      }]
    },
    "networkService": {
      "networkEndpoint": {
        "type": "IP_PORT",
        "ipAddress": {
          "addressFamily": "IPV4",
          "address": "127.0.0.1"
        },
        "port": {
          "portNumber": 8080
        }
      },
      "transportProtocol": "TCP",
      "serviceName": "http",
      "software": {
        "name": "SimpleHTTPServer"
      },
      "versionSet": {
        "versions": [{
          "type": "NORMAL",
          "fullVersionString": "0.6"
        }]
      }
    },
    "vulnerability": {
      "mainId": {
        "publisher": "5wimming",
        "value": "MY_WEBSERVICE_EXPOSED_UI"
      },
      "severity": "CRITICAL",
      "title": "my webservice Exposed Ui",
      "description": "my webservice is not password or token protected"
    }
  }],
  "scanStartTimestamp": "2021-02-21T14:10:25.517Z",
  "scanDuration": "18.273s",
  "fullDetectionReports": {
    "detectionReports": [{
      "targetInfo": {
        "networkEndpoints": [{
          "type": "IP",
          "ipAddress": {
            "addressFamily": "IPV4",
            "address": "127.0.0.1"
          }
        }]
      },
      "networkService": {
        "networkEndpoint": {
          "type": "IP_PORT",
          "ipAddress": {
            "addressFamily": "IPV4",
            "address": "127.0.0.1"
          },
          "port": {
            "portNumber": 8080
          }
        },
        "transportProtocol": "TCP",
        "serviceName": "http",
        "software": {
          "name": "SimpleHTTPServer"
        },
        "versionSet": {
          "versions": [{
            "type": "NORMAL",
            "fullVersionString": "0.6"
          }]
        }
      },
      "detectionTimestamp": "2021-02-21T14:10:43.266Z",
      "detectionStatus": "VULNERABILITY_VERIFIED",
      "vulnerability": {
        "mainId": {
          "publisher": "5wimming",
          "value": "MY_WEBSERVICE_EXPOSED_UI"
        },
        "severity": "CRITICAL",
        "title": "my webservice Exposed Ui",
        "description": "my webservice is not password or token protected"
      }
    }]
  },
  "reconnaissanceReport": {
    "targetInfo": {
      "networkEndpoints": [{
        "type": "IP",
        "ipAddress": {
          "addressFamily": "IPV4",
          "address": "127.0.0.1"
        }
      }]
    },
    "networkServices": [{
      "networkEndpoint": {
        "type": "IP_PORT",
        "ipAddress": {
          "addressFamily": "IPV4",
          "address": "127.0.0.1"
        },
        "port": {
          "portNumber": 22
        }
      },
      "transportProtocol": "TCP",
      "serviceName": "ssh",
      "software": {
        "name": "OpenSSH"
      },
      "versionSet": {
        "versions": [{
          "type": "NORMAL",
          "fullVersionString": "7.6p1 Ubuntu 4ubuntu0.3"
        }]
      },
      "banner": ["SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3"]
    }, {
      "networkEndpoint": {
        "type": "IP_PORT",
        "ipAddress": {
          "addressFamily": "IPV4",
          "address": "127.0.0.1"
        },
        "port": {
          "portNumber": 8080
        }
      },
      "transportProtocol": "TCP",
      "serviceName": "http",
      "software": {
        "name": "SimpleHTTPServer"
      },
      "versionSet": {
        "versions": [{
          "type": "NORMAL",
          "fullVersionString": "0.6"
        }]
      }
    }]
  }
}

参考
https://github.com/5wimming/5wimming-security-scanner-plugins/tree/main/google/detectors/mine/mywebservice

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值