login using js error: undefined is not a constructor

leeh.chen's Avatar

leeh.chen

15 Mar, 2017 05:22 PM

Hi, I using Arachni scanning my site with a login script in js. Here is the command line:

arachni https://<mysite>.com --plugin=login_script:script='auth1.js'

and here is the js:

   document.getElementById('txtUserName_ION').value = 'Test1';
   document.getElementById('txtPWD_ION').value = 'pwd';
   document.getElementById('txtPP_ION').value = 'Test';
   document.getElementById('btnLogin_ION').submit();

Here is the outcome:

 [+] An error was encountered while executing the login script.

The content of log output has the following error:

[2017-03-15 12:51:31 -0400] Session: [utilities#exception_jail:428] [Selenium::WebDriver::Error::UnknownError] {"errorMessage":"undefined is not a constructor (evaluating 'window.document.getElementById('btnLogin_ION').submit()')","request":{"headers":{"Accept":"application/json","Accept-Encoding":"gzip;q=1.0,deflate;q=0.6,identity;q=0.3","Connection":"close","Content-Length":"303","Content-Type":"application/json; charset=utf-8","Host":"127.0.0.1:62783","User-Agent":"Ruby"},"httpVersion":"1.1","method":"POST","post":"{\"script\":\"    window.document.getElementById('txtUserName_ION').value = 'Test1';\\n    window.document.getElementById('txtPWD_ION').value = 'pwd';\\n    window.document.getElementById('txtPP_ION').value = 'Test';\\n\\n    window.document.getElementById('btnLogin_ION').submit();\",\"args\":[]}","url":"/execute","urlParsed":{"anchor":"","query":"","file":"execute","directory":"/","path":"/execute","relative":"/execute","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/execute","queryKey":{},"chunks":["execute"]},"urlOriginal":"/session/a2f2f150-099f-11e7-8c44-9b6427064cf1/execute"}} (org.openqa.selenium.WebDriverException)

I double checked the elements and they are correct. Any suggestions?
Thanks,

  1. Support Staff 1 Posted by Tasos Laskos on 16 Mar, 2017 11:02 AM

    Tasos Laskos's Avatar

    I could be mistaken, but buttons don't have a submit event, forms do; buttons you just click.
    Can you try altering your login script and retrying?

  2. 2 Posted by leeh.chen on 16 Mar, 2017 02:06 PM

    leeh.chen's Avatar

    You are right. I updated the script and now getting a different error:
    [2017-03-16 09:52:32 -0400] Login script: [components/plugins/login_script#set_status:99] No session check was provided, either via interface options or the script.

    It seems that this indicates no check specified. I actually did this through command line:
    arachni --checks=xss --plugin=login_script:script='auth1.js' https://

    After I tried in include more than one check: arachni --checks=xss,sql_injection --plugin=login_script:script='auth1.js' https://
    there is no error, but no scan either. Just this output:

    Arachni - Web Application Security Scanner Framework v1.5
    Author: Tasos "Zapotek" Laskos [email blocked]

           (With the support of the community and the Arachni Team.)
    

    Website: http://arachni-scanner.com Documentation: http://arachni-scanner.com/wiki

    [~] Available checks:

  3. Support Staff 3 Posted by Tasos Laskos on 16 Mar, 2017 06:29 PM

    Tasos Laskos's Avatar

    It's not about security checks, the system needs a session check in order to know if it has logged in successfully, see: https://github.com/Arachni/arachni/wiki/Command-line-user-interface...

  4. 4 Posted by leeh.chen on 17 Mar, 2017 06:31 PM

    leeh.chen's Avatar

    Thanks for clarification! I changed to not use browser and got an error like this:
    [2017-03-17 11:48:25 -0400] Session: [utilities#exception_jail:428] [NoMethodError] undefined method `content' for #<Arachni::HTTP::Response:0x0000000539dfc8>

    Here is the script:

    @base_url = "https://<myurl>"
    response = http.post( @base_url,
        parameters: {
            'username' => 'Test1',
            'password' => 'pwd',
            'pin' => 'Test'
        },
        mode: :sync,
        update_cookies: true
    )

    framework.options.session.check_url = to_absolute( response.headers.location, response.content.StartPageUrl )
    framework.options.session.check_pattern = /Sign out|User profile/

    Here is a successful login response using Fiddler:
    {"IsSuccessfulLogin":true,"MissingFields":[],"StartPageUrl":"/main/4eba4f35649e48f28e4e361d6e594022"}

    I am trying to make "https://<myurl>/main/4eba4f35649e48f28e4e361d6e594022" as the session check URL but the syntax is wrong. The GUID is different so can't hardcode. How should I specify framework.options.session.check_url?

    Thanks!

  5. 5 Posted by leeh.chen on 17 Mar, 2017 06:57 PM

    leeh.chen's Avatar

    Also tried this for session check, still failed on session check.

    framework.options.session.check_url = to_absolute( response.headers.location, response.url )
    framework.options.session.check_pattern = /Test Location/

    Here is the html element that only exist after login.
    <span>Test Location</span>

  6. Support Staff 6 Posted by Tasos Laskos on 17 Mar, 2017 07:01 PM

    Tasos Laskos's Avatar

    You need to parse the JSON response and get the StartPageUrl to set as the session checkk URL.
    Are you familiar with Ruby?

  7. 7 Posted by leeh.chen on 17 Mar, 2017 07:42 PM

    leeh.chen's Avatar

    Not familiar with Ruby :-(
    Is this something that needs importing some other packages? Any links will be appreciated.

  8. Support Staff 8 Posted by Tasos Laskos on 18 Mar, 2017 12:35 PM

    Tasos Laskos's Avatar

    Try this:

    framework.options.session.check_url = to_absolute( JSON.load( response.body )['StartPageUrl'], response.url )
    
  9. 9 Posted by leeh.chen on 20 Mar, 2017 09:20 PM

    leeh.chen's Avatar

    I tweak the code a little
    framework.options.session.check_url = to_absolute( ::JSON.parse(response.body)['StartPageUrl'], response.url )
    since the Jason gem lib is 1.8.6 which doesn't support parse. It worked to login by inspecting log.
    However, the session.check_pattern still failed:
    Here is the pattern:
    framework.options.session.check_pattern = /logout/
    also tried this:
    framework.options.session.check_pattern = /Sign out/

    The html contains the follow element:
    <li data-test="logout-link">Sign out</li>

    Here is the log result:
    2017-03-20 17:10:43 -0400] Login script: [components/plugins/login_script#set_status:99] The script was executed successfully, but the login check failed.

    Seem like we are very close to getting it work. What can be changed to achieve that?

  10. Support Staff 10 Posted by Tasos Laskos on 21 Mar, 2017 10:54 AM

    Tasos Laskos's Avatar

    Ah, Arachni has a class named JSON (irrelevant to the parser) that's why you had to use ::JSON, so that you'll call the JSON gem rather than Arachni's class.

    You're going to be checking the HTTP response though, it won't be loaded in a browser. Is that <li> a result of a subsequent AJAX request or it is actually returned in the HTTP response?

  11. 11 Posted by leeh.chen on 21 Mar, 2017 03:28 PM

    leeh.chen's Avatar

    The http response does contain the html element. I tried with some other terms such as "list" which also only exist after login. Still no luck. As a workaround, I did put /.*/ and it went on scanning. I understand the downside, just want to see the next stage.

    From the log, it seems that even though the login was successful, but the scan didn't go into authenticated site. Here is an example of the authenticated site: https://<myurl>/main/4eba4f35649e48f28e4e361d6e594022
    The scan kept going after https://<myurl>/ which unfortunately has no redirect to the authenticated end point. This seems to be caused by the command line I used:
    arachni https://<mysite>.com --plugin=login_script:script='auth1.js'
    How to specify to switch to the correct endpoint (with new GUID)?

  12. Support Staff 12 Posted by Tasos Laskos on 21 Mar, 2017 04:22 PM

    Tasos Laskos's Avatar

    Ok, I don't want to encourage people doing this, but in this case it's necessary:

    framework.push_to_url_queue( to_absolute( ::JSON.parse(response.body)['StartPageUrl'], response.url )  )
    
  13. Support Staff 13 Posted by Tasos Laskos on 21 Mar, 2017 04:25 PM

    Tasos Laskos's Avatar

    It just occurred to me, make sure that you don't get logged out (disable any logout links) ever, because due to its URL structure the scan will probably never end.

    From Arachni's perspective, a branch new site is created after every login.

    I'm assuming that everything lives under /main/4eba4f35649e48f28e4e361d6e594022/ and the hash changes after each login.

  14. 14 Posted by leeh.chen on 21 Mar, 2017 06:37 PM

    leeh.chen's Avatar

    push_to_url_queue does the trick! Just curious, why you don't recommend in general?

    Yes, everything is under /main/4eba4f35649e48f28e4e361d6e594022/ and the hash changes after each login.
    I added --scope-exclude-pattern=logout to prevent logout. It is still going. Will update when it finish.

  15. Support Staff 15 Posted by Tasos Laskos on 22 Mar, 2017 05:07 AM

    Tasos Laskos's Avatar

    It's not a good idea to mess with how Arachni processes its workload, especially from inside a login script since that's not its purpose, it's untidy.

  16. 16 Posted by leeh.chen on 22 Mar, 2017 02:29 PM

    leeh.chen's Avatar

    The scan finished in a few hours. There are still a few errors from the log file. Some are listed here:
    Maximum file size exceeded Timeout was reached
    invalid byte sequence in UTF-8
    The report has more issues so I think the scan is good.

  17. Support Staff 17 Posted by Tasos Laskos on 22 Mar, 2017 05:49 PM

    Tasos Laskos's Avatar
  18. Tasos Laskos closed this discussion on 22 Mar, 2017 05:49 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac