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