JavaScript / Authentication / Handle CAS authentication

1,546 views
Skip to first unread message

Thiago Porciúncula

unread,
Nov 19, 2015, 6:04:13 AM11/19/15
to OWASP ZAP Scripts
Hi,

We've been working a lot with ZAP here at Softplan and our first challenge was to be able to run an authenticated attack on applications that use CAS. This script is the solution we came up with.

When working with CAS, a single POST request with the credentials is not enough to trigger the authentication. When we GET the login page, some input values used by CAS are generated (the login ticket and some Spring Web Flow related parameters), and they must be included in the POST request for the authentication to work. So the script basically sends a GET to the login page, parses its response looking for the values generated by CAS and sends a POST request with these values and the credentials.

This is enough to trigger the authentication, but it's not enough to enable a successfull authenticated scan with ZAP. There is one more step needed because of redirects: CAS loves them and ZAP doesn't. More details on that can be found in the comments within the script.

Reauthentication works and a good way to achieve this is with a Logged Out Regex as something like "\QLocation: http://your.domain/cas-server/\E.*". Unauthenticated responses will be 302 redirects to the CAS server, so this is the easiest way to identifiy that there was a redirection to the CAS server and thus the user is not logged in.

Here's a step-by-step guide on how to use it:
- Import the script in ZAP;
- Include your target to a ZAP context;
- Set the script-based authentication method for that context;
- Fill the login URL with the CAS server login page (i.e. http://your.domain/cas-server/login);
- Provide one protected page for each application that will be analyzed separated by comma (i.e. http://your.domain/your-app/protected/index.html);
- Optionally define any extra post data that is needed to be sent to your application in the login POST request;
- Optionally provide a logged in/out regex (i.e. \QLocation: http://your.domain/cas-server/\E. as the logged out regex);
- Create an user providing his username and password;
- Activate Forced User Mode or run the Spider/Active Scan as the user you just created.

Any suggestions will be deeply appreciated, specially those related to the last step of the script.

Here is the script, by the way:

Simon Bennetts

unread,
Nov 20, 2015, 7:43:21 AM11/20/15
to OWASP ZAP Scripts
Very nice!
How about submitting it to https://github.com/zaproxy/community-scripts ?

Many thanks,

Simon

Thiago Porciúncula

unread,
Nov 20, 2015, 10:57:12 AM11/20/15
to OWASP ZAP Scripts
I've just submitted! :)

thc...@gmail.com

unread,
Nov 20, 2015, 10:58:05 AM11/20/15
to zaproxy...@googlegroups.com
Hi.

Would you mind raising an issue? It should be possible for the
authentication scripts to configure how the messages are sent (e.g.
enable "allow circular redirections" [1]).
(Maybe even exposing the HttpSender instance?)

That would make the workflow a little easier.


Regarding the spider, when you say "explicitly" what does that mean? The
redirection is not followed? Not followed immediately?
The spider should be following redirections...


[1]
https://github.com/zaproxy/zaproxy/blob/b3b7a3fa544b00ee25685d7f3538c055d513623d/src/org/parosproxy/paros/network/HttpSender.java#L797

Best regards.

On 19/11/15 11:04, Thiago Porciúncula wrote:
> Hi,
>
> We've been working a lot with ZAP here at Softplan and our first
> challenge was to be able to run an authenticated attack on applications
> that use CAS <http://jasig.github.io/cas/4.1.x/index.html>. This script
> --
> You received this message because you are subscribed to the Google
> Groups "OWASP ZAP Scripts" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to zaproxy-scrip...@googlegroups.com
> <mailto:zaproxy-scrip...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.

Thiago Porciúncula

unread,
Nov 20, 2015, 4:11:55 PM11/20/15
to OWASP ZAP Scripts
Hi,

Sure, I'll raise the issue. Exposing the HttpSender instance seems to be good and I'll be glad to get rid of the reflection in my script. And I just realized I could've used this setAllowCircularRedirects() method instead of getting the HttpClient instance from the HttpSender. Once the issue I raise is fixed I'll update the script.


And regarding the Spider, when I say "explicitly", I mean this. I didn't look further to understand how the redirections are manually handled, but this is what would happen with me:

- Authentication is done and the user is authenticated;
- The Spider access the first protected page (page A) and gets a redirect response to the CAS server;
- The Spider never really get to see page A's content (I can tell that because the Spider wouldn't visit pages referenced by page A).

Maybe the Spider visits the CAS server later, but since it didn't follow that redirect, this time the CAS server won't redirect the Spider back to page A, as it would if the Spider had followed the redirect right away. However, had the Spider followed the redirect right away, it would've been a circular redirect and ZAP would've complained. Maybe it had something to do with that fact that the CAS server was out of my context.

I'm not sure, but the workaround for that was to make sure a protected page is accessed once before the Spider start working, so I don't need to worry about these redirects :)

Have a nice weekend!

Thiago Porciúncula

unread,
Nov 20, 2015, 4:28:21 PM11/20/15
to OWASP ZAP Scripts

ryerson...@gmail.com

unread,
Nov 24, 2015, 2:15:01 PM11/24/15
to OWASP ZAP Scripts
I've been playing around with the script, great job and thank you very much for sharing! I was wondering where the referrer request data comes into play? According to the history log, ZAP is successfully authenticating into CAS but is not redirecting to my desired url because the spider fails to explore any nodes.

Thiago Porciúncula

unread,
Nov 25, 2015, 5:10:26 AM11/25/15
to OWASP ZAP Scripts
What do you mean by referrer request data?

Are you providing a protected page to the script? If a protected page is not accessed at least once before the Spider starts, the first (protected) page the Spider access won't be spidered, since it will be a redirect response to the CAS server.

It might be a good idea to print the response content of the last POST performed by the script (variable post) just to make sure the script is, in fact, successfully authenticating. When ZAP says "Authentication successful.", it means the script run with no error, but that doesn't necessarily means that the authentication was successful.

ryerson...@gmail.com

unread,
Nov 25, 2015, 11:35:53 AM11/25/15
to OWASP ZAP Scripts
Let me just explain how CAS works for us.

This is my site tree in ZAP
  • Sites
    • apps1.test.domain.ca
      • testapp
        • Get:login
        • Get:j_spring_cas_security_check(ticket)
    • cas.test.domain.ca
      • GET:login(renew,service)
      • POST:login(renew,service)(_eventId,execution,lt,password,submit,username)
CAS for us is configured to require authentication verification on each app.

Say i have 2 apps: apps1.test.domain.ca/testapp and apps1.test.domain.ca/fakeapp, both will require to authentication.

  1. Go to URL: apps1.test.domain.ca/testapp
  2. Redirects me to https://cas.test.domain.ca/login?service=https%3A%2F%2Fapps1.test.domain.ca%2Ftestapp%2Fj_spring_cas_security_check&renew=true
    • This is CAS now asking for username and password, the parameters above include the url of the app that requested authentication and upon successful authentication will redirect back to it.
  3. Authenticated into apps1.test.domain.ca/testapp
This might be different from your setup or similar?

I am not sure what you mean by protected page, are you simply referring to a page that is behind authentication? Example: apps1.test.domain.ca/testapp/admin/index.html

I noticed that as well, ZAP was saying that Authentication was successful, I will do as you suggest and print out the POST.

ryerson...@gmail.com

unread,
Nov 25, 2015, 11:37:49 AM11/25/15
to OWASP ZAP Scripts
One last thing: I included testapp into my context, do i need to include cas.test.domain.ca into that same context as well?

Thiago Porciúncula

unread,
Nov 25, 2015, 11:46:42 AM11/25/15
to OWASP ZAP Scripts
This is exactly how CAS works for me, too :)

And yes, by "protected page" I mean a page that is behind authentication. A page that, upon access, will redirect you to the CAS server (if you haven't authenticated yet).

And also, no, the CAS server doesn't need to be included into the context.


If things don't work out for you, post here all the parameters you're using to feed the script so I can try to have a clue of what might be going wrong.

ryerson...@gmail.com

unread,
Nov 25, 2015, 11:52:16 AM11/25/15
to OWASP ZAP Scripts
[1] https://cas.test.domain.ca/login will NOT log me into testapp.


However if i use [2] as the loginURL: then the script returns

lt=undefined
execution=undefined
_eventId=undefined

. . 

In terms of [1] thought, the post and authentication is successful into the CAS portal but in case of the testapp, it doesn't matter because the configuration is set to require to authenticate again, as such [2] is required as the url with the referred request data.

ryerson...@gmail.com

unread,
Nov 25, 2015, 11:53:49 AM11/25/15
to OWASP ZAP Scripts
Thank you!

Thiago Porciúncula

unread,
Nov 25, 2015, 11:58:44 AM11/25/15
to OWASP ZAP Scripts
So, if you manually access https://cas.test.domain.ca/login and login, and then access your app, you'll have to perform the login again? Because that's what ZAP and the script will do.

ryerson...@gmail.com

unread,
Nov 25, 2015, 12:15:57 PM11/25/15
to OWASP ZAP Scripts
Yes.

You access the app first, which will redirect you to a cas login page [1], once authenticated that will use the data from the query string and use the field "service" and it's value to redirect you back along with a ticket that the app will use to confirm that authentication has been successful!


[1] is the encoded get request to cas

These are both for the loginURL, the ended version returns undefined which i believe is a ZAP bug because it isn't accepting URL Escape Codes, can a ZAP team member confirm the format of the field and if it requires escape codes or no?

---

If on the other hand, as you suggest:

Access https://cas.test.domain.ca/login and login, this will only grant you access to the portal and some apps whereas others such as the one i am trying to access will force you as an added security measure to login again by redirecting you to [1] even though you already logged in. I have no control over this, it's on an app to app basis and up to the discretion of the developer :(

Cheers.

Thiago Porciúncula

unread,
Nov 25, 2015, 12:34:24 PM11/25/15
to OWASP ZAP Scripts
Thank you for the throughout answer. So, there is a difference between our CAS applications after all :)

It seems that the single sign on is disabled on your CAS server (at least for this specific application).

What happens if you feed the script with a login URL including the service query string? I'll run some tests here and will get back to you soon.

ryerson...@gmail.com

unread,
Nov 25, 2015, 12:46:00 PM11/25/15
to OWASP ZAP Scripts
Test 1)

Result of script:
lt=undefined
execution=undefined
_eventId=undefined

Test 2)

Result of script:
 
get: verified that it gets the right page.
lt=has value
execution=has value
_eventId=has value
post:  is empty, nothing displayed here

So i have confirmed that the loginURL cannot use URL escape characters, i printed out the get request and verified that it is hitting the proper CAS login page :D however, the post is empty as i mentioned above.

Thiago Porciúncula

unread,
Nov 25, 2015, 12:57:06 PM11/25/15
to OWASP ZAP Scripts
Thank you for the tests!

So it seems the script doesn't support (yet!) non single sign on CAS applications... I wonder if this is because Paro's HttpMessage might not support query strings. I'll have to run some tests and do some debugging.

As soon as I have good (or bad) news, I'll post them here.

Best regards.

ryerson...@gmail.com

unread,
Nov 25, 2015, 1:07:59 PM11/25/15
to OWASP ZAP Scripts
Thank you!

thc...@gmail.com

unread,
Nov 25, 2015, 1:42:55 PM11/25/15
to zaproxy...@googlegroups.com
Hi.

The script expects the "loginUrl" in decoded form (as given by the
second parameter, which says that the URI is not encoded).

Best regards.

On 25/11/15 17:15, ryerson...@gmail.com wrote:
> Yes.
>
> You access the app first, which will redirect you to a cas login page
> [1], once authenticated that will use the data from the query string and
> use the field "service" and it's value to redirect you back along with a
> ticket that the app will use to confirm that authentication has been
> successful!
>
> [1] https://cas.test.domain.ca/login?service=https%3A%2F%2Fapps1.test.domain.ca%2Ftestapp%2Fj_spring_cas_security_check&renew=true
> <https://cas.domain.ca/login?service=https%3A%2F%2Ftest.domain.ca%2Ftestapp%2Fj_spring_cas_security_check&renew=true>
>
> [1] is the encoded get request to cas
> [2] decoded
> request: https://cas.test.domain.ca/login?service=https://apps1.test.domain.ca/testapp/j_spring_cas_security_check&renew=true
>
> These are both for the loginURL, the ended version returns undefined
> which i believe is a ZAP bug because it isn't accepting URL Escape
> Codes, can a ZAP team member confirm the format of the field and if it
> requires escape codes or no?
>
> ---
>
> If on the other hand, as you suggest:
>
> Access https://cas.test.domain.ca/login
> <https://cas.domain.ca/login?service=https%3A%2F%2Ftest.domain.ca%2Ftestapp%2Fj_spring_cas_security_check&renew=true> and
> login, this will only grant you access to the portal and some apps
> whereas others such as the one i am trying to access will force you as
> an added security measure to login again by redirecting you to [1] even
> though you already logged in. I have no control over this, it's on an
> app to app basis and up to the discretion of the developer :(
>
> Cheers.
>
> On Wednesday, November 25, 2015 at 11:58:44 AM UTC-5, Thiago Porciúncula
> wrote:
>
> So, if you manually access https://cas.test.domain.ca/login
> <https://cas.domain.ca/login?service=https%3A%2F%2Ftest.domain.ca%2Ftestapp%2Fj_spring_cas_security_check&renew=true> and
> login, and then access your app, you'll have to perform the login
> again? Because that's what ZAP and the script will do.
>
> --
> You received this message because you are subscribed to the Google
> Groups "OWASP ZAP Scripts" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to zaproxy-scrip...@googlegroups.com
> <mailto:zaproxy-scrip...@googlegroups.com>.

Thiago Porciúncula

unread,
Nov 26, 2015, 6:54:32 AM11/26/15
to OWASP ZAP Scripts
What version of CAS are you using? For not so new versions (like the one I use, 4.0.3), even when SSO is disabled, the first accessed application after a successful login at the CAS server (without the service query string) wouldn't require another authentication. Anyways, newer versions of CAS have changed, and for now the script doesn't work for them if SSO is not enabled.


This is how I'm sending the POST to authenticated:

post.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.POST, loginUri, HttpHeader.HTTP10));
post.setRequestBody(requestBody);
helper.sendAndReceive(post);

If we check HttpRequestHeader's constructor, we clearly see how the query strings from the loginUri are completely ignored. So we simply need a way to make sure our query strings are not ignored.

There is a method within HttpMessage that seems to be our guy: setGetParams(). I've created a new gist with a new version of the script calling this method with a hard coded parameter. I'd really apreciate it if you could test it :)

Here is the gist:

Thank you!

On Wednesday, November 25, 2015 at 4:07:59 PM UTC-2, ryerson...@gmail.com wrote:
Thank you!

ryerson...@gmail.com

unread,
Nov 26, 2015, 11:43:37 AM11/26/15
to OWASP ZAP Scripts
Good morning,

Not sure about CAS version, will let you know asap.

extraPostData: 

The print out of the POST: is empty, not sure if it's hitting an empty page or an empty post. is there any way for me to debug or add breakpoints into the JS?
Message has been deleted
Message has been deleted

Thiago Porciúncula

unread,
Nov 26, 2015, 12:17:35 PM11/26/15
to OWASP ZAP Scripts
Any extra POST data can be inserted into the extraPostData parameter (like ticket=ticketValue). For the tests with the new script, the loginUrl should not include any query strings, those are hard coded into the script here.

Try again with the loginUrl as https://cas.test.domain.ca/login and let me know what happens (using the new script). I have some obstacles preventing me from updating my CAS version, so since I can't seem to reproduce your problem, I can't run any tests here :(

On Thursday, November 26, 2015 at 3:05:20 PM UTC-2, ryerson...@gmail.com wrote:
j_spring_cas_security_check page also get's a parameter called ticket via POST, where would that get included?

The request to the page looks like this:

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Cookie: JSESSIONID=uniquejsessionidtoken
Connection: keep-alive

and the Response

HTTP/1.1 302 Found
Date: Tue, 24 Nov 2015 16:43:31 GMT
Content-Length: 0
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/plain; charset=UTF-8

ryerson...@gmail.com

unread,
Nov 26, 2015, 12:23:13 PM11/26/15
to OWASP ZAP Scripts
I just deleted the old post because i was adding more details haha. :(

Ticket refers to "CAS generated service ticket used to validate

The problem is that for us, cas.test.domain.ca/login is different from cas.test.domain.ca/login?query_string

just cas.test.domain.ca/login will never authenticate into this app because the pages are different.

The very first page hit has to be either

testapp which will redirect to cas.test.domain.ca/login?query_string

because this will generate a CAS ticket to go along with the LT which validates that this user for this specific app has request authentication.

From my understanding, will confirm once the guy who handles CAS comes in :S

ryerson...@gmail.com

unread,
Nov 26, 2015, 12:24:29 PM11/26/15
to OWASP ZAP Scripts
To answer your question, the same thing as before happens, i am able to log into CAS but it won't redirect to testapp and similarly, i am not logged into testapp because cas.test.domain.ca/login can't be used to authenticate into it :(

ryerson...@gmail.com

unread,
Nov 26, 2015, 12:32:08 PM11/26/15
to OWASP ZAP Scripts
Let me get back to you in 2 hours or so, i am waiting for a colleague to get in who can explain our CAS workflow to me better. :)

Thiago Porciúncula

unread,
Nov 26, 2015, 12:35:14 PM11/26/15
to OWASP ZAP Scripts
Even though loginUrl is just https://cas.test.domain.ca/login in these last tests, I'm adding the query strings within my script. I understand the loginUrl must include the query strings. You've used the last version of the script, right? Did you check if the query strings I'm adding there are correct for your case?

I guess I'll have to figure a way to get a new version of CAS, disable SSO and finally be able to reproduce your problem.
Message has been deleted

ryerson...@gmail.com

unread,
Nov 26, 2015, 1:01:15 PM11/26/15
to OWASP ZAP Scripts
Yes, i used the version you linked me. I also tried loginUrl is just https://cas.test.domain.ca/login which does not redirect me to the testapp even thought you added the query string with the script :(.

I have a print("get body: " + get.getResponseBody().toString() + "\n");
is there any way to for me to print out the URL of that get? I want to confirm that the FIRST get is hitting

Thiago Porciúncula

unread,
Nov 26, 2015, 1:04:21 PM11/26/15
to OWASP ZAP Scripts
The first GET is definitely not considering the query strings, I added them only to the POST message. This might be an issue, indeed.

I just updated the gist. Now both messages are (supposedly) using the query strings. Make sure the query strings are correct!

BTW, get.getResponseHeader() 

Thiago Porciúncula

unread,
Nov 26, 2015, 1:07:39 PM11/26/15
to OWASP ZAP Scripts
I sent the message before finishing it. I meant that you can call get.getRequestHeader().getURI(). This should tell you if the query strings are being included or not (and you can do that to the post as well).

ryerson...@gmail.com

unread,
Nov 26, 2015, 1:11:37 PM11/26/15
to OWASP ZAP Scripts
Haha, i just figured it out myself as well!

I used     print("get req head: " + get.getRequestHeader().toString() + "\n");

It is using the wrong URL, for my case it has to consider the query string as well. Will try now :D

ryerson...@gmail.com

unread,
Nov 26, 2015, 2:01:54 PM11/26/15
to OWASP ZAP Scripts
I think i found out why it doesn't work :D I'm missing a few steps.

So, the workflow is such that.


post request body: along with my username, password, lt, eventID, excecution

which NOW responds with post response header:
HTTP/1.1 302 Moved Temporarily
Date: Thu, 26 Nov 2015 18:26:15 GMT
Pragma: no-cache
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache
Cache-Control: no-store
Set-Cookie: cookie data
Set-Cookie:cookie data
Content-Length: 0
Connection: close
Content-Type: text/plain; charset=UTF-8
Set-Cookie: cookie data 
Set-Cookie: cookie data

This location now becomes the NEW REQUEST and it's response will be  https://apps1.test.domain.ca/testapp/login.html

login.html is the main page.

so the script once it gets the post response header, needs to redirect to the location and use that requests response to finish auth.

Did i make any sense? 
Message has been deleted

thc...@gmail.com

unread,
Nov 26, 2015, 2:28:02 PM11/26/15
to zaproxy...@googlegroups.com
Hi.

The query parameters are not being ignored, they are kept in the
request-uri (mUri).

Setting the query parameters with method setGetParams has the same
effect as passing them with the parameter uri of the mentioned constructor.

Best regards.

On 26/11/15 11:54, Thiago Porciúncula wrote:
> What version of CAS are you using? For not so new versions (like the one
> I use, 4.0.3), even when SSO is disabled, the first accessed application
> after a successful login at the CAS server (without the service query
> string) wouldn't require another authentication. Anyways, newer versions
> of CAS have changed, and for now the script doesn't work for them if SSO
> is not enabled.
>
>
> This is how I'm sending the POST to authenticated:
>
> post.setRequestHeader(new HttpRequestHeader(HttpRequestHeader.POST,
> loginUri, HttpHeader.HTTP10));
> post.setRequestBody(requestBody);
> helper.sendAndReceive(post);
>
> If we check HttpRequestHeader
> <https://github.com/zaproxy/zaproxy/blob/develop/src/org/parosproxy/paros/network/HttpRequestHeader.java#L153>'s
> constructor
> <https://github.com/zaproxy/zaproxy/blob/develop/src/org/parosproxy/paros/network/HttpRequestHeader.java#L153>,
> we clearly see how the query strings from the loginUri are completely
> ignored. So we simply need a way to make sure our query strings are not
> ignored.
>
> There is a method within HttpMessage that seems to be our
> guy: setGetParams(). I've created a new gist with a new version of the
> script calling this method with a hard coded parameter. I'd really
> apreciate it if you could test it :)
>
> Here is the gist:
> https://gist.github.com/tfcporciuncula/8e7dfe7fa9e92ff0a90d
>
> Thank you!
>
> On Wednesday, November 25, 2015 at 4:07:59 PM UTC-2,
> ryerson...@gmail.com wrote:
>
> Thank you!
>

ryerson...@gmail.com

unread,
Nov 26, 2015, 2:46:47 PM11/26/15
to OWASP ZAP Scripts
@thc202 Ahh, that's really good to know! Thanks :D

@Thiago Porciúncula
Once you get the response https://apps1.test.domain.ca/testapp/j_spring_cas_security_check?ticket=unique_ticket

CAS side is done and it has authenticated, now it is just not redirecting to  https://apps1.test.domain.ca/testapp/login.html

---

to create a new request whose response would then be https://apps1.test.domain.ca/testapp/login.html or is this a step that is meant to be handled with

client.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, false);
client.getParams().setParameter(HttpClientParams.ALLOW_CIRCULAR_REDIRECTS, true);

ryerson...@gmail.com

unread,
Nov 26, 2015, 3:06:44 PM11/26/15
to OWASP ZAP Scripts
@Thiago Porciúncula CAS version version is 3.5.1 haha =D

Thiago Porciúncula

unread,
Nov 26, 2015, 3:20:06 PM11/26/15
to OWASP ZAP Scripts
@thc202 Thank you for the clarification!

@ryerson I thought older versions of CAS wouldn't require a new authentication for the first app regardless of SSO, but there is probably more configuration beneath it.

So, the authentication is working?

I do have some questions and tests to run. I'm too used to the flow: login at the CAS server with no query strings -> access app -> good to go. I'm not sure about what CAS does when you login pointing to a server. But I thought it would create you a service ticket (ST) right away and you would be good to go too.

I'm calling it a day but I'll be back tomorrow.

ryerson...@gmail.com

unread,
Nov 26, 2015, 3:25:40 PM11/26/15
to OWASP ZAP Scripts
Thanks a lot for the help mate, much appreciated. Made a lot of progress and now i understand more clearly what's going on with CAS and authentication via the script :D  I'll be back on Tuesday!

ryerson...@gmail.com

unread,
Nov 26, 2015, 4:08:55 PM11/26/15
to OWASP ZAP Scripts
I GOT IT! =D

I am running a spider right now and it is traversing the website, I am done for the day so i'll let it run. I have to do some code clean up and add some error handling, but i'll re-post the modified version that is working for me first thing Tuesday!

Thiago Porciúncula

unread,
Nov 27, 2015, 5:26:43 AM11/27/15
to OWASP ZAP Scripts
Awesome! I'm so glad to hear it! :)))

And I'm looking forward to see what you've done.

ryerson...@gmail.com

unread,
Dec 1, 2015, 12:26:01 PM12/1/15
to OWASP ZAP Scripts
Let's say I have the following.

My Application has following path
https://www.mywebsite.com/MyWebApp

Let's say there is a JSP file

https://www.mywebsite.com/MyWebApp/protected/index.jsp

and I need to retrieve

https://www.mywebsite.com/MyWebApp 


How do I actually retrieve the application name "MyWebApp"? Is there a function part of HTTP Message or ZAP that i can use to decode the URI into it's various parts?


fyi: script works great, just making some fine tuning and trying to get rid of the hard coded values :D

Thiago Porciúncula

unread,
Dec 1, 2015, 12:52:44 PM12/1/15
to OWASP ZAP Scripts
Hmm... I'm not sure I completely get your point.

Maybe you could show us the not so fine tuned version of the script so we can see what you mean. Also, you can always externalize values as parameters to get rid of the hard coded value.
Message has been deleted
Message has been deleted
Message has been deleted

ryerson...@gmail.com

unread,
Dec 1, 2015, 2:46:22 PM12/1/15
to OWASP ZAP Scripts
This is the not so fine tuned version but it works, it will expire in a day and i'll upload a better version. The redirects are explicit. Protected page is not needed except to obtain the application name. If you have any questions, please feel free to ask.

Sorry it's taking me so long to update this, lots on my plate today :(

Please copy paste the link because clicking on it, loads an older version for some reason: http://pastebin.com/qPcT6Nne
Message has been deleted

ryerson...@gmail.com

unread,
Dec 2, 2015, 12:04:10 PM12/2/15
to OWASP ZAP Scripts
I am trying to do that just, externalize some of the values as parameters. It seems rather strange thought that I have to tell zap to follow the redirects since it isn't following them on it's own :( It just gets stuck on the response, they aren't even circular redirects in this case.

Thiago Porciúncula

unread,
Dec 2, 2015, 12:47:29 PM12/2/15
to OWASP ZAP Scripts
You can ask ZAP to follow the redirects!

There is an overloaded version of the sendAndReceive method from the helper object that includes a second boolean parameter indicating whether to follow the redirects or not.


I hope that helps.

ryerson...@gmail.com

unread,
Dec 2, 2015, 12:52:48 PM12/2/15
to OWASP ZAP Scripts
I had seen that and tried myself but it wasn't following them which is why i had to explicitly created my own requests as you seen in the pastebin code above :(

I'll play around with it some more this afternoon and try to optimize the script, but i can't argue with results. I'm just glad it works! Thanks a lot for all your help!

ryerson...@gmail.com

unread,
Dec 8, 2015, 2:36:25 PM12/8/15
to OWASP ZAP Scripts
Using script based authentication for CAS

1) Does this script still require a regex pattern to identify the logged in response? I have a button logout with text 'logout' so i used .*\Qlogout\E.* as my regex

2) Similarly are there any pages that should be excluded from the spider/scanner? Maybe the logout.html?

Thanks! Cheers Goran.

Thiago Porciúncula

unread,
Dec 8, 2015, 3:22:25 PM12/8/15
to OWASP ZAP Scripts
Answering both questions: A logged in/out pattern is not required. It is a good idea, though, since it makes sure ZAP will always be authenticated (i.e. if the logged in pattern doesn't match, ZAP will perform authentication again). However, if you have a logout button, you can also exclude it from the scan so ZAP will never click on it (never logging out).

These are two different strategies to ensure ZAP's scan will be authenticated. None of them are required, but they are essential to make sure ZAP doesn't log itself out during the scan. They can be used together, but normally one is enough.

You should run some tests and use whatever gives you the best results :)

I normally tend to have better results excluding the logout button, but that's not always possible. The logged in/out pattern is more robust, though. If, for instance, you kill the session ZAP is using (i.e. by accidentally logging into the system with the same user), ZAP will be able to realize it's not logged in anymore and perform the authentication again.

Kong

unread,
Jul 19, 2017, 2:30:47 AM7/19/17
to OWASP ZAP Scripts
Hello,

I'm following your post to handle ZAP with CAS:

https://groups.google.com/forum/#!msg/zaproxy-scripts/a7Tv8VE5C4Q/6tWCRPLyBgAJ


Issue:

===

CAS has authenticated, but not redirecting to my app: https://webapp1.eg.com/login.action.
which is not enough to enable a successfull authenticated scan with ZAP. Any idea?

below is ZAP request and response, when i doing spider:
===

request:
POST https://cas.eg.com/cas/login?service=https://webapp1.eg.com/login.action

response:
 location: https://webapp1.eg.com/login.action?ticket=ST-30298-KjvPH23tcCrndegF5xx





On Thursday, November 19, 2015 at 3:04:13 AM UTC-8, Thiago Porciúncula wrote:
Hi,

We've been working a lot with ZAP here at Softplan and our first challenge was to be able to run an authenticated attack on applications that use CAS. This script is the solution we came up with.

When working with CAS, a single POST request with the credentials is not enough to trigger the authentication. When we GET the login page, some input values used by CAS are generated (the login ticket and some Spring Web Flow related parameters), and they must be included in the POST request for the authentication to work. So the script basically sends a GET to the login page, parses its response looking for the values generated by CAS and sends a POST request with these values and the credentials.

This is enough to trigger the authentication, but it's not enough to enable a successfull authenticated scan with ZAP. There is one more step needed because of redirects: CAS loves them and ZAP doesn't. More details on that can be found in the comments within the script.

Reauthentication works and a good way to achieve this is with a Logged Out Regex as something like "\QLocation: http://your.domain/cas-server/\E.*". Unauthenticated responses will be 302 redirects to the CAS server, so this is the easiest way to identifiy that there was a redirection to the CAS server and thus the user is not logged in.

Here's a step-by-step guide on how to use it:
- Import the script in ZAP;
- Include your target to a ZAP context;
- Set the script-based authentication method for that context;
- Fill the login URL with the CAS server login page (i.e. http://your.domain/cas-server/login);
- Provide one protected page for each application that will be analyzed separated by comma (i.e. http://your.domain/your-app/protected/index.html);
- Optionally define any extra post data that is needed to be sent to your application in the login POST request;
- Optionally provide a logged in/out regex (i.e. \QLocation: http://your.domain/cas-server/\E. as the logged out regex);
- Create an user providing his username and password;
- Activate Forced User Mode or run the Spider/Active Scan as the user you just created.

Any suggestions will be deeply appreciated, specially those related to the last step of the script.

Here is the script, by the way:

Daniel Panizo Montaño

unread,
Dec 4, 2017, 7:55:25 AM12/4/17
to OWASP ZAP Scripts

Good morning.
Sorry for the necroposting; but we are really stuck in a Cas Auth, and we are unable to make the script run properly.
Our application is divided in a very similar way like the other users.
The application is using a SSO authentication by calling CAS. After providing ZAP with the entry point url, it redirects to the CAS, authenticates correctly (CAS ticker obtained), and redirect us again to the aplication’s internal pages.

After the redirection takes place, the ZAP spider is not able to scan the internal pages from the URL stated at the script configuration, then creating a circular loop of re-authentication attempts which generated new sessions all the time.

 

This is the basic sketch of what we see:

·         Sites

o  cas.domain.es:8888

        • Cac
          • contactdata
            • Get:login
          • services
            • Get:j_spring_cas_security_check(ticket)

o  apps2.test.domain.com

        • GET:aplication
        • aplication
          • GET:inicio
        • inicio
          • GET:inicioAplicacion.action
        • services
          • GET:j_spring_cas_security_check(ticket)

 

When we make the login; the app redirects us to the SSO, and after the authentication it redirects again to the protected pages of the app. When we do a manual scan with zap it register the directory flawlessly, but when we try to launch a crawler or a active scan with the script it can't handle the authentication and doesn't reach to the directory ubications it should, and seems like the script it's stuck with the session management and it runs again and again creating a lot of sessions.

At this point we have tried different aproachs to the problem, changing various parameters in the script authentication configuration. We tried
:

 

-       Different addresses for the protected pages;

 

-       Setting of the parameters in encoded form (as suggested by another user in the forum) and in a plane text form,

 

-       Using a regex pattern in a url form and different coded strings (^(?=.*[A-Za-z0-9]$)[A-Za-z][A-Za-z\d.-]{0,19}$).

After testing all the aforementioned things the script looks like working in a way that it takes the session data and shows it in the command sequence console of zap ( a script Post with the username, password, lt, execution and eventId) and indicates that the CAS authentication script has finished. But looks like the script runs over and over (in an endless loop) creating different sessions each time.


 

Besides, the crawler isn’t deploying the tree correctly, getting usually stuck in a session authentication loop.

At this point we have read a lot of threads in various forums about this problem, but seems like we are unable to hit the nail on the head.

 

Anyone has a suggestion of why could this been failing?

And another thing. ¿The script modified by ryerson is available somewhere?








El jueves, 19 de noviembre de 2015, 12:04:13 (UTC+1), Thiago Porciúncula escribió:
Hi,

We've been working a lot with ZAP here at Softplan and our first challenge was to be able to run an authenticated attack on applications that use CAS. This script is the solution we came up with.

When working with CAS, a single POST request with
...

kingthorin+owaspzap

unread,
Dec 4, 2017, 11:44:53 AM12/4/17
to OWASP ZAP Scripts
I don't think this is the updated script but these still might be something here that gets you going (by example, etc):
https://github.com/zaproxy/community-scripts/tree/master/authentication

Daniel Panizo Montaño

unread,
Dec 4, 2017, 12:00:16 PM12/4/17
to OWASP ZAP Scripts
Yeah i know, that's the page from where i picked the script. But no luck with that.
Reply all
Reply to author
Forward
0 new messages