Skip to content

Commit e3b7a21

Browse files
committed
CYBS-737: WSS4j security vulnerability fix
1 parent 202346b commit e3b7a21

5 files changed

Lines changed: 73 additions & 58 deletions

File tree

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ To install the `cybersource-sdk-java` from central repository, add dependency to
1010
<dependency>
1111
<groupId>com.cybersource</groupId>
1212
<artifactId>cybersource-sdk-java</artifactId>
13-
<version>6.2.11</version>
13+
<version>6.2.12</version>
1414
</dependency>
1515
```
1616
Run `mvn install` to install dependency
@@ -19,7 +19,7 @@ Run `mvn install` to install dependency
1919
Add the dependency to your build.gradle
2020
```java
2121
dependencies {
22-
compile 'com.cybersource:cybersource-sdk-java:6.2.11'
22+
compile 'com.cybersource:cybersource-sdk-java:6.2.12'
2323
}
2424
```
2525
## Requirements
@@ -250,6 +250,11 @@ Retry Pattern allows to retry sending a failed request and it will only work wit
250250

251251
## Changes
252252
_______________________________
253+
Version Cybersource-sdk-java 6.2.12 (JUNE,2022)
254+
_______________________________
255+
1) Apache WSS4j Security Vulnerability fix.
256+
_______________________________
257+
_______________________________
253258
Version Cybersource-sdk-java 6.2.11 (MAY,2020)
254259
_______________________________
255260
1)Exception handling improvement.

java/pom.xml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@
230230
<dependency>
231231
<groupId>org.apache.santuario</groupId>
232232
<artifactId>xmlsec</artifactId>
233-
<version>1.5.6</version>
233+
<version>2.3.0</version>
234234
</dependency>
235235
<dependency>
236236
<groupId>org.apache.httpcomponents</groupId>
@@ -249,15 +249,14 @@
249249
<version>1.61</version>
250250
</dependency>
251251
<dependency>
252-
<groupId>org.apache.ws.security</groupId>
253-
<artifactId>wss4j</artifactId>
254-
<version>1.6.19</version>
255-
<exclusions>
256-
<exclusion>
257-
<groupId>org.opensaml</groupId>
258-
<artifactId>opensaml</artifactId>
259-
</exclusion>
260-
</exclusions>
252+
<groupId>org.apache.wss4j</groupId>
253+
<artifactId>wss4j-ws-security-common</artifactId>
254+
<version>2.4.1</version>
255+
</dependency>
256+
<dependency>
257+
<groupId>org.apache.wss4j</groupId>
258+
<artifactId>wss4j-ws-security-dom</artifactId>
259+
<version>2.4.1</version>
261260
</dependency>
262261
<dependency>
263262
<groupId>org.apache.commons</groupId>
@@ -270,6 +269,12 @@
270269
<version>1.10.19</version>
271270
<scope>test</scope>
272271
</dependency>
272+
<dependency>
273+
<groupId>org.apache.wss4j</groupId>
274+
<artifactId>wss4j-ws-security-dom</artifactId>
275+
<version>2.4.1</version>
276+
<scope>compile</scope>
277+
</dependency>
273278
</dependencies>
274279
</project>
275280

java/src/main/java/com/cybersource/ws/client/MessageHandlerKeyStore.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.cybersource.ws.client;
22

3-
import org.apache.ws.security.components.crypto.CredentialException;
4-
import org.apache.ws.security.components.crypto.Merlin;
3+
import org.apache.wss4j.common.crypto.Merlin;
54

65
import java.io.IOException;
76
import java.security.KeyStoreException;
@@ -15,11 +14,10 @@
1514
public class MessageHandlerKeyStore extends Merlin {
1615

1716
/**
18-
* @throws CredentialException
1917
* @throws IOException
2018
*/
21-
public MessageHandlerKeyStore() throws CredentialException, IOException {
22-
super(null);
19+
public MessageHandlerKeyStore() {
20+
super();
2321
properties = new Properties();
2422
}
2523

java/src/main/java/com/cybersource/ws/client/SecurityUtil.java

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
package com.cybersource.ws.client;
22

3-
import org.apache.ws.security.WSConstants;
4-
import org.apache.ws.security.WSEncryptionPart;
5-
import org.apache.ws.security.WSSecurityException;
6-
import org.apache.ws.security.components.crypto.CredentialException;
7-
import org.apache.ws.security.message.WSSecEncrypt;
8-
import org.apache.ws.security.message.WSSecHeader;
9-
import org.apache.ws.security.message.WSSecSignature;
3+
import org.apache.wss4j.common.WSEncryptionPart;
4+
import org.apache.wss4j.common.ext.WSSecurityException;
5+
import org.apache.wss4j.dom.WSConstants;
6+
import org.apache.wss4j.dom.WSDocInfo;
7+
import org.apache.wss4j.dom.message.WSSecEncrypt;
8+
import org.apache.wss4j.dom.message.WSSecHeader;
9+
import org.apache.wss4j.dom.message.WSSecSignature;
1010
import org.bouncycastle.jce.provider.BouncyCastleProvider;
1111
import org.w3c.dom.Document;
1212

13+
import javax.crypto.KeyGenerator;
1314
import java.io.FileInputStream;
1415
import java.io.FileNotFoundException;
1516
import java.io.IOException;
1617
import java.security.*;
17-
import java.security.cert.Certificate;
1818
import java.security.cert.CertificateException;
1919
import java.security.cert.X509Certificate;
2020
import java.util.Collections;
@@ -44,7 +44,9 @@ public class SecurityUtil {
4444
private static final String SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
4545
// By default digest algorithm is set to "http://www.w3.org/2000/09/xmldsig#sha1"
4646
private static final String DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmlenc#sha256";
47-
47+
// SymmetricKey Generator Algorithm to handle message encryption
48+
private static final String SYM_KEY_ALGO = "AES";
49+
4850
private static BouncyCastleProvider bcProvider = new BouncyCastleProvider();
4951

5052
// This is loaded by WSS4J but since we use it lets make sure its here
@@ -57,7 +59,7 @@ public class SecurityUtil {
5759
}
5860
}
5961

60-
private static void initKeystore() throws KeyStoreException, CredentialException, IOException, NoSuchAlgorithmException, CertificateException{
62+
private static void initKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException{
6163
KeyStore keyStore = KeyStore.getInstance("jks");
6264
keyStore.load(null, null);
6365
localKeyStoreHandler = new MessageHandlerKeyStore();
@@ -190,91 +192,92 @@ private static void readAndStoreCertificateAndPrivateKey(MerchantConfig merchant
190192
* @throws SignException
191193
*/
192194
public static Document handleMessageCreation(Document signedDoc, String merchantId, Logger logger) throws SignEncryptException, SignException{
193-
195+
194196
logger.log(Logger.LT_INFO, "Encrypting Signed doc ...");
195-
196-
WSSecHeader secHeader = new WSSecHeader();
197+
198+
org.apache.xml.security.Init.init();
199+
WSSecHeader secHeader = new WSSecHeader(signedDoc);
197200
try {
198-
secHeader.insertSecurityHeader(signedDoc);
201+
secHeader.insertSecurityHeader();
199202
} catch (WSSecurityException e) {
200203
logger.log(Logger.LT_EXCEPTION, "Exception while adding document in soap securiy header for MLE");
201204
throw new SignException(e);
202205
}
203-
204-
WSSecEncrypt encrBuilder = new WSSecEncrypt();
206+
WSSecEncrypt encrBuilder = new WSSecEncrypt(secHeader);
205207
//Set the user name to get the encryption certificate.
206208
//The public key of this certificate is used, thus no password necessary. The user name is a keystore alias usually.
207209
encrBuilder.setUserInfo(identities.get(SERVER_ALIAS).getKeyAlias());
208-
210+
209211
/*This is to reference a public key or certificate when signing or encrypting a SOAP message.
210212
*The following valid values for these configuration items are:
211213
*IssuerSerial (default),DirectReference[BST],X509KeyIdentifier,Thumbprint,SKIKeyIdentifier,KeyValue (signature only),EncryptedKeySHA1 (encryption only)
212214
*/
213215
encrBuilder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
214-
216+
215217
//This encryption algorithm is used to encrypt the data.
216218
encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_256);
217-
219+
218220
//Sets the algorithm to encode the symmetric key. Default is the WSConstants.KEYTRANSPORT_RSAOEP algorithm.
219221
//encrBuilder.setKeyEnc(WSConstants.KEYTRANSPORT_RSAOEP);
220-
221-
222+
223+
222224
//Create signed document
223225
//Document signedDoc = createSignedDoc(workingDocument,senderAlias,password,secHeader);
224-
226+
225227
Document signedEncryptedDoc;
226228
try {
227229
//Builds the SOAP envelope with encrypted Body and adds encrypted key.
228230
// If no external key (symmetricalKey) was set ,generate an encryption
229231
// key (session key) for this Encrypt element. This key will be
230232
// encrypted using the public key of the receiver
231-
signedEncryptedDoc = encrBuilder.build(signedDoc, localKeyStoreHandler, secHeader);
232-
} catch (WSSecurityException e) {
233+
signedEncryptedDoc = encrBuilder.build(localKeyStoreHandler, KeyGenerator.getInstance(SYM_KEY_ALGO).generateKey());
234+
} catch (WSSecurityException | NoSuchAlgorithmException e) {
233235
logger.log(Logger.LT_EXCEPTION, "Failed while encrypting signed requeest for , '" + merchantId + "'" + " with " + SERVER_ALIAS);
234236
throw new SignEncryptException("Failed while encrypting signed requeest for , '" + merchantId + "'" + " with " + SERVER_ALIAS, e);
235237
}
236-
encrBuilder.prependToHeader(secHeader);
238+
encrBuilder.prependToHeader();
237239
return signedEncryptedDoc;
238240
}
239241

240242
/**
241243
* Create signed document
242-
* @param workingDocument
244+
* @param signedDoc
243245
* @param keyAlias
244246
* @param password
245247
* @param logger
246248
* @return Document
247249
* @throws SignException
248250
*/
249-
public static Document createSignedDoc(Document workingDocument,String keyAlias, String password,Logger logger) throws SignException {
250-
251+
public static Document createSignedDoc(Document signedDoc,String keyAlias, String password,Logger logger) throws SignException {
252+
251253
logger.log(Logger.LT_INFO, "Signing request...");
252-
//long startTime = System.nanoTime();
253-
WSSecHeader secHeader = new WSSecHeader();
254+
long startTime = System.nanoTime();
255+
WSSecHeader secHeader = new WSSecHeader(signedDoc);
254256
try {
255-
secHeader.insertSecurityHeader(workingDocument);
257+
secHeader.insertSecurityHeader();
256258
} catch (WSSecurityException e) {
257259
logger.log(Logger.LT_EXCEPTION,
258-
"Exception while signing XML document");
260+
"Exception while signing XML document");
259261
throw new SignException(e);
260262
}
261-
262-
WSSecSignature sign = new WSSecSignature();
263-
263+
264+
WSSecSignature sign = new WSSecSignature(secHeader);
264265
sign.setUserInfo(keyAlias, password);
265-
266-
//sign.setUserInfo(mc.getKeyAlias(), mc.getPassword());
266+
267267
sign.setDigestAlgo(DIGEST_ALGORITHM);
268268
sign.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
269269
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
270270
sign.setUseSingleCertificate(true);
271-
271+
//
272+
sign.setWsDocInfo(new WSDocInfo(signedDoc));
273+
272274
//Set which parts of the message to encrypt/sign.
273275
WSEncryptionPart msgBodyPart = new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP11_ENV, "");
274-
sign.setParts(Collections.singletonList(msgBodyPart));
276+
275277
try {
276-
Document document = sign.build(workingDocument, localKeyStoreHandler, secHeader);
277-
//System.out.println("SecurityUtil.createSignedDoc time taken to sign the request is " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
278+
sign.addReferencesToSign(Collections.singletonList(msgBodyPart));
279+
Document document = sign.build(localKeyStoreHandler);
280+
System.out.println("SecurityUtil.createSignedDoc time taken to sign the request is " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
278281
return document;
279282
} catch (WSSecurityException e) {
280283
logger.log(Logger.LT_EXCEPTION, "Failed while signing request for , '" + keyAlias + "'");

zip/README

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ Provides low level HTTP transport components that can be used to build custom cl
277277

278278
##Changes
279279

280+
Version Cybersource-sdk-java 6.2.12 (JUNE,2022)
281+
_______________________________
282+
1) Apache WSS4j Security Vulnerability fix.
283+
280284
Version Cybersource-sdk-java 6.2.11 (MAY,2020)
281285
_______________________________
282286

0 commit comments

Comments
 (0)