Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kotlin scripting addon #2442

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions addOns/kotlin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog
All notable changes to this add-on will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased

- Kotlin scripting for the JVM
27 changes: 27 additions & 0 deletions addOns/kotlin/kotlin.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import org.zaproxy.gradle.addon.AddOnStatus

plugins {
kotlin("jvm") version "1.3.50"
}

version = "1.0.0"
description = "Allows Kotlin to be used for ZAP scripting - (some) templates included"

zapAddOn {
addOnName.set("Kotlin Support")
addOnStatus.set(AddOnStatus.ALPHA)
zapVersion.set("2.9.0")

manifest {
author.set("StackHawk Engineering")
}
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable")
implementation("org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable")
implementation("org.jetbrains.kotlin:kotlin-script-util")

testImplementation(project(":testutils"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2020 The ZAP Development Team
*
* 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 org.zaproxy.zap.extension.kotlin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.*;
import org.apache.log4j.Logger;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.extension.Extension;
import org.parosproxy.paros.extension.ExtensionAdaptor;
import org.parosproxy.paros.extension.ExtensionHook;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.ZAP;
import org.zaproxy.zap.control.AddOnLoader;
import org.zaproxy.zap.control.ExtensionFactory;
import org.zaproxy.zap.extension.script.ExtensionScript;

public class ExtensionKotlin extends ExtensionAdaptor {

public static final String NAME = "ExtensionKotlin";
public static final int EXTENSION_ORDER = 9999;
public static final ImageIcon KOTLIN_ICON;
private static final List<Class<? extends Extension>> EXTENSION_DEPENDENCIES;
private static final Logger LOGGER = Logger.getLogger(ExtensionKotlin.class);

static {
List<Class<? extends Extension>> dependencies = new ArrayList<>(1);
dependencies.add(ExtensionScript.class);
EXTENSION_DEPENDENCIES = Collections.unmodifiableList(dependencies);

KOTLIN_ICON =
View.isInitialised()
? new ImageIcon(
ExtensionKotlin.class.getResource(
"/org/zaproxy/zap/extension/kotlin/resources/kotlin.png"))
: null;
}

public ExtensionKotlin() {
super(NAME);
setOrder(EXTENSION_ORDER);
}

@Override
public void hook(ExtensionHook extensionHook) {
super.hook(extensionHook);

LOGGER.debug("Hooking Kotlin Scripting Extension");
String zapJar = ZAP.class.getProtectionDomain().getCodeSource().getLocation().getFile();

LOGGER.debug("Loading Kotlin engine...");
AddOnLoader addonLoader = ExtensionFactory.getAddOnLoader();
Arrays.stream(addonLoader.getURLs()).forEach(LOGGER::debug);
KotlinScriptEngineFactory factory = new KotlinScriptEngineFactory(addonLoader, zapJar);
getExtScript().registerScriptEngineWrapper(new KotlinEngineWrapper(factory));
LOGGER.debug("Kotlin engine loaded.");
}

public List<Class<? extends Extension>> getDependencies() {
return EXTENSION_DEPENDENCIES;
}

private ExtensionScript getExtScript() {
return Control.getSingleton().getExtensionLoader().getExtension(ExtensionScript.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2020 The ZAP Development Team
*
* 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 org.zaproxy.zap.extension.kotlin;

import java.util.Collections;
import java.util.List;
import javax.script.ScriptEngineFactory;
import javax.swing.*;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.zaproxy.zap.extension.script.DefaultEngineWrapper;

public class KotlinEngineWrapper extends DefaultEngineWrapper {

@Override
public ImageIcon getIcon() {
return ExtensionKotlin.KOTLIN_ICON;
}

@Override
public String getSyntaxStyle() {
return SyntaxConstants.SYNTAX_STYLE_NONE;
}

@Override
public boolean isRawEngine() {
return false;
}

@Override
public List<String> getExtensions() {
return Collections.singletonList("kts");
}

public KotlinEngineWrapper(ScriptEngineFactory factory) {
super(factory);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2020 The ZAP Development Team
*
* 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 org.zaproxy.zap.extension.kotlin;

import java.io.File;
import java.util.List;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import kotlin.jvm.JvmClassMappingKt;
import kotlin.reflect.KClass;
import kotlin.script.experimental.jvm.util.JvmClasspathUtilKt;
import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase;
import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes;
import org.jetbrains.kotlin.script.jsr223.KotlinJsr223JvmLocalScriptEngine;
import org.jetbrains.kotlin.script.jsr223.KotlinStandardJsr223ScriptTemplate;

public class KotlinScriptEngineFactory extends KotlinJsr223JvmScriptEngineFactoryBase {

private final List<File> jars;

public KotlinScriptEngineFactory(ClassLoader classLoader, String zapJar) {
List<File> clJars =
JvmClasspathUtilKt.scriptCompilationClasspathFromContextOrStdlib(
new String[] {"kotlin-stdlib"}, classLoader, true);
if (zapJar != null) {
clJars.add(new File(zapJar));
}
jars = clJars;
}

@Override
public ScriptEngine getScriptEngine() {
return new KotlinJsr223JvmLocalScriptEngine(
this,
jars,
KotlinStandardJsr223ScriptTemplate.class.getName(),
(ctx, types) ->
new ScriptArgsWithTypes(
new Bindings[] {ctx.getBindings(ScriptContext.ENGINE_SCOPE)},
types),
new KClass<?>[] {JvmClassMappingKt.getKotlinClass(Bindings.class)});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kotlin.desc=Allows Kotlin to be used for ZAP scripting
kotlin.options.title=Kotlin
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import org.apache.commons.httpclient.URI
import org.parosproxy.paros.network.HttpHeader
import org.parosproxy.paros.network.HttpMessage
import org.parosproxy.paros.network.HttpRequestHeader
import org.zaproxy.zap.authentication.AuthenticationHelper
import org.zaproxy.zap.authentication.GenericAuthenticationCredentials

val PARAM_TARGET_URL = "targetUrl"

fun authenticate(
helper: AuthenticationHelper,
paramsValues: Map<String, String>,
credentials: GenericAuthenticationCredentials): HttpMessage {

println("Kotlin auth template")

println("TARGET_URL: ${paramsValues[PARAM_TARGET_URL]}")
val msg = helper.prepareMessage()
msg.requestHeader = HttpRequestHeader(HttpRequestHeader.GET, URI(paramsValues[PARAM_TARGET_URL], true),
HttpHeader.HTTP11)
println("msg: $msg ${msg.requestHeader.headers.size}")
msg.requestHeader.headers.forEach { println(it) }
helper.sendAndReceive(msg)
return msg
}

fun getRequiredParamsNames(): Array<String> {
return arrayOf(PARAM_TARGET_URL)
}

fun getOptionalParamsNames(): Array<String> {
return arrayOf()
}

fun getCredentialsParamsNames(): Array<String> {
return arrayOf("username", "password")
}

fun getLoggedInIndicator(): String {
return "Sign Out"
}

fun getLoggedOutIndicator(): String {
return "Sign In"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
println("KaaKaawwtlin!!")


Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2020 The ZAP Development Team
*
* 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 org.zaproxy.zap.extension.kotlin;

import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.script.Compilable;
import javax.script.CompiledScript;
import org.junit.jupiter.api.BeforeAll;
import org.zaproxy.zap.testutils.AbstractVerifyScriptTemplates;

/** Verifies that the Kotlin script templates are parsed without errors. */
public class VerifyScriptTemplates extends AbstractVerifyScriptTemplates {

private static Compilable se;

@BeforeAll
public static void setUp() {
se =
(Compilable)
new KotlinScriptEngineFactory(
Thread.currentThread().getContextClassLoader(), null)
.getScriptEngine();
}

@Override
protected String getScriptExtension() {
return ".kts";
}

@Override
protected void parseTemplate(Path template) throws Exception {
try (Reader reader = Files.newBufferedReader(template, StandardCharsets.UTF_8)) {
CompiledScript cs = se.compile(reader);
cs.eval();
}
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ var addOns = listOf(
"jruby",
"jsonview",
"jython",
"kotlin",
"onlineMenu",
"openapi",
"plugnhack",
Expand Down