Skip to content

Commit b723525

Browse files
committed
added new remediator and test
1 parent 99d8a49 commit b723525

File tree

11 files changed

+153353
-1
lines changed

11 files changed

+153353
-1
lines changed

core-codemods/src/main/java/io/codemodder/codemods/DefaultCodemods.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public static List<Class<? extends CodeChanger>> asList() {
3737
CodeQLLogInjectionCodemod.class,
3838
CodeQLMavenSecureURLCodemod.class,
3939
CodeQLOutputResourceLeakCodemod.class,
40+
CodeQLPotentiallyUnsafeCryptoAlgorithmCodemod.class,
4041
CodeQLPredictableSeedCodemod.class,
4142
CodeQLRegexInjectionCodemod.class,
4243
CodeQLSQLInjectionCodemod.class,
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.codemodder.codemods.codeql;
2+
3+
import com.contrastsecurity.sarif.Result;
4+
import com.github.javaparser.ast.CompilationUnit;
5+
import io.codemodder.*;
6+
import io.codemodder.codetf.DetectorRule;
7+
import io.codemodder.providers.sarif.codeql.ProvidedCodeQLScan;
8+
import io.codemodder.remediation.GenericRemediationMetadata;
9+
import io.codemodder.remediation.Remediator;
10+
import io.codemodder.remediation.weakcrypto.WeakCryptoAlgorithmRemediator;
11+
import java.util.Optional;
12+
import javax.inject.Inject;
13+
14+
/** A codemod for automatically fixing weak crypto algorithms. */
15+
@Codemod(
16+
id = "codeql:java/potentially-weak-cryptographic-algorithm",
17+
reviewGuidance = ReviewGuidance.MERGE_AFTER_REVIEW,
18+
importance = Importance.HIGH,
19+
executionPriority = CodemodExecutionPriority.HIGH)
20+
public final class CodeQLPotentiallyUnsafeCryptoAlgorithmCodemod extends CodeQLRemediationCodemod {
21+
22+
private final Remediator<Result> remediator;
23+
24+
@Inject
25+
public CodeQLPotentiallyUnsafeCryptoAlgorithmCodemod(
26+
@ProvidedCodeQLScan(ruleId = "java/potentially-weak-cryptographic-algorithm")
27+
final RuleSarif sarif) {
28+
super(GenericRemediationMetadata.WEAK_CRYPTO_ALGORITHM.reporter(), sarif);
29+
this.remediator = new WeakCryptoAlgorithmRemediator<>();
30+
}
31+
32+
@Override
33+
public DetectorRule detectorRule() {
34+
return new DetectorRule(
35+
"potentially-weak-cryptographic-algorithm",
36+
"Use of a potentially broken or risky cryptographic algorithm",
37+
"https://codeql.github.com/codeql-query-help/java/java-potentially-weak-cryptographic-algorithm/");
38+
}
39+
40+
@Override
41+
public CodemodFileScanningResult visit(
42+
final CodemodInvocationContext context, final CompilationUnit cu) {
43+
return remediator.remediateAll(
44+
cu,
45+
context.path().toString(),
46+
detectorRule(),
47+
ruleSarif.getResultsByLocationPath(context.path()),
48+
SarifFindingKeyUtil::buildFindingId,
49+
r -> r.getLocations().get(0).getPhysicalLocation().getRegion().getStartLine(),
50+
r ->
51+
Optional.ofNullable(
52+
r.getLocations().get(0).getPhysicalLocation().getRegion().getEndLine()),
53+
r -> Optional.empty());
54+
}
55+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.codemodder.codemods.codeql;
2+
3+
import io.codemodder.testutils.CodemodTestMixin;
4+
import io.codemodder.testutils.Metadata;
5+
6+
@Metadata(
7+
codemodType = CodeQLPotentiallyUnsafeCryptoAlgorithmCodemod.class,
8+
testResourceDir = "codeql-potentially-unsafe-crypto-algorithm",
9+
renameTestFile = "app/src/main/java/org/apache/roller/weblogger/util/WSSEUtilities.java",
10+
expectingFixesAtLines = {38},
11+
doRetransformTest = false,
12+
dependencies = {})
13+
final class CodeQLPotentiallyUnsafeCryptoAlgorithmCodemodTest implements CodemodTestMixin {}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2005, Dave Johnson
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.roller.weblogger.util;
17+
18+
import java.io.IOException;
19+
import java.io.UnsupportedEncodingException;
20+
import java.security.MessageDigest;
21+
import java.security.NoSuchAlgorithmException;
22+
import java.text.SimpleDateFormat;
23+
import java.util.Date;
24+
25+
import org.apache.commons.codec.binary.Base64;
26+
27+
import static java.nio.charset.StandardCharsets.UTF_8;
28+
29+
/**
30+
* Utilties to support WSSE authentication.
31+
* @author Dave Johnson
32+
*/
33+
public class WSSEUtilities {
34+
public static synchronized String generateDigest(
35+
byte[] nonce, byte[] created, byte[] password) {
36+
String result = null;
37+
try {
38+
MessageDigest digester = MessageDigest.getInstance("SHA-256");
39+
digester.reset();
40+
digester.update(nonce);
41+
digester.update(created);
42+
digester.update(password);
43+
byte[] digest = digester.digest();
44+
result = base64Encode(digest);
45+
}
46+
catch (NoSuchAlgorithmException e) {
47+
result = null;
48+
}
49+
return result;
50+
}
51+
public static byte[] base64Decode(String value) throws IOException {
52+
return Base64.decodeBase64(value.getBytes(UTF_8));
53+
}
54+
public static String base64Encode(byte[] value) {
55+
return new String(Base64.encodeBase64(value));
56+
}
57+
public static String generateWSSEHeader(String userName, String password)
58+
throws UnsupportedEncodingException {
59+
60+
byte[] nonceBytes = Long.toString(new Date().getTime()).getBytes();
61+
String nonce = WSSEUtilities.base64Encode(nonceBytes);
62+
63+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
64+
String created = sdf.format(new Date());
65+
66+
String digest = WSSEUtilities.generateDigest(
67+
nonceBytes, created.getBytes(UTF_8), password.getBytes(UTF_8));
68+
69+
StringBuilder header = new StringBuilder("UsernameToken Username=\"");
70+
header.append(userName);
71+
header.append("\", ");
72+
header.append("PasswordDigest=\"");
73+
header.append(digest);
74+
header.append("\", ");
75+
header.append("Nonce=\"");
76+
header.append(nonce);
77+
header.append("\", ");
78+
header.append("Created=\"");
79+
header.append(created);
80+
header.append("\"");
81+
return header.toString();
82+
}
83+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2005, Dave Johnson
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.roller.weblogger.util;
17+
18+
import java.io.IOException;
19+
import java.io.UnsupportedEncodingException;
20+
import java.security.MessageDigest;
21+
import java.security.NoSuchAlgorithmException;
22+
import java.text.SimpleDateFormat;
23+
import java.util.Date;
24+
25+
import org.apache.commons.codec.binary.Base64;
26+
27+
import static java.nio.charset.StandardCharsets.UTF_8;
28+
29+
/**
30+
* Utilties to support WSSE authentication.
31+
* @author Dave Johnson
32+
*/
33+
public class WSSEUtilities {
34+
public static synchronized String generateDigest(
35+
byte[] nonce, byte[] created, byte[] password) {
36+
String result = null;
37+
try {
38+
MessageDigest digester = MessageDigest.getInstance("SHA");
39+
digester.reset();
40+
digester.update(nonce);
41+
digester.update(created);
42+
digester.update(password);
43+
byte[] digest = digester.digest();
44+
result = base64Encode(digest);
45+
}
46+
catch (NoSuchAlgorithmException e) {
47+
result = null;
48+
}
49+
return result;
50+
}
51+
public static byte[] base64Decode(String value) throws IOException {
52+
return Base64.decodeBase64(value.getBytes(UTF_8));
53+
}
54+
public static String base64Encode(byte[] value) {
55+
return new String(Base64.encodeBase64(value));
56+
}
57+
public static String generateWSSEHeader(String userName, String password)
58+
throws UnsupportedEncodingException {
59+
60+
byte[] nonceBytes = Long.toString(new Date().getTime()).getBytes();
61+
String nonce = WSSEUtilities.base64Encode(nonceBytes);
62+
63+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
64+
String created = sdf.format(new Date());
65+
66+
String digest = WSSEUtilities.generateDigest(
67+
nonceBytes, created.getBytes(UTF_8), password.getBytes(UTF_8));
68+
69+
StringBuilder header = new StringBuilder("UsernameToken Username=\"");
70+
header.append(userName);
71+
header.append("\", ");
72+
header.append("PasswordDigest=\"");
73+
header.append(digest);
74+
header.append("\", ");
75+
header.append("Nonce=\"");
76+
header.append(nonce);
77+
header.append("\", ");
78+
header.append("Created=\"");
79+
header.append(created);
80+
header.append("\"");
81+
return header.toString();
82+
}
83+
}

0 commit comments

Comments
 (0)