|
1 | 1 | # Writing a Tsunami detector
|
2 | 2 |
|
3 |
| -## Overview |
| 3 | +Welcome to the Tsunami community, we are thrilled that you want to contribute. |
| 4 | +This guide will help you get started with writing a Tsunami detector. |
4 | 5 |
|
5 |
| -Each Tsunami detector needs the following pieces which we will create in this |
6 |
| -tutorial: |
| 6 | +There are several ways to write a Tsunami detector: |
7 | 7 |
|
8 |
| -* A plugin name that is unique among all enabled Tsunami plugins. |
9 |
| -* A set of build rules for [Gradle](https://gradle.org/) (external build) |
10 |
| -* A `VulnDetector` that implements the vulnerability detection logic. |
11 |
| -* A `PluginBootstrapModule` that provides necessary Guice bindings for the |
12 |
| - detector. |
13 |
| -* An optional `CliOption` that captures all the supported command line flags |
14 |
| - for the detector. |
15 |
| -* An optional `ConfigProperties` that captures all the supported configuration |
16 |
| - for the detector. |
17 |
| - |
18 |
| -## 1. Fork the examples |
19 |
| - |
20 |
| -Tsunami provides a few example implementations of a `VulnDetector` plugin. The |
21 |
| -examples live in the |
22 |
| -[examples directory](https://github.com/google/tsunami-security-scanner-plugins/tree/master/examples) |
23 |
| - |
24 |
| -* Update Java package names. The example `VulnDetector` plugin is defined |
25 |
| - under `com.google.tsunami.plugins.example` package. Refactor the package and |
26 |
| - class name according to your detector implementation. |
27 |
| -* Give a meaningful description to the Gradle build rule at `build.gradle`. We |
28 |
| - will work on the Gradle build rule later. |
29 |
| -* Rewrite the `README.md` file to have a good explanation of your |
30 |
| - `VulnDetector` plugin. |
31 |
| - |
32 |
| -## 2. Putting the detector together |
33 |
| - |
34 |
| -### 2.a - `PluginInfo` annotation |
35 |
| - |
36 |
| -All Tsunami plugins must be annotated by the `PluginInfo` annotation. Otherwise |
37 |
| -it cannot be identified by Tsunami scanner at runtime. This annotation provides |
38 |
| -the general information about the plugin to the core scanner. |
39 |
| - |
40 |
| -Following is an example usage of the `PluginInfo` annotation from our |
41 |
| -`WordPressInstallPageDetector`. |
42 |
| - |
43 |
| -```java |
44 |
| -@PluginInfo( |
45 |
| - // VULN_DETECTION PluginType is required for a VulnDetector plugin. |
46 |
| - type = PluginType.VULN_DETECTION, |
47 |
| - // This gives a human readable name for your VulnDetector. Can be different |
48 |
| - // from your class name. |
49 |
| - name = "WordPressInstallPageDetector", |
50 |
| - // The current version of your plugin. |
51 |
| - version = "0.1", |
52 |
| - // A detailed description about what this plugin does. |
53 |
| - description = |
54 |
| - "This detector checks whether a WordPress install is unfinished. An unfinished WordPress" |
55 |
| - + " installation exposes the /wp-admin/install.php page, which allows attacker to set" |
56 |
| - + " the admin password and possibly compromise the system.", |
57 |
| - // The author of this plugin. |
58 |
| - author = "Tsunami Team ([email protected])", |
59 |
| - // The guice module that bootstraps this plugin. |
60 |
| - bootstrapModule = WordPressInstallPageDetectorBootstrapModule.class) |
61 |
| -``` |
62 |
| - |
63 |
| -### 2.b - Define the `VulnDetector` plugin |
64 |
| - |
65 |
| -Each vulnerability detector plugin is an implementation of the `VulnDetector` |
66 |
| -interface. For this step we only explain the placeholder code, later you'll need |
67 |
| -to provide implementations for the class itself. |
68 |
| - |
69 |
| -Following is an example placeholder code from the |
70 |
| -`WordPressInstallPageDetector`: |
71 |
| - |
72 |
| -```java |
73 |
| -// ... |
74 |
| -// annotations |
75 |
| -// ... |
76 |
| -public final class WordPressInstallPageDetector implements VulnDetector { |
77 |
| - // See https://github.com/google/flogger for details. |
78 |
| - private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); |
79 |
| - |
80 |
| - // Tsunami uses Guice (https://github.com/google/guice) to manage the |
81 |
| - // dependencies. |
82 |
| - @Inject |
83 |
| - WordPressInstallPageDetector( |
84 |
| - // Tsunami provides a UtcClock for production and FakeUtcClock for |
85 |
| - // testing purposes. |
86 |
| - @UtcClock Clock utcClock, |
87 |
| - // You can also inject other useful dependencies to your plugin code, e.g. |
88 |
| - // inject HttpClient if you need to interact with a web server. |
89 |
| - HttpClient httpClient) { |
90 |
| - } |
91 |
| - |
92 |
| - // The entrypoint of the VulnDetector. We will explain this later. |
93 |
| - @Override |
94 |
| - public DetectionReportList detect( |
95 |
| - TargetInfo targetInfo, ImmutableList<NetworkService> matchedServices) { |
96 |
| - // implement me. |
97 |
| - } |
98 |
| -} |
99 |
| -``` |
100 |
| - |
101 |
| -### 2.c - Implement the main detection logic |
102 |
| - |
103 |
| -The main logic of the detection is expected to happen in the `detect` method, |
104 |
| -which expects two arguments: |
105 |
| - |
106 |
| -1. [The `TargetInfo` proto](https://github.com/google/tsunami-security-scanner/blob/master/proto/reconnaissance.proto). |
107 |
| - This proto contains information that were gathered during the fingerprinting |
108 |
| - and discovery phase. |
109 |
| -1. [The `NetworkService` list](https://github.com/google/tsunami-security-scanner/blob/master/proto/network_service.proto). |
110 |
| - This list contains all the identified network services that match the |
111 |
| - service filtering annotations. |
112 |
| - |
113 |
| -The main detection logic usually iterates over all the elements of the |
114 |
| -`matchedServices` parameter and checks whether the `NetworkService` is |
115 |
| -vulnerable to the vulnerability your plugin checks for. If any service is |
116 |
| -vulnerable, you'll need to build a `DetectionReport` proto that explains the |
117 |
| -identified vulnerability. |
118 |
| - |
119 |
| -Following is an example implementation from our `WordPressInstallPageDetector`: |
120 |
| - |
121 |
| -```java |
122 |
| -@Override |
123 |
| -public DetectionReportList detect( |
124 |
| - TargetInfo targetInfo, ImmutableList<NetworkService> matchedServices) { |
125 |
| - return DetectionReportList.newBuilder() |
126 |
| - .addAllDetectionReports( |
127 |
| - matchedServices.stream() |
128 |
| - // The WordPressInstallPageDetector only works for web services. |
129 |
| - .filter(NetworkServiceUtils::isWebService) |
130 |
| - // Detection logic that checks whether a web service exposes |
131 |
| - // a wordpress installation page. Omitted here for simplicity. |
132 |
| - .filter(this::isServiceVulnerable) |
133 |
| - // Build a DetectionReport when the web service is vulnerable. |
134 |
| - .map(networkService -> buildDetectionReport(targetInfo, networkService)) |
135 |
| - .collect(toImmutableList())) |
136 |
| - .build(); |
137 |
| -} |
138 |
| - |
139 |
| -private DetectionReport buildDetectionReport( |
140 |
| - TargetInfo scannedTarget, NetworkService vulnerableNetworkService) { |
141 |
| - return DetectionReport.newBuilder() |
142 |
| - .setTargetInfo(scannedTarget) |
143 |
| - .setNetworkService(vulnerableNetworkService) |
144 |
| - .setDetectionTimestamp(Timestamps.fromMillis(Instant.now(utcClock).toEpochMilli())) |
145 |
| - .setDetectionStatus(DetectionStatus.VULNERABILITY_VERIFIED) |
146 |
| - .setVulnerability( |
147 |
| - Vulnerability.newBuilder() |
148 |
| - .setMainId( |
149 |
| - VulnerabilityId.newBuilder() |
150 |
| - .setPublisher("GOOGLE") |
151 |
| - .setValue("UNFINISHED_WORD_PRESS_INSTALLATION")) |
152 |
| - .setSeverity(Severity.CRITICAL) |
153 |
| - .setTitle("Unfinished WordPress Installation") |
154 |
| - .setDescription( |
155 |
| - "An unfinished WordPress installation exposes the /wp-admin/install.php page," |
156 |
| - + " which allows attacker to set the admin password and possibly" |
157 |
| - + " compromise the system.")) |
158 |
| - .build(); |
159 |
| -} |
160 |
| -``` |
161 |
| - |
162 |
| -## 3. Preparing the `PluginBootstrapModule` |
163 |
| - |
164 |
| -Each Tsunami plugin must have a companion `PluginBootstrapModule` that provides |
165 |
| -the required Guice bindings and registers the plugin to the core engine. |
166 |
| - |
167 |
| -Creating a `PluginBootstrampModule` is rather simple if you only need to |
168 |
| -register the plugin. You only need to call `registerPlugin` within the |
169 |
| -`configurePlugin` method (e.g. |
170 |
| -[`ExampleVulnDetectorBootstrapModule`](https://github.com/google/tsunami-security-scanner-plugins/tree/master/examples/example_vuln_detector/src/main/java/com/google/tsunami/plugins/example/ExampleVulnDetectorBootstrapModule.java)). |
171 |
| - |
172 |
| -A more complete example is the |
173 |
| -[GenericWeakCredentialDetectorBootstrapModule](https://github.com/google/tsunami-security-scanner-plugins/blob/master/google/detectors/credentials/generic_weak_credential_detector/src/main/java/com/google/tsunami/plugins/detectors/credentials/genericweakcredentialdetector/GenericWeakCredentialDetectorBootstrapModule.java) |
| 8 | +* Using our custom configuration format (coming soon) |
| 9 | +* [Using Java]({{ site.baseurl }}/howto/new-detector/new-detector-java) |
| 10 | +* Using Python (not documented yet) |
0 commit comments