Selenium script

453 views
Skip to first unread message

Emy

unread,
Jul 18, 2022, 4:41:29 AM7/18/22
to OWASP ZAP User Group
Hello,

I have a Selenium script (written in JavaScript) which works without ZAP. I want to add it with ZAP so that it can discover how works my web application.

Unfortunately, I get this error :

The provided Selenium script (selenium_v3.js) does not implement the required interface.
Please refer to the provided templates for examples.jdk.nashorn.internal.runtime.ParserException: <eval>:44:7 Expected ) but found function
(async function selenium(driver){
       ^

I use the template available but I need to add my function with my Selenium tests (selenium(driver)) because my function must be asynchronous so that I can use the await keywords. This function is called in the browerLaunched(ssutils) function and the driver parameter is obtained by the ssutils.getWebDriver() function.

Do you know how can I do to add my Selenium script into ZAP ?

I use that with the automation framework with the weekly Docker image.

Thanks for your help !
Emy

Simon Bennetts

unread,
Jul 18, 2022, 8:06:37 AM7/18/22
to OWASP ZAP User Group
Hiya Emy,

So you have a standalone Selenium script which drives your app?
So does this launch its own browsers to do that?:
If not, how does it work?

Why do you want to add that script into ZAP?
ZAP supports scripting, but it does that so that those scripts can interact with ZAP.
I'm not currently sure why you need your script to interact with ZAP.

Cheers,

Simon
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Emy

unread,
Jul 18, 2022, 11:54:26 AM7/18/22
to OWASP ZAP User Group
Hi,

I have done a selenium script which works without ZAP. It opens a browser, goes on the web application and makes some tests. But I would like to add my script into ZAP so that ZAP can listen to these tests to analyze my web application. I need some tests because the AJAX Spider is not able to navigate and find forms, buttons...

My selenium script :
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const webdriver = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const proxy = require('selenium-webdriver/proxy');


let driver = new webdriver.Builder()
    .forBrowser('firefox')
    .usingServer('http://localhost:4444/wd/hub')
    .withCapabilities(webdriver.Capabilities.firefox())
    .setProxy(proxy.manual({http: '127.0.0.1:1111', bypass: ''}))
    .build();

(async function(){
    try{
        // Apply timeout for 15 seconds
        await driver.manage().setTimeouts( { implicit: 15000 } );
       
        // Navigate to url
        await driver.get('http://localhost:9000');

        //Création d'un projet
        console.log("Je veux créer un premier projet");
        await driver.findElement(webdriver.By.xpath("/html/body/jhi-main/ciri-navbar/header/nav/mat-toolbar/mat-toolbar-row/div/a[1]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/jhi-main/div/projects/mat-drawer-container/mat-drawer-content/div/div/div/div/button")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[1]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[1]/mat-form-field/div/div[1]/div/input")).sendKeys("Test1");
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[2]/mat-form-field/div/div[1]/div[3]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[2]/mat-form-field/div/div[1]/div[3]/textarea")).sendKeys("Ceci est le projet de tests numéro 1");
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[4]/div[2]/button")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[5]/div/div[3]/gridster/gridster-item")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[5]/div/div[4]/div/div/button")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[6]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[6]/mat-form-field/div/div[1]/div/input")).sendKeys("release");
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[7]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[7]/mat-form-field/div/div[1]/div/input")).sendKeys("cycle");  
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[8]/div[2]/button")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/div/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/div/mat-form-field/div/div[1]/div/input")).sendKeys("campagne");
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[1]/div[4]/gridster/gridster-item[1]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[1]/mat-step-header[2]/div[3]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/table/tbody/tr[1]/td[2]/input")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/table/tbody/tr[1]/td[2]/input")).sendKeys("équipement");
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/div[2]/div/button[2]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[3]/div[2]/div/button[2]")).click();
        //Attendre
        await driver.findElement(webdriver.By.className("bottom-right")).findElements(webdriver.By.className('toast-body')).then(async function(elements){
            while(elements.length != 0){
                var elements = await driver.findElement(webdriver.By.className("bottom-right")).findElements(webdriver.By.className('toast-body'))
                driver.sleep(1000);
            }      
        })
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-actions/button[2]")).click();
        await driver.findElement(webdriver.By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-actions/button[2]")).click();
        console.log("Premier projet créé");

        console.log("Fin du script Selenium");

    }
    finally{
        driver.quit();
        console.log("Browser closed");
    }
   
}());
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

I would like to add it into ZAP with the automation framework, like this :
  - type: script
    parameters:
      action: add                  
      type: selenium                    
      engine: Oracle Nashorn                  
      name: test_selenium.js                    
      file: "../../../.ZAP/scripts/scripts/selenium/test_selenium.js"

I tried to adapt my script so ZAP can run it (test_selenium.js) but my script doesn't implement the required interface :
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var By = Java.type('org.openqa.selenium.By');

function browserLaunched(utils) {
    logger("Début du script Selenium");
    var wd = utils.getWebDriver();
    wd.get(ihm);
    var url = utils.waitForURL(2000);
    logger('browserLaunched ' + utils.getBrowserId() + ' url: ' + url);
    logger("Proxy : " + utils.getProxyAddress() + ":" + utils.getProxyPort());
    if (url.startsWith(ihm)){
        selenium(wd);
    }
}

// Logging with the script name is super helpful!
function logger() {
    print('[' + this['zap.script.name'] + '] ' + arguments[0]);
}

(async function selenium(driver){
    try{
        // Apply timeout for 15 seconds
        await driver.manage().setTimeouts( { implicit: 15000 } );
       
        // Navigate to url
        await driver.get('http://localhost:9000');
        
        //Création d'un projet
        console.log("Je veux créer un premier projet");
        await driver.findElement(By.xpath("/html/body/jhi-main/ciri-navbar/header/nav/mat-toolbar/mat-toolbar-row/div/a[1]")).click();
        await driver.findElement(By.xpath("/html/body/jhi-main/div/projects/mat-drawer-container/mat-drawer-content/div/div/div/div/button")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[1]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[1]/mat-form-field/div/div[1]/div/input")).sendKeys("Test1");
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[2]/mat-form-field/div/div[1]/div[3]")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[2]/mat-form-field/div/div[1]/div[3]/textarea")).sendKeys("Ceci est le projet de tests numéro 1");
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[4]/div[2]/button")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[5]/div/div[3]/gridster/gridster-item")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[5]/div/div[4]/div/div/button")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[6]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[6]/mat-form-field/div/div[1]/div/input")).sendKeys("release");
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[7]/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[7]/mat-form-field/div/div[1]/div/input")).sendKeys("cycle");  
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-content/div[8]/div[2]/button")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/div/mat-form-field/div/div[1]/div")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/div/mat-form-field/div/div[1]/div/input")).sendKeys("campagne");
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[1]/div[4]/gridster/gridster-item[1]")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[1]/mat-step-header[2]/div[3]")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/table/tbody/tr[1]/td[2]/input")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/table/tbody/tr[1]/td[2]/input")).sendKeys("équipement");
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[2]/div[2]/div/button[2]")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-content/add-test-template/div/mat-stepper/div[2]/div[3]/div[2]/div/button[2]")).click();
        //Attendre
        await driver.findElement(By.className("bottom-right")).findElements(By.className('toast-body')).then(async function(elements){
            while(elements.length != 0){
                var elements = await driver.findElement(By.className("bottom-right")).findElements(By.className('toast-body'))
                driver.sleep(1000);
            }      
        })
        await driver.findElement(By.xpath("/html/body/div[1]/div[4]/div/mat-dialog-container/create-campaign/mat-dialog-actions/button[2]")).click();
        await driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/mat-dialog-container/create-project/mat-dialog-actions/button[2]")).click();
        console.log("Premier projet créé");

        console.log("Fin du script Selenium");

    }
    finally{
        driver.quit();
        console.log("Browser closed");
    }
   
}());
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Is it possible to adapt my script so ZAP can work ? Or do I need to find an other way to add my Selenium tests ?

Thanks,
Emy        

Simon Bennetts

unread,
Jul 19, 2022, 3:30:46 AM7/19/22
to OWASP ZAP User Group
Cool, thats what I thought.

ZAP cant directly run selenium scripts like this - it is not a completely general purpose scripting engine.
ZAP "selenium" scripts have a very specific purpose - they are for running scripts in browsers launched by ZAP, which is not what you want to do.

In order to run this script from the Automation Framework you need to create a simple Standalone script which runs your selenium script from the command line - you can test that out in the ZAP desktop.
You can then run the standalone script via a job and that will run your selenium script.
Make sure that the browsers your script launches are configured to proxy through ZAP.

Does that make sense?

Cheers,

Simon

Emy

unread,
Jul 19, 2022, 4:36:41 AM7/19/22
to OWASP ZAP User Group
Hey,

If I understand well, I need to create a standalone script which will run the command that will call my selenium script and my script will run. Then, ZAP will be able to listen to these tests because my selenium script will be configured to proxy. Is that right?

But I already tried to put a proxy on my selenium script which runs without ZAP and it didn't work because I don't find how to add the certificate provided by ZAP into the browser opened by my script.
This was what I tried where 127.0.0.1:1111 is my ZAP proxy:
let driver = new webdriver.Builder()
    .forBrowser('firefox')
    .usingServer('http://localhost:4444/wd/hub')
    .withCapabilities(webdriver.Capabilities.firefox())
    .setProxy(proxy.manual({http: '127.0.0.1:1111', bypass: ''}))
    .build();

Did I make a mistake?

Thank you!
Emy

Simon Bennetts

unread,
Jul 19, 2022, 8:50:50 AM7/19/22
to OWASP ZAP User Group
Hi Emy,

Thats right!

When we launch browsers from ZAP we configure them to ignore certificate warnings.
We set other options in that file so it might be work playing with those if you cant get it to work.
To speed up your testing you can leave ZAP running and then run your script with different options to see which combination works.

Let us know how you get on and if you hit any problems running your script this way.

Cheers,

Simon

Emy

unread,
Jul 21, 2022, 5:52:52 AM7/21/22
to OWASP ZAP User Group
Hi !

I managed to make my selenium script work so that ZAP can listen !
Here is how I set it up :
---------------------------------------------------------------------------------------------------------------------------------------------------------
const webdriver = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const proxy = require('selenium-webdriver/proxy');

let profile = new firefox.Options();
profile.setPreference("network.proxy.allow_hijacking_localhost", true);
profile.setPreference("network.captive-portal-service.enabled", false);
profile.setPreference("network.proxy.ssl", "127.0.0.1");
profile.setPreference("network.proxy.ssl_port", 1111);

var driver = new webdriver.Builder()

    .forBrowser('firefox')
    .usingServer('http://localhost:4444/wd/hub')
    .setFirefoxOptions(profile)
    .withCapabilities({'browserName': 'firefox', acceptSslCerts: true, acceptInsecureCerts: true})

    .setProxy(proxy.manual({http: '127.0.0.1:1111', bypass: ''}))
    .build();
------------------------------------------------------------------------------------------------------------------------------------------------------

But I still have a problem.
I would like to make a Python script so that I can run my selenium script from ZAP. But ZAP doesn't want to execute os commands.

For example, I tried to list files :
import os
os.system("ls")

When I run this standalone script, it doesn't display anything.

Do you know what could be the problem ? How can I solve it ?

Thank you,
Emy

Emy

unread,
Jul 22, 2022, 8:38:32 AM7/22/22
to OWASP ZAP User Group
To clarify: I have the same problem using the subProcess library

Simon Bennetts

unread,
Jul 22, 2022, 10:14:42 AM7/22/22
to OWASP ZAP User Group
Hi Emy,

I'll have a look at this asap...

Cheers,

Simon

Simon Bennetts

unread,
Jul 22, 2022, 10:19:42 AM7/22/22
to OWASP ZAP User Group
Hi Emy,

I've just tried this script in the ZAP desktop:

import os
os.system("ls")

And it worked fine for me .. but it output the result in the Eclipse console rather than the ZAP Scripts Console. I'm running the dev version of ZAP via Eclipse :)
You could try capturing the output, and/or writing it to a specific file?

Cheers,

Simon

Emy

unread,
Jul 25, 2022, 4:10:51 AM7/25/22
to OWASP ZAP User Group
Hi Simon,

My script works well now using the graphical interface thanks to your help! Thank you!

But when I use the weekly image, I get this error which I don't understand:

07:59:55.244 INFO [ActiveSessionFactory.lambda$apply$11] - Matched factory org.openqa.selenium.grid.session.remote.ServicedSession$Factory (provider: org.openqa.selenium.firefox.GeckoDriverService)
(node:877) UnhandledPromiseRejectionWarning: SessionNotCreatedError: Unable to create new service: GeckoDriverService
Build info: version: '4.0.0-alpha-2', revision: 'f148142cf8', time: '2019-07-01T21:30:10'
System info: host: '14f62959cf78', ip: '172.17.0.2', os.name: 'Linux', os.arch: 'amd64', os.version: '5.4.0-121-generic', java.version: '11.0.15'
Driver info: driver.version: unknown
    at Object.checkLegacyResponse (/zap/wrk/node_modules/selenium-webdriver/lib/error.js:558:15)
    at parseHttpResponse (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:581:13)
    at Executor.execute (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:514:28)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:877) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:877) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:877) UnhandledPromiseRejectionWarning: SessionNotCreatedError: Unable to create new service: GeckoDriverService
Build info: version: '4.0.0-alpha-2', revision: 'f148142cf8', time: '2019-07-01T21:30:10'
System info: host: '14f62959cf78', ip: '172.17.0.2', os.name: 'Linux', os.arch: 'amd64', os.version: '5.4.0-121-generic', java.version: '11.0.15'
Driver info: driver.version: unknown
    at Object.checkLegacyResponse (/zap/wrk/node_modules/selenium-webdriver/lib/error.js:558:15)
    at parseHttpResponse (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:581:13)
    at Executor.execute (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:514:28)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(node:877) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:877) UnhandledPromiseRejectionWarning: SessionNotCreatedError: Unable to create new service: GeckoDriverService
Build info: version: '4.0.0-alpha-2', revision: 'f148142cf8', time: '2019-07-01T21:30:10'
System info: host: '14f62959cf78', ip: '172.17.0.2', os.name: 'Linux', os.arch: 'amd64', os.version: '5.4.0-121-generic', java.version: '11.0.15'
Driver info: driver.version: unknown
    at Object.checkLegacyResponse (/zap/wrk/node_modules/selenium-webdriver/lib/error.js:558:15)
    at parseHttpResponse (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:581:13)
    at Executor.execute (/zap/wrk/node_modules/selenium-webdriver/lib/http.js:514:28)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(node:877) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)


Do you know what could be the problem?

There is something weird in the weekly image : my standalone python script always print messages 2 times like this:

Job script started
Job: script Start action: run
Hello world
Hello world
Job Script finished

But I think that it's just the print function which shows messages 2 times because with my python script which runs my Selenium script, it runs the selenium server only one time so I think that it's not a problem (I hope).

Thanks,
Emy
Reply all
Reply to author
Forward
0 new messages