WebSockets in OWASP ZAP

610 views
Skip to first unread message

Wojciech Kopec

unread,
May 11, 2022, 9:25:11 AM5/11/22
to OWASP ZAP User Group
Recently I run ZAP scan against application that is mostly using WebSockets communication along with few REST endpoints.

Scan was performed after proxying long E2E tests through ZAP to build extensive history for the scan along setting the highest possible strenght of attack (INSANE) with extensive reporting (Threshold: LOW). Scan took about 10 hours.

What we've noticed in our ZAP Report that there weren't any vulnerabilities found in our WebSockets communication, all reported issues were related to these few REST endpoints.

That got us thinking - is ZAP even touching WebSockets in terms of scanning/attacks?
I tried to find as many information about this as possible, but still am not sure what ZAP is doing in terms of WebSockets communication, hence this post
What I know for now - ZAP has support for WebSockets (bottom panel), can allow some fuzzing of its data, could act as WS proxy - but I don't know if any of this is happening by default or in order to scan WS you got to define it yourself.


My questions:
1. Is ZAP scan touching WebSockets communication by default ? Question regarding passive scan as well as active scan.

2. In my ZAP desktop, there are no predefined scripts for 'WebSocket Passive Rules' and `WebSocket Sender` tabs - and I've noticed that in some ZAP's videos people have some scripts there - any idea what this could happen there? 

Simon Bennetts

unread,
May 16, 2022, 7:10:56 AM5/16/22
to OWASP ZAP User Group
Hiya,

WebSocket connections are initiated by browsers.
You will either need to explore ZAP using the Ajax Spider or using unit tests using browsers that are proxying through ZAP.

ZAP currently only supports WebSocket passive scanning, not active scanning. The latter is planned but no ETA.

Out of interest, what data format are you using for your WebSocket comms?
As you probably know there are no real standards in this area, which makes it significantly harder to attack than more traditional web apps.

Cheers,

Simon

Wojciech Kopec

unread,
May 16, 2022, 9:45:08 AM5/16/22
to OWASP ZAP User Group
" You will either need to explore ZAP using the Ajax Spider or using unit tests using browsers that are proxying through ZAP. "
I'm running E2E Selenium tests which are already triggering WebSockets communications - isn't that enough?

"ZAP currently only supports WebSocket passive scanning, not active scanning."
Alright, so passive scanning should be done by default during attacks, is that correct? 
As mentioned, for some reason, I don't have ANY scripts under *WebSocket* scripts, please see attached image - is that expected?
 
ws_zap.png


"Out of interest, what data format are you using for your WebSocket comms?"
Our payload is in plain JSON, but with some bytes added by RSocket (https://rsocket.io/) by default (Ref: https://github.com/rsocket/rsocket-js/blob/7b1fe16e50d41935480e0b3e1beb381e8b07c41f/packages/rsocket-core/src/Codecs.ts#L940 - FRAME_HEADER_SIZE var) 

SOME ISSUE HAS BEEN OBSERVED USING ZAP WITH RSOCKET 
First 6 bytes are not UTF-8 characters which results in ZAP not being able to parse data to String - You see msg in "WebSocket" history, but you cannot manually edit it (<unreadable binary payload>) and fuzzing does not work - ZAP just resends the same frame with no payload fuzzing involved - see attachments.
Is that a bug in ZAP?

ws_zap2.png

ws_zap3.png


Regarging to this observed issue, I guess I need to somehow tweak WebSocket messages so that fuzzing would be available - I thought that using custom defined Fuzzer WebSocket Processor script (or Web Socket Sender) I will be able to modify message before it is send BUT no success there as well - for unknown reason I couldn't get it to work, even with simple https://www.piesocket.com/websocket-tester app - I couldn't get any message from within the script (added some plain print commands)

fuzzer_ws_processor.py:
def processMessage(utils, message):
    print(COUNT)
    print("")
    print(">>> message: " + message)
    print("")
    print(">>> utils.getOriginalMessage(): " + utils.getOriginalMessage())

    for (i, item) in enumerate(utils.getPayloads()):
        print(i, item)

    utils.sendMessage(message)
    return


Could you also help me with that, please?


BTW, Thanks a lot for your commitment to ZAP project, Simon! 

Wojciech Kopec

unread,
May 16, 2022, 12:44:56 PM5/16/22
to OWASP ZAP User Group
For the last paragraph, regarding Fuzzer WebSocker Processor I think I've found an answer - There is additional Fuzzer dialog when selecting phrase to be fuzzed in Request view by clicking it with 
right mouse button -> select Fuzz... -> Message Processors -> Add... -> select your custom script

Seems to be working, at least now I can see printed text in output - although it there a way to set up Fuzzer during Active Scan this way?

Simon Bennetts

unread,
May 17, 2022, 9:51:04 AM5/17/22
to OWASP ZAP User Group
On Monday, 16 May 2022 at 17:44:56 UTC+1 wojciec...@gmail.com wrote:
For the last paragraph, regarding Fuzzer WebSocker Processor I think I've found an answer - There is additional Fuzzer dialog when selecting phrase to be fuzzed in Request view by clicking it with 
right mouse button -> select Fuzz... -> Message Processors -> Add... -> select your custom script

Seems to be working, at least now I can see printed text in output - although it there a way to set up Fuzzer during Active Scan this way?

No, fuzzing is a manual process and automation is not currently supported.
 

poniedziałek, 16 maja 2022 o 15:45:08 UTC+2 Wojciech Kopec napisał(a):
" You will either need to explore ZAP using the Ajax Spider or using unit tests using browsers that are proxying through ZAP. "
I'm running E2E Selenium tests which are already triggering WebSockets communications - isn't that enough?

Are they proxying through ZAP?
Can you see the websocket messages in ZAP?
 

"ZAP currently only supports WebSocket passive scanning, not active scanning."
Alright, so passive scanning should be done by default during attacks, is that correct? 

Its done while exploring and attacking.
 
As mentioned, for some reason, I don't have ANY scripts under *WebSocket* scripts, please see attached image - is that expected?
 
ws_zap.png


Thats not expected - how did you install ZAP?
There should be a set of WebSocket Passive Scan rules installed by default - they are also under https://github.com/zaproxy/zap-extensions/tree/main/addOns/websocket/src/main/zapHomeFiles/scripts/templates/websocketpassive
 

"Out of interest, what data format are you using for your WebSocket comms?"
Our payload is in plain JSON, but with some bytes added by RSocket (https://rsocket.io/) by default (Ref: https://github.com/rsocket/rsocket-js/blob/7b1fe16e50d41935480e0b3e1beb381e8b07c41f/packages/rsocket-core/src/Codecs.ts#L940 - FRAME_HEADER_SIZE var) 

Thanks, thats good to know.
 

SOME ISSUE HAS BEEN OBSERVED USING ZAP WITH RSOCKET 
First 6 bytes are not UTF-8 characters which results in ZAP not being able to parse data to String - You see msg in "WebSocket" history, but you cannot manually edit it (<unreadable binary payload>) and fuzzing does not work - ZAP just resends the same frame with no payload fuzzing involved - see attachments.
Is that a bug in ZAP?

A bug or a restriction? Could be counted as either ;)
 

ws_zap2.png

ws_zap3.png


Regarging to this observed issue, I guess I need to somehow tweak WebSocket messages so that fuzzing would be available - I thought that using custom defined Fuzzer WebSocket Processor script (or Web Socket Sender) I will be able to modify message before it is send BUT no success there as well - for unknown reason I couldn't get it to work, even with simple https://www.piesocket.com/websocket-tester app - I couldn't get any message from within the script (added some plain print commands)

fuzzer_ws_processor.py:
def processMessage(utils, message):
    print(COUNT)
    print("")
    print(">>> message: " + message)
    print("")
    print(">>> utils.getOriginalMessage(): " + utils.getOriginalMessage())

    for (i, item) in enumerate(utils.getPayloads()):
        print(i, item)

    utils.sendMessage(message)
    return


Could you also help me with that, please?


I havnt tried fuzzing binary websocker messages, so that might not be supported (especially based on your note above).
However I'd expect WebSocket sender scripts to be able to change the messages - what have you tried?

Do you know of any publicly available apps which use rsocket?
It will be difficult for us to help without access to some way to reproduce any problems...

 

BTW, Thanks a lot for your commitment to ZAP project, Simon! 


Cheers,

Simon

Wojciech Kopec

unread,
May 17, 2022, 12:02:05 PM5/17/22
to OWASP ZAP User Group
"No, fuzzing is a manual process and automation is not currently supported."
Just to confirm - it involves HTTP requests as well (during Active Scan) ?


"Are they proxying through ZAP?
Can you see the websocket messages in ZAP?" 
Yes and Yes :)


"Thats not expected - how did you install ZAP?
There should be a set of WebSocket Passive Scan rules installed by default"
No idea why this would happen - I suspect my security software (ESET) which had some problems with ZAP files in the past - good to know scripts should be there, I will put them back up.


 "I havnt tried fuzzing binary websocker messages, so that might not be supported (especially based on your note above).
However I'd expect WebSocket sender scripts to be able to change the messages - what have you tried?"

I simply tried fuzzing the data the same way as you in this video ZAP DeepDive: WebSockets


Because our application heavily depends on WebSockets communication and this issue (parsing binary data) got us confused and uncertain that ZAP is doing any security scanning here 
- could you assure me that Passive Scanning is working with BINARY payload in WebSockets? I would really appreciate that and be just a little more calm about our application security,  please


Here is how it looks in my ZAP:
Sensitive data covered 

zap_ws_fuzzer.png

ya juzi

unread,
May 17, 2022, 4:09:25 PM5/17/22
to zaprox...@googlegroups.com
this is helpful but i dont understand most of them!
i tried using the method in zap blog through using scripts zest and i fuzzed out nothing 
no account no password from my web application

--
You received this message because you are subscribed to the Google Groups "OWASP ZAP User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to zaproxy-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/zaproxy-users/94ba6bbc-1b65-45d5-9c6a-5ad9b4d765b7n%40googlegroups.com.

Wojciech Kopec

unread,
May 19, 2022, 11:05:26 AM5/19/22
to OWASP ZAP User Group
SImon, little update on this thread:

1. I've reinstalled ZAP - ESET indeed is removing/quarantining some of the ZAPs files, specifically addOns files - added appropriate exclusions.
2. Copied templates/websocketpassiverules to scripts/websocketpassiverules  and load scripts.
3. I've verified that these scripts indeed work for example app - I've used https://www.piesocket.com/websocket-tester app and add some simple fuzzed payloads.

image (3).png


One issue remain:
Is there a way to fuzz payloads once more using WebSocketFuzzerTaskProcessorUtils object that is exposed in default Fuzz WebSocket Processor script (function processMessage(utils, message)) ???
Because my payloads are in BINARY the fuzzer do not do anything, evidence:


TextWebSocketMessageLocationReplacer class:
@Override
public WebSocketFuzzMessageDTO replace(
(...code ...)

if (!(message.getPayload() instanceof String)) {
// TODO: Exclude popup menu or support fuzzing binary payloads - why not?
return copyMessage(message);
(...code ...) }


 I could write my custom script to extract problematic bytes making payload instanceof String, then add remaining bytes again to Payload and send message - do you have some ideas how this could be performed?
Reply all
Reply to author
Forward
0 new messages