(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V 4 false # Expression # RCE
20 | */
21 | public class ExpressionRCE extends BaseLocalInspectionTool {
22 |
23 | public static final String MESSAGE = InspectionBundle.message("expression.rce.type.msg");
24 |
25 | @Override
26 | @NotNull
27 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
28 | return new JavaElementVisitor() {
29 | @Override
30 | public void visitNewExpression(PsiNewExpression expression) {
31 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.beans.Expression"))
32 | holder.registerProblem(
33 | expression,
34 | MESSAGE,
35 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
36 | }
37 | };
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssti/ValidationSSTI.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssti;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1031
15 | * javax/validation/ConstraintValidatorContext buildConstraintViolationWithTemplate * -1 true # SSTI常用sink # SSTI
16 | * org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl buildConstraintViolationWithTemplate * -1 true # SSTI常用sink # SSTI
17 | */
18 | public class ValidationSSTI extends BaseLocalInspectionTool {
19 | public static final String MESSAGE = InspectionBundle.message("validation.ssti.type.msg");
20 |
21 | @Override
22 | @NotNull
23 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
24 | return new JavaElementVisitor() {
25 | @Override
26 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
27 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.validation.ConstraintValidatorContext", "buildConstraintViolationWithTemplate")
28 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl", "buildConstraintViolationWithTemplate")
29 | ) {
30 | holder.registerProblem(
31 | expression,
32 | MESSAGE,
33 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
34 | }
35 | }
36 | };
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/XMLDecoderUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1003: XMLDecoder 反序列化风险
30 | */
31 | public class XMLDecoderUnserialize extends BaseLocalInspectionTool {
32 | public static final String MESSAGE = InspectionBundle.message("xml.decoder.unserialize.msg");
33 |
34 |
35 | @Override
36 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
37 | return new JavaElementVisitor() {
38 | @Override
39 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
40 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.beans.XMLDecoder","readObject")) {
41 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
42 | }
43 | }
44 | };
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/SPELRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1022
15 | * org/springframework/expression/ExpressionParser parseExpression * -1 true # SPEL # RCE
16 | * org/springframework/expression/spel/standard/SpelExpressionParser parseExpression * 1 true # SPEL # RCE
17 | * org/springframework/expression/spel/standard/SpelExpressionParser parseRaw * -1 true # SPEL # RCE
18 | */
19 | public class SPELRCE extends BaseLocalInspectionTool {
20 |
21 | public static final String MESSAGE = InspectionBundle.message("spel.rce.type.msg");
22 |
23 | @Override
24 | @NotNull
25 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
26 | return new JavaElementVisitor() {
27 | @Override
28 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
29 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.expression.ExpressionParser", "parseExpression")
30 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.expression.spel.standard.SpelExpressionParser", "parseExpression")
31 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.expression.spel.standard.SpelExpressionParser", "parseRaw")) {
32 | holder.registerProblem(
33 | expression,
34 | MESSAGE,
35 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
36 | }
37 | }
38 | };
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/FastjsonUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.fix.DeleteElementQuickFix;
23 | import com.itkim.inspector.utils.InspectionBundle;
24 | import com.itkim.inspector.utils.SecExpressionUtils;
25 | import org.jetbrains.annotations.NotNull;
26 |
27 | /**
28 | * 1002: Fastjson反序列化风险
29 | *
30 | * "com.alibaba.fastjson.JSON.parseObject,存在反序列化风险,建议检查Fastjson版本
31 | */
32 | public class FastjsonUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("fastjson.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.alibaba.fastjson.JSON", "parseObject")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/ClassLoaderRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1030
15 | * java/lang/ClassLoader defineClass ([BII)Ljava/lang/Class; 1 all # defineClass # RCE
16 | * java/lang/ClassLoader defineClass (Ljava/lang/String;[BII)Ljava/lang/Class; 2 all # defineClass # RCE
17 | * java/lang/ClassLoader defineClass (Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class; 2 all # defineClass # RCE
18 | * java/lang/ClassLoader defineClass (Ljava/lang/String;Ljava/nio/ByteBuffer;Ljava/security/ProtectionDomain;)Ljava/lang/Class; 2 all # defineClass # RCE
19 | * org/mozilla/javascript/DefiningClassLoader defineClass * 2 false # defineClass # RCE
20 | */
21 | public class ClassLoaderRCE extends BaseLocalInspectionTool {
22 | public static final String MESSAGE = InspectionBundle.message("classLoader.rce.type.msg");
23 |
24 | @Override
25 | @NotNull
26 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
27 | return new JavaElementVisitor() {
28 | @Override
29 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
30 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.lang.ClassLoader", "defineClass")
31 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mozilla.javascript.DefiningClassLoader", "defineClass")
32 | ) {
33 | holder.registerProblem(
34 | expression,
35 | MESSAGE,
36 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
37 | }
38 | }
39 | };
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/BurlapUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1013
30 | * com/caucho/burlap/io/BurlapInput readObject * 0 false # burlap反序列化 # RCE1
31 | */
32 | public class BurlapUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("burlap.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.caucho.burlap.io.BurlapInput", "readObject")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/YamlBeansUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1010
30 | * com/esotericsoftware/yamlbeans/YamlReader * 1 false # yamlbeans反序列化 # RCE
31 | */
32 | public class YamlBeansUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("yamlBeans.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.esotericsoftware.yamlbeans.YamlReader", "read")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/JsonIOUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1009
30 | * com/cedarsoftware/util/io/JsonReader readObject ()Ljava/lang/Object; 0 false # jsonio反序列化 # RCE
31 | */
32 | public class JsonIOUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("jsonIO.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.cedarsoftware.util.io.JsonReader", "readObject")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/ObjectInputStreamUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1016
30 | * java/io/ObjectInputStream readObject ()Ljava/lang/Object; 0 all # deserialization反序列化 # RCE
31 | */
32 | public class ObjectInputStreamUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("objectInputStream.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.io.ObjectInputStream", "readObject")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/XStreamUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1015
30 | * com/thoughtworks/xstream/XStream fromXML (Ljava/lang/String;)Ljava/lang/Object; 1 false # XStreamDeserialization # RCE
31 | */
32 | public class XStreamUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("xStream.unserialize.type.msg");
34 |
35 | @Override
36 | @NotNull
37 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.thoughtworks.xstream.XStream", "fromXML")) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/HessianUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1011
30 | * com/caucho/hessian/io/HessianInput readObject * 0 false # hessian反序列化 # RCE
31 | * com/caucho/hessian/io/Hessian2Input readObject * 0 false # hessian2反序列化 # RCE
32 | */
33 | public class HessianUnserialize extends BaseLocalInspectionTool {
34 | public static final String MESSAGE = InspectionBundle.message("hessian.unserialize.type.msg");
35 |
36 | @Override
37 | @NotNull
38 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
39 | return new JavaElementVisitor() {
40 | @Override
41 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
42 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.caucho.hessian.io.HessianInput", "readObject") ||
43 | SecExpressionUtils.hasFullQualifiedName(expression, "com.caucho.hessian.io.Hessian2Input", "readObject")) {
44 | holder.registerProblem(
45 | expression,
46 | MESSAGE,
47 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
48 | }
49 | }
50 | };
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/fix/SetBoolArgQuickFix.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.fix;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.openapi.project.Project;
21 | import com.intellij.psi.*;
22 | import com.intellij.util.ObjectUtils;
23 | import org.jetbrains.annotations.Nls;
24 | import org.jetbrains.annotations.NotNull;
25 |
26 | public class SetBoolArgQuickFix implements LocalQuickFix {
27 | private final String QUICK_FIX_NAME;
28 | private final Boolean b;
29 | private SmartPsiElementPointer argPointer;
30 |
31 | public SetBoolArgQuickFix(String name, Boolean b) {
32 | this.QUICK_FIX_NAME = name;
33 | this.b = b;
34 | this.argPointer = null;
35 | }
36 |
37 | public SetBoolArgQuickFix(String name, Boolean b, PsiLiteralExpression arg) {
38 | this.QUICK_FIX_NAME = name;
39 | this.b = b;
40 | this.argPointer = SmartPointerManager.createPointer(arg);
41 | }
42 |
43 | @Override
44 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
45 | return QUICK_FIX_NAME;
46 | }
47 |
48 | @Override
49 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
50 | if (this.argPointer == null) {
51 | PsiLiteralExpression arg = ObjectUtils.tryCast(descriptor.getPsiElement(), PsiLiteralExpression.class);
52 | if (arg == null) return ;
53 | this.argPointer = SmartPointerManager.createPointer(arg);
54 | }
55 |
56 | PsiLiteralExpression targetArg = this.argPointer.getElement();
57 | if (targetArg == null) return ;
58 | PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
59 | PsiLiteralExpression newArg = (PsiLiteralExpression)factory.createExpressionFromText(b.toString(), null);
60 | targetArg.replace(newArg);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssrf/GoogleIOSSRF.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssrf;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1067
15 | * com/google/common/io/Resources asByteSource (Ljava/net/URL;) 1 false # SSRF # SSRF
16 | * com/google/common/io/Resources asCharSource (Ljava/net/URL;Ljava/nio/charset/Charset;) 1 false # SSRF # SSRF
17 | * com/google/common/io/Resources copy (Ljava/net/URL;Ljava/io/OutputStream;) 1 false # SSRF # SSRF
18 | * com/google/common/io/Resources readLines * 1 false # SSRF # SSRF
19 | * com/google/common/io/Resources toByteArray (Ljava/net/URL;) 1 false # SSRF # SSRF
20 | * com/google/common/io/Resources toString (Ljava/net/URL;Ljava/nio/charset/Charset;) 1 false # SSRF # SSRF
21 | */
22 | public class GoogleIOSSRF extends BaseLocalInspectionTool {
23 | public static final String MESSAGE = InspectionBundle.message("google.ssrf.msg");
24 |
25 | @Override
26 | @NotNull
27 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
28 | return new JavaElementVisitor() {
29 | @Override
30 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
31 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "asByteSource")
32 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "asCharSource")
33 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "copy")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "readLines")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "toByteArray")
36 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.google.common.io.Resources", "toString")) {
37 | holder.registerProblem(
38 | expression,
39 | MESSAGE,
40 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
41 | }
42 | }
43 | };
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/JYamlUnserialize.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1008
15 | * org/ho/yaml/Yaml load * 1 false # jyaml反序列化 # RCE
16 | * org/ho/yaml/Yaml loadStream * 1 false # jyaml反序列化 # RCE
17 | * org/ho/yaml/Yaml loadStreamOfType * 1 false # jyaml反序列化 # RCE
18 | * org/ho/yaml/Yaml loadType * 1 false # jyaml反序列化 # RCE
19 | * org/ho/yaml/YamlConfig load * 1 false # jyaml反序列化 # RCE
20 | * org/ho/yaml/YamlConfig loadStream * 1 false # jyaml反序列化 # RCE
21 | * org/ho/yaml/YamlConfig loadStreamOfType * 1 false # jyaml反序列化 # RCE
22 | * org/ho/yaml/YamlConfig loadType * 1 false # jyaml反序列化 # RCE
23 | */
24 | public class JYamlUnserialize extends BaseLocalInspectionTool {
25 | public static final String MESSAGE = InspectionBundle.message("jYaml.unserialize.type.msg");
26 |
27 |
28 | @Override
29 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
30 | return new JavaElementVisitor() {
31 | @Override
32 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
33 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.Yaml", "load")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.Yaml", "loadStream")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.Yaml", "loadStreamOfType")
36 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.Yaml", "loadType")
37 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.YamlConfig", "load")
38 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.YamlConfig", "loadStream")
39 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.YamlConfig", "loadStreamOfType")
40 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.ho.yaml.YamlConfig", "loadType"))
41 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
42 | }
43 | };
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/reflect/Reflect.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.reflect;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1046
15 | * java/lang/reflect/Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; 0 false # Method.invoke,其实需要两个参数都可控才能打 # REFLECT
16 | * java/net/URLClassLoader newInstance ([Ljava/net/URL;Ljava/lang/ClassLoader;)Ljava/net/URLClassLoader; -1 false # 实例化任意对象的sink # REFLECT
17 | * java/lang/ClassLoader loadClass * 1 true # ClassLoader加载任意Class # REFLECT
18 | * org/codehaus/groovy/runtime/InvokerHelper invokeMethod * 1 false # groovy-specific sinks # REFLECT
19 | * groovy/lang/MetaClass invokeMethod * -1 true # groovy-specific sinks # REFLECT
20 | * groovy/lang/MetaClass invokeConstructor * -1 true # groovy-specific sinks # REFLECT
21 | * groovy/lang/MetaClass invokeStaticMethod * -1 true # groovy-specific sinks # REFLECT
22 | */
23 | public class Reflect extends BaseLocalInspectionTool {
24 | public static final String MESSAGE = InspectionBundle.message("reflect.type.msg");
25 |
26 | @Override
27 | @NotNull
28 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
29 | return new JavaElementVisitor() {
30 | @Override
31 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
32 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.lang.reflect.Method", "invoke")
33 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.net.URLClassLoader", "newInstance")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.lang.ClassLoader", "loadClass")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.codehaus.groovy.runtime.InvokerHelper", "invokeMethod")
36 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.MetaClass", "invokeMethod")
37 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.MetaClass", "invokeConstructor")
38 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.MetaClass", "invokeStaticMethod")) {
39 | holder.registerProblem(
40 | expression,
41 | MESSAGE,
42 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
43 | }
44 | }
45 | };
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssrf/JavaURLSSRF.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssrf;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.intellij.psi.PsiNewExpression;
9 | import com.itkim.inspector.BaseLocalInspectionTool;
10 | import com.itkim.inspector.utils.InspectionBundle;
11 | import com.itkim.inspector.utils.SecExpressionUtils;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | /**
15 | * 1064
16 | * java/net/URL (Ljava/lang/String;)V 1 false # SSRF -- openConnection方法触发、openStream方法触发 # SSRF
17 | * java/net/Socket (Ljava/lang/String;I)V 1 false # SSRF # SSRF
18 | * java/net/URI create (Ljava/lang/String;)Ljava/net/URI; 0 false # SSRF # SSRF
19 | * java/net/URL openStream ()Ljava/io/InputStream; 0 false # SSRF文件读取的sink # FILE
20 | * java/net/http/HttpRequest newBuilder (Ljava/net/URL;Ljava/nio/charset/Charset;) 1 false # HttpClient.newHttpClient();传入send方法 # SSRF
21 | * javax/ws/rs/client/Client target * 1 false # jakarta ssrf -- ClientBuilder/newClient();client/target(url); # SSRF
22 | */
23 | public class JavaURLSSRF extends BaseLocalInspectionTool {
24 | public static final String MESSAGE = InspectionBundle.message("java.url.ssrf.msg");
25 |
26 | @Override
27 | @NotNull
28 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
29 | return new JavaElementVisitor() {
30 | @Override
31 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
32 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.net.URI", "create")
33 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.net.URI", "openStream")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.net.http.HttpRequest", "newBuilder")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "javax.ws.rs.client.Client", "target")) {
36 | holder.registerProblem(
37 | expression,
38 | MESSAGE,
39 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
40 | }
41 | }
42 |
43 | @Override
44 | public void visitNewExpression(PsiNewExpression expression) {
45 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.net.URL")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.net.Socket"))
47 | holder.registerProblem(
48 | expression,
49 | MESSAGE,
50 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
51 | }
52 | };
53 |
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/FastjsonAutoType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.utils.InspectionBundle;
23 | import com.itkim.inspector.fix.DeleteElementQuickFix;
24 | import com.itkim.inspector.utils.SecExpressionUtils;
25 | import org.jetbrains.annotations.NotNull;
26 |
27 | /**
28 | * 1001: Fastjson反序列化风险
29 | *
30 | * com.alibaba:fastjson 在开启AutoTypeSupport时,存在反序列化风险
31 | *
32 | * 程序内开启方法
33 | * (1) ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
34 | * (2) parseConfLocalVar.setAutoTypeSupport(true);
35 | * JVM开启方法
36 | * -Dfastjson.parser.autoTypeSupport=true
37 | */
38 | public class FastjsonAutoType extends BaseLocalInspectionTool {
39 | public static final String MESSAGE = InspectionBundle.message("fastjson.auto.type.msg");
40 | private static final String QUICK_FIX_NAME = InspectionBundle.message("fastjson.auto.type.fix");
41 |
42 | @Override
43 | @NotNull
44 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
45 | return new JavaElementVisitor() {
46 | @Override
47 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
48 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.alibaba.fastjson.parser.ParserConfig", "setAutoTypeSupport")) {
49 | PsiExpression[] args = expression.getArgumentList().getExpressions();
50 | if (args.length == 1 &&
51 | args[0] instanceof PsiLiteralExpression &&
52 | Boolean.TRUE.equals(((PsiLiteralExpression)args[0]).getValue())
53 | ) {
54 | holder.registerProblem(
55 | expression,
56 | MESSAGE,
57 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
58 | new DeleteElementQuickFix(expression, QUICK_FIX_NAME)
59 | );
60 | }
61 | }
62 | }
63 | };
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/OutdatedEncryptionInspector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.utils.InspectionBundle;
23 | import com.itkim.inspector.utils.SecExpressionUtils;
24 | import org.jetbrains.annotations.NotNull;
25 |
26 | /**
27 | * 1053
28 | * DES / 3DES(DESede) 为过时的加密标准
29 | *
30 | * 检查如下内容
31 | * javax.crypto.Cipher.getInstance
32 | * DES/CBC/NoPadding (56)
33 | * DES/CBC/PKCS5Padding (56)
34 | * DES/ECB/NoPadding (56)
35 | * DES/ECB/PKCS5Padding (56)
36 | * DESede/CBC/NoPadding (168)
37 | * DESede/CBC/PKCS5Padding (168)
38 | * DESede/ECB/NoPadding (168)
39 | * DESede/ECB/PKCS5Padding (168)
40 | *
41 | * ref:
42 | * https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard
43 | */
44 | public class OutdatedEncryptionInspector extends BaseLocalInspectionTool {
45 | public static final String MESSAGE = InspectionBundle.message("outdated.encryption.inspector.msg");
46 |
47 | @Override
48 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
49 | return new JavaElementVisitor() {
50 | @Override
51 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
52 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.crypto.Cipher", "getInstance")) {
53 | PsiExpressionList argList = expression.getArgumentList();
54 | PsiExpression[] args = argList.getExpressions();
55 | if (args.length > 0 && args[0] instanceof PsiLiteralExpression) {
56 | String trans = SecExpressionUtils.getLiteralInnerText(args[0]);
57 | if (null != trans && trans.startsWith("DES")) {
58 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
59 | }
60 | }
61 | }
62 | }
63 | };
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/fileRead/FileRead.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.fileRead;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.intellij.psi.PsiNewExpression;
9 | import com.itkim.inspector.BaseLocalInspectionTool;
10 | import com.itkim.inspector.utils.InspectionBundle;
11 | import com.itkim.inspector.utils.SecExpressionUtils;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | /**
15 | * 1040
16 | * java/io/FileInputStream * 1 false # 文件读取的sink # FILE_READ
17 | * java/lang/Class getResourceAsStream (Ljava/lang/String;)Ljava/io/InputStream; 1 false # 文件读取 # FILE_READ
18 | *
19 | * org.apache.commons.io.FileUtils#readFileToByteArray
20 | * org.apache.commons.io.FileUtils#readFileToString(java.io.File)
21 | * org.apache.commons.io.FileUtils#readFileToString(java.io.File, java.nio.charset.Charset)
22 | * org.apache.commons.io.FileUtils#readFileToString(java.io.File, java.lang.String)
23 | * org.apache.commons.io.FileUtils#readLines(java.io.File)
24 | * org.apache.commons.io.FileUtils#readLines(java.io.File, java.nio.charset.Charset)
25 | * org.apache.commons.io.FileUtils#readLines(java.io.File, java.lang.String)
26 | */
27 | public class FileRead extends BaseLocalInspectionTool {
28 | public static final String MESSAGE = InspectionBundle.message("file.read.type.msg");
29 |
30 | @Override
31 | @NotNull
32 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
33 | return new JavaElementVisitor() {
34 | @Override
35 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
36 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.lang.Class", "getResourceAsStream")
37 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.io.FileUtils", "readFileToByteArray")
38 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.io.FileUtils", "readFileToString")
39 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.io.FileUtils", "readLines")) {
40 | holder.registerProblem(
41 | expression,
42 | MESSAGE,
43 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
44 | }
45 | }
46 |
47 | @Override
48 | public void visitNewExpression(PsiNewExpression expression) {
49 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.io.FileInputStream")) {
50 | holder.registerProblem(
51 | expression,
52 | MESSAGE,
53 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
54 | }
55 | }
56 | };
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssti/FreemarkeraSSTI.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssti;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.intellij.psi.PsiNewExpression;
9 | import com.itkim.inspector.BaseLocalInspectionTool;
10 | import com.itkim.inspector.utils.InspectionBundle;
11 | import com.itkim.inspector.utils.SecExpressionUtils;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | /**
15 | * 1035
16 | * freemarker/cache/StringTemplateLoader putTemplate * 2 all # Freemarker # SSTI
17 | * freemarker/template/Template (Ljava/lang/String;Ljava/io/Reader;) 2 all # Freemarker # SSTI
18 | * freemarker/template/Template (Ljava/lang/String;Ljava/io/Reader;Lfreemarker/template/Configuration;) 2 all # Freemarker # SSTI
19 | * freemarker/template/Template (Ljava/lang/String;Ljava/io/Reader;Lfreemarker/template/Configuration;Ljava/lang/String;) 2 all # Freemarker # SSTI
20 | * freemarker/template/Template (Ljava/lang/String;Ljava/lang/String;Lfreemarker/template/Configuration;) 2 all # Freemarker # SSTI
21 | * freemarker/template/Template (Ljava/lang/String;Ljava/lang/String;Ljava/io/Reader;Lfreemarker/template/Configuration;) 3 all # Freemarker # SSTI
22 | * freemarker/template/Template (Ljava/lang/String;Ljava/lang/String;Ljava/io/Reader;Lfreemarker/template/Configuration;LParserConfiguration;Ljava/lang/String;) 3 all # Freemarker # SSTI
23 | * freemarker/template/Template (Ljava/lang/String;Ljava/lang/String;Ljava/io/Reader;Lfreemarker/template/Configuration;Ljava/lang/String;) 3 all # Freemarker # SSTI
24 | */
25 | public class FreemarkeraSSTI extends BaseLocalInspectionTool {
26 | public static final String MESSAGE = InspectionBundle.message("freemarker.ssti.type.msg");
27 |
28 | @Override
29 | @NotNull
30 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
31 | return new JavaElementVisitor() {
32 | @Override
33 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
34 | if (SecExpressionUtils.hasFullQualifiedName(expression, "freemarker.cache.StringTemplateLoader", "putTemplate")) {
35 | holder.registerProblem(
36 | expression,
37 | MESSAGE,
38 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
39 | }
40 | }
41 |
42 | @Override
43 | public void visitNewExpression(PsiNewExpression expression) {
44 | if (SecExpressionUtils.hasFullQualifiedName(expression, "freemarker.template.Template")) {
45 | holder.registerProblem(
46 | expression,
47 | MESSAGE,
48 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
49 | }
50 | }
51 | };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssti/VelocitySSTI.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssti;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1032
15 | * org/apache/velocity/app/Velocity evaluate * 4 all # Velocity # SSTI
16 | * org/apache/velocity/app/Velocity mergeTemplate * 3 all # Velocity # SSTI
17 | * org/apache/velocity/app/VelocityEngine evaluate * 4 all # Velocity # SSTI
18 | * org/apache/velocity/app/VelocityEngine mergeTemplate * 3 all # Velocity # SSTI
19 | * org/apache/velocity/runtime/RuntimeServices evaluate * 4 all # Velocity # SSTI
20 | * org/apache/velocity/runtime/RuntimeServices parse * 1 all # Velocity # SSTI
21 | * org/apache/velocity/runtime/RuntimeSingleton parse * 1 all # Velocity # SSTI
22 | * org/apache/velocity/runtime/resource/util/StringResourceRepository putStringResource * 2 all # Velocity # SSTI
23 | */
24 | public class VelocitySSTI extends BaseLocalInspectionTool {
25 | public static final String MESSAGE = InspectionBundle.message("velocity.ssti.type.msg");
26 |
27 | @Override
28 | @NotNull
29 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
30 | return new JavaElementVisitor() {
31 | @Override
32 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
33 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.app.Velocity", "evaluate")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.app.Velocity", "mergeTemplate")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.app.VelocityEngine", "evaluate")
36 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.app.VelocityEngine", "mergeTemplate")
37 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.runtime.RuntimeServices", "evaluate")
38 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.runtime.RuntimeServices", "parse")
39 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.runtime.RuntimeSingleton", "parse")
40 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.velocity.runtime.resource.util.StringResourceRepository", "putStringResource")
41 | ) {
42 | holder.registerProblem(
43 | expression,
44 | MESSAGE,
45 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
46 | }
47 | }
48 | };
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/redirect/JavaxRedirect.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.redirect;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.intellij.psi.PsiNewExpression;
9 | import com.itkim.inspector.BaseLocalInspectionTool;
10 | import com.itkim.inspector.utils.InspectionBundle;
11 | import com.itkim.inspector.utils.SecExpressionUtils;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | /**
15 | * 1044
16 | * javax/servlet/http/HttpServletResponse sendRedirect (Ljava/lang/String;)V 1 false # REDIRECT # REDIRECT
17 | * javax/servlet/RequestDispatcher getRequestDispatcher (Ljava/lang/String;)Ljavax/servlet/RequestDispatcher; 1 false # REDIRECT # REDIRECT
18 | * javax/servlet/http/HttpServletRequest getRequestDispatcher (Ljava/lang/String;)Ljavax/servlet/RequestDispatcher; 1 false # REDIRECT # REDIRECT
19 | * org/springframework/web/servlet/ModelAndView (Ljava/lang/String;)V 1 false # REDIRECT # REDIRECT
20 | * javax/ws/rs/core/Response seeOther * 1 all # REDIRECT # REDIRECT
21 | * javax/ws/rs/core/Response temporaryRedirect * 1 all # REDIRECT # REDIRECT
22 | */
23 | public class JavaxRedirect extends BaseLocalInspectionTool {
24 | public static final String MESSAGE = InspectionBundle.message("javax.redirect.type.msg");
25 |
26 | @Override
27 | @NotNull
28 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
29 | return new JavaElementVisitor() {
30 | @Override
31 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
32 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.servlet.http.HttpServletResponse", "sendRedirect")
33 | || SecExpressionUtils.hasFullQualifiedName(expression, "javax.servlet.RequestDispatcher", "getRequestDispatcher")
34 | || SecExpressionUtils.hasFullQualifiedName(expression, "javax.servlet.http.HttpServletRequest", "getRequestDispatcher")
35 | || SecExpressionUtils.hasFullQualifiedName(expression, "javax.ws.rs.core.Response", "seeOther")
36 | || SecExpressionUtils.hasFullQualifiedName(expression, "javax.ws.rs.core.Response", "temporaryRedirect")) {
37 | holder.registerProblem(
38 | expression,
39 | MESSAGE,
40 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
41 | }
42 | }
43 |
44 | @Override
45 | public void visitNewExpression(PsiNewExpression expression) {
46 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.servlet.ModelAndView")) {
47 | holder.registerProblem(
48 | expression,
49 | MESSAGE,
50 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
51 | }
52 | }
53 | };
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/KryoUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1014
30 | * com/esotericsoftware/kryo/Kryo readObject (Lcom/esotericsoftware/kryo/io/Input;Ljava/lang/Class;)Ljava/lang/Object; 1 false # Kryo反序列化 # RCE
31 | * com/esotericsoftware/kryo/Kryo readObject (Lcom/esotericsoftware/kryo/io/Input;Ljava/lang/Class;Lcom/esotericsoftware/kryo/Serializer;)Ljava/lang/Object; 1 false # Kryo反序列化 # RCE
32 | * com/esotericsoftware/kryo/Kryo readObjectOrNull (Lcom/esotericsoftware/kryo/io/Input;Ljava/lang/Class;)Ljava/lang/Object; 1 false # Kryo反序列化 # RCE
33 | * com/esotericsoftware/kryo/Kryo readObjectOrNull (Lcom/esotericsoftware/kryo/io/Input;Ljava/lang/Class;Lcom/esotericsoftware/kryo/Serializer;)Ljava/lang/Object; 1 false # Kryo反序列化 # RCE
34 | * com/esotericsoftware/kryo/Kryo readClassAndObject (Lcom/esotericsoftware/kryo/io/Input;)Ljava/lang/Object; 1 false # Kryo反序列化 # RCE
35 | */
36 | public class KryoUnserialize extends BaseLocalInspectionTool {
37 | public static final String MESSAGE = InspectionBundle.message("kryo.unserialize.type.msg");
38 |
39 | @Override
40 | @NotNull
41 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
42 | return new JavaElementVisitor() {
43 | @Override
44 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
45 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.esotericsoftware.kryo.Kryo", "readObject")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.esotericsoftware.kryo.Kryo", "readObjectOrNull")
47 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.esotericsoftware.kryo.Kryo", "readClassAndObject")
48 | ) {
49 | holder.registerProblem(
50 | expression,
51 | MESSAGE,
52 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
53 | }
54 | }
55 | };
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/openSAML2/OpenSAML2IgnoreComment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.openSAML2;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.intellij.util.ObjectUtils;
22 | import com.itkim.inspector.BaseLocalInspectionTool;
23 | import com.itkim.inspector.fix.SetBoolArgQuickFix;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import com.siyeh.ig.psiutils.ExpressionUtils;
27 | import org.jetbrains.annotations.NotNull;
28 |
29 | /**
30 | * Momo 1024: OpenSAML2 认证绕过风险
31 | *
32 | * 在不忽略XML注释的情况下,攻击者可以设法更改NameID字段以使用XML注释来标识用户身份。
33 | *
34 | * ref: https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-5679
35 | */
36 | public class OpenSAML2IgnoreComment extends BaseLocalInspectionTool {
37 | public static final String MESSAGE = InspectionBundle.message("open.saml2.ignore.comment.msg");
38 | public static final String QUICK_FIX_NAME = InspectionBundle.message("open.saml2.ignore.comment.fix");
39 |
40 | @Override
41 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
42 | return new JavaElementVisitor() {
43 | @Override
44 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
45 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.opensaml.xml.parse.StaticBasicParserPool", "setIgnoreComments") ||
46 | SecExpressionUtils.hasFullQualifiedName(expression, "org.opensaml.xml.parse.BasicParserPool", "setIgnoreComments")
47 | ) {
48 | PsiExpression[] args = expression.getArgumentList().getExpressions();
49 | if (args.length > 0) {
50 | PsiLiteralExpression arg0 = ObjectUtils.tryCast(args[0], PsiLiteralExpression.class);
51 | if (arg0 == null) return ;
52 | if (ExpressionUtils.isLiteral(arg0, Boolean.FALSE)) {
53 | holder.registerProblem(
54 | expression,
55 | MESSAGE,
56 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
57 | new SetBoolArgQuickFix(QUICK_FIX_NAME, true, arg0)
58 | );
59 | }
60 | }
61 | }
62 | }
63 | };
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/HardcodedIp.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.JavaTokenType;
22 | import com.intellij.psi.PsiElementVisitor;
23 | import com.intellij.psi.PsiLiteralExpression;
24 | import com.intellij.psi.tree.IElementType;
25 | import com.itkim.inspector.BaseLocalInspectionTool;
26 | import com.itkim.inspector.utils.InspectionBundle;
27 | import org.jetbrains.annotations.NotNull;
28 |
29 |
30 | /**
31 | * 1071: IP地址硬编码
32 | *
33 | * ref: https://rules.sonarsource.com/java/type/Security%20Hotspot/RSPEC-1313
34 | */
35 | public class HardcodedIp extends BaseLocalInspectionTool {
36 | public static final String MESSAGE = InspectionBundle.message("hardcoded.ip.msg");
37 |
38 | @Override
39 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
40 | return new JavaElementVisitor() {
41 | @Override
42 | public void visitLiteralExpression(PsiLiteralExpression expression) {
43 | IElementType type = expression.getFirstChild().getNode().getElementType();
44 | if (type == JavaTokenType.STRING_LITERAL) {
45 | Object v = expression.getValue();
46 | if (v != null && isSensitiveIp(v.toString())) {
47 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
48 | }
49 | }
50 | }
51 | };
52 | }
53 |
54 | private static boolean isSensitiveIp(String ip) {
55 | //判断是否是7-15位之间(0.0.0.0-255.255.255.255.255)
56 | if (ip.length()<7||ip.length()>15) {
57 | return false;
58 | }
59 |
60 | //判断是否能以小数点分成四段
61 | String[] ipArray = ip.split("\\.");
62 | if (ipArray.length != 4) {
63 | return false;
64 | }
65 |
66 | for (int i = 0; i < ipArray.length; i++) {
67 | //判断每段是否都是数字
68 | try {
69 | int number = Integer.parseInt(ipArray[i]);
70 | //判断每段数字是否都在0-255之间
71 | if (number < 0 || number > 255) {
72 | return false;
73 | }
74 |
75 | // 忽略 127.0.0.1/8
76 | if (i == 0 && number == 127) {
77 | return false;
78 | }
79 | } catch (Exception e) {
80 | return false;
81 | }
82 | }
83 |
84 |
85 | if ("255.255.255.255".equals(ip) || // 忽略 255.255.255.255
86 | "0.0.0.0".equals(ip) || // 忽略 0.0.0.0
87 | ip.startsWith("2.5.") // // 忽略 2.5.x.x (OID)
88 | ) {
89 | return false;
90 | }
91 |
92 | return true;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/SpringSessionFixProtection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.codeInspection.ProblemHighlightType;
21 | import com.intellij.codeInspection.ProblemsHolder;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.psi.*;
24 | import com.intellij.util.ObjectUtils;
25 | import com.itkim.inspector.BaseLocalInspectionTool;
26 | import com.itkim.inspector.utils.InspectionBundle;
27 | import com.itkim.inspector.utils.SecExpressionUtils;
28 | import org.jetbrains.annotations.Nls;
29 | import org.jetbrains.annotations.NotNull;
30 |
31 | /**
32 | * 1057: Spring 会话固定攻击风险
33 | *
34 | * 默认开启,但使用sessionFixation().none()会关闭
35 | *
36 | * ref: https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-5876
37 | */
38 | public class SpringSessionFixProtection extends BaseLocalInspectionTool {
39 | public static final String MESSAGE = InspectionBundle.message("spring.session.fix.protection.msg");
40 | public static final String QUICK_FIX_NAME = InspectionBundle.message("spring.session.fix.protection.fix");
41 |
42 | private final SpringSessionFixProtectionQuickFix springSessionFixProtectionQuickFix = new SpringSessionFixProtectionQuickFix();
43 |
44 | @Override
45 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
46 | return new JavaElementVisitor() {
47 | @Override
48 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
49 | if (SecExpressionUtils.hasFullQualifiedName(
50 | expression,
51 | "org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer.SessionFixationConfigurer",
52 | "none")
53 | ) {
54 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, springSessionFixProtectionQuickFix);
55 | }
56 | }
57 | };
58 | }
59 |
60 | public static class SpringSessionFixProtectionQuickFix implements LocalQuickFix {
61 | @Override
62 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
63 | return QUICK_FIX_NAME;
64 | }
65 |
66 | @Override
67 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
68 | PsiMethodCallExpression methodCallExp = ObjectUtils.tryCast(descriptor.getPsiElement(), PsiMethodCallExpression.class);
69 | if (methodCallExp == null) {
70 | return ;
71 | }
72 |
73 | PsiReferenceExpression referenceExpression = methodCallExp.getMethodExpression();
74 | if ("none".equals(referenceExpression.getReferenceName())) {
75 | PsiIdentifier identifier = ObjectUtils.tryCast(referenceExpression.getLastChild(), PsiIdentifier.class);
76 | if (identifier != null) {
77 | identifier.replace(JavaPsiFacade.getElementFactory(project).createIdentifier("migrateSession"));
78 | }
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/jndi/LDAPUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.jndi;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.fix.SetBoolArgQuickFix;
23 | import com.itkim.inspector.utils.InspectionBundle;
24 | import com.itkim.inspector.utils.SecExpressionUtils;
25 | import org.jetbrains.annotations.NotNull;
26 |
27 | /**
28 | * 1060: LDAP反序列化风险
29 | *
30 | * ref: https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-4434
31 | */
32 | public class LDAPUnserialize extends BaseLocalInspectionTool {
33 | public static final String MESSAGE = InspectionBundle.message("ldap.unserialize.msg");
34 | private static final String QUICK_FIX_NAME = InspectionBundle.message("ldap.unserialize.fix");
35 |
36 | @Override
37 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
38 | return new JavaElementVisitor() {
39 | @Override
40 | public void visitNewExpression(PsiNewExpression expression) {
41 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.naming.directory.SearchControls")) {
42 | PsiExpressionList expressionList = expression.getArgumentList();
43 | if (expressionList != null && expressionList.getExpressionCount() == 6) {
44 | PsiExpression[] args = expressionList.getExpressions();
45 | if (args[4] instanceof PsiLiteralExpression &&
46 | Boolean.TRUE.equals(((PsiLiteralExpression) args[4]).getValue())
47 | ) {
48 | holder.registerProblem(
49 | expression,
50 | MESSAGE,
51 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
52 | new SetBoolArgQuickFix(QUICK_FIX_NAME, false, (PsiLiteralExpression)args[4])
53 | );
54 | }
55 | }
56 | }
57 | }
58 |
59 | @Override
60 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
61 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.naming.directory.SearchControls", "setReturningObjFlag")) {
62 | PsiExpressionList expressionList = expression.getArgumentList();
63 | PsiExpression[] args = expressionList.getExpressions();
64 | if (args.length == 1 &&
65 | args[0] instanceof PsiLiteralExpression &&
66 | Boolean.TRUE.equals(((PsiLiteralExpression)args[0]).getValue())
67 | ) {
68 | holder.registerProblem(
69 | expression,
70 | MESSAGE,
71 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
72 | new SetBoolArgQuickFix(QUICK_FIX_NAME, false, (PsiLiteralExpression)args[0])
73 | );
74 | }
75 | }
76 | }
77 | };
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/CastorUnserialize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.rce;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiMethodCallExpression;
23 | import com.itkim.inspector.BaseLocalInspectionTool;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SecExpressionUtils;
26 | import org.jetbrains.annotations.NotNull;
27 |
28 | /**
29 | * 1012
30 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljava/io/Reader;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
31 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljava/io/Reader;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
32 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/exolab/castor/xml/EventProducer;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
33 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/exolab/castor/xml/SAX2EventProducer;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
34 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/exolab/castor/types/AnyNode;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
35 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/xml/sax/InputSource;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
36 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/w3c/dom/Node;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
37 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljavax/xml/stream/XMLEventReader;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
38 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljavax/xml/stream/XMLStreamReader;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
39 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/exolab/castor/xml/SAX2EventAndErrorProducer;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
40 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljavax/xml/transform/Source;)Ljava/lang/Object; 1 false # castor反序列化 # RCE
41 | * org/exolab/castor/xml/Unmarshaller unmarshal (Lorg/exolab/castor/xml/UnmarshalHandler;)Lorg/xml/sax/ContentHandler; 1 false # castor反序列化 # RCE
42 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljava/lang/Class;Ljava/io/Reader;)Ljava/lang/Object; 2 false # castor反序列化 # RCE
43 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljava/lang/Class;Lorg/xml/sax/InputSource;)Ljava/lang/Object; 2 false # castor反序列化 # RCE
44 | * org/exolab/castor/xml/Unmarshaller unmarshal (Ljava/lang/Class;Lorg/w3c/dom/Node;)Ljava/lang/Object; 2 false # castor反序列化 # RCE
45 | */
46 | public class CastorUnserialize extends BaseLocalInspectionTool {
47 | public static final String MESSAGE = InspectionBundle.message("castor.unserialize.type.msg");
48 |
49 | @Override
50 | @NotNull
51 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
52 | return new JavaElementVisitor() {
53 | @Override
54 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
55 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.exolab.castor.xml.Unmarshaller", "unmarshal")) {
56 | holder.registerProblem(
57 | expression,
58 | MESSAGE,
59 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
60 | }
61 | }
62 | };
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/SpringSecurityDebugEnabled.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.codeInspection.ProblemHighlightType;
21 | import com.intellij.codeInspection.ProblemsHolder;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.psi.*;
24 | import com.itkim.inspector.BaseLocalInspectionTool;
25 | import com.itkim.inspector.utils.InspectionBundle;
26 | import org.jetbrains.annotations.Nls;
27 | import org.jetbrains.annotations.NotNull;
28 |
29 | /**
30 | * 1056: SpringSecurity关闭Debug模式
31 | *
32 | * ref: https://rules.sonarsource.com/java/type/Security%20Hotspot/RSPEC-4507
33 | */
34 | public class SpringSecurityDebugEnabled extends BaseLocalInspectionTool {
35 | public static final String MESSAGE = InspectionBundle.message("spring.security.debug.enabled.msg");
36 | private static final String QUICK_FIX_NAME = InspectionBundle.message("spring.security.debug.enabled.fix");
37 | private final SpringSecurityDebugDisable springSecurityDebugDisable = new SpringSecurityDebugDisable();
38 |
39 | @Override
40 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
41 | return new JavaElementVisitor() {
42 | @Override
43 | public void visitAnnotation(PsiAnnotation annotation) {
44 | if ("org.springframework.security.config.annotation.web.configuration.EnableWebSecurity".equals(annotation.getQualifiedName())) {
45 | PsiAnnotationParameterList annotationParameterList = annotation.getParameterList();
46 | PsiNameValuePair[] nameValuePairs = annotationParameterList.getAttributes();
47 | for(PsiNameValuePair nameValuePair : nameValuePairs) {
48 | if ("debug".equals(nameValuePair.getAttributeName()) &&
49 | "true".equals(nameValuePair.getLiteralValue())
50 | ) {
51 | holder.registerProblem(
52 | nameValuePair,
53 | MESSAGE,
54 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
55 | springSecurityDebugDisable
56 | );
57 | }
58 | }
59 | }
60 | }
61 | };
62 | }
63 |
64 | public static class SpringSecurityDebugDisable implements LocalQuickFix {
65 |
66 | @Override
67 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
68 | return QUICK_FIX_NAME;
69 | }
70 |
71 | @Override
72 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
73 | PsiNameValuePair nameValuePair = (PsiNameValuePair)descriptor.getPsiElement();
74 | if ("debug".equals(nameValuePair.getAttributeName())) {
75 | PsiAnnotationMemberValue member = nameValuePair.getValue();
76 | PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
77 | if (member != null) {
78 | member.replace(factory.createExpressionFromText("false", null));
79 | }
80 | }
81 |
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/OGNLInjectionRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1020
15 | * com/opensymphony/xwork2/ognl/OgnlUtil callMethod * 1 false # ognl-injection # RCE
16 | * com/opensymphony/xwork2/ognl/OgnlUtil getValue * 1 false # ognl-injection # RCE
17 | * com/opensymphony/xwork2/ognl/OgnlUtil setValue * 1 false # ognl-injection # RCE
18 | * ognl/Node getValue * 0 false # ognl-injection # RCE
19 | * ognl/Node setValue * 0 false # ognl-injection # RCE
20 | * ognl/Ognl getValue * 1 false # ognl-injection # RCE
21 | * ognl/Ognl setValue * 1 false # ognl-injection # RCE
22 | * ognl/enhance/ExpressionAccessor get * 0 all # ognl-injection # RCE
23 | * ognl/enhance/ExpressionAccessor set * 0 all # ognl-injection # RCE
24 | * org/apache/commons/ognl/Node getValue * 0 all # ognl-injection # RCE
25 | * org/apache/commons/ognl/Node setValue * 0 all # ognl-injection # RCE
26 | * org/apache/commons/ognl/Ognl getValue * 1 false # ognl-injection # RCE
27 | * org/apache/commons/ognl/Ognl setValue * 1 false # ognl-injection # RCE
28 | * org/apache/commons/ognl/enhance/ExpressionAccessor get * 0 all # ognl-injection # RCE
29 | * org/apache/commons/ognl/enhance/ExpressionAccessor set * 0 all # ognl-injection # RCE
30 | */
31 | public class OGNLInjectionRCE extends BaseLocalInspectionTool {
32 | public static final String MESSAGE = InspectionBundle.message("ognl.injection.rce.type.msg");
33 |
34 | @Override
35 | @NotNull
36 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
37 | return new JavaElementVisitor() {
38 | @Override
39 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
40 | if (SecExpressionUtils.hasFullQualifiedName(expression, "com.opensymphony.xwork2.ognl.OgnlUtil", "callMethod")
41 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.opensymphony.xwork2.ognl.OgnlUtil", "getValue")
42 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.opensymphony.xwork2.ognl.OgnlUtil", "setValue")
43 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.Node", "getValue")
44 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.Node", "setValue")
45 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.Ognl", "getValue")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.Ognl", "setValue")
47 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.enhance.ExpressionAccessor", "get")
48 | || SecExpressionUtils.hasFullQualifiedName(expression, "ognl.enhance.ExpressionAccessor", "set")
49 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.Node", "getValue")
50 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.Node", "setValue")
51 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.Ognl", "getValue")
52 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.Ognl", "setValue")
53 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.enhance.ExpressionAccessor", "get")
54 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.ognl.enhance.ExpressionAccessor", "set")
55 | )
56 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
57 | }
58 | };
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/sqli/BaseSQLi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.sqli;
17 |
18 | import com.intellij.psi.PsiExpression;
19 | import com.intellij.psi.PsiMethodCallExpression;
20 | import com.intellij.psi.util.PsiTreeUtil;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.utils.SQLiUtil;
23 | import com.itkim.inspector.utils.SecExpressionUtils;
24 | import com.siyeh.ig.psiutils.MethodCallUtils;
25 |
26 | import java.util.ArrayList;
27 | import java.util.List;
28 | import java.util.regex.Matcher;
29 | import java.util.regex.Pattern;
30 |
31 | public abstract class BaseSQLi extends BaseLocalInspectionTool {
32 |
33 | private static final Pattern sqlPattern =
34 | Pattern.compile("^\\s*(select|delete|update|insert)\\s+.*?(from|into|set)\\s+.*?where.*", Pattern.CASE_INSENSITIVE);
35 |
36 | /**
37 | * 判断指定字符串是否为SQL语句
38 | * @param str String
39 | * @return boolean
40 | */
41 | protected boolean isSql(String str) {
42 | return sqlPattern.matcher(str).find();
43 | }
44 |
45 | /**
46 | * 按 needle 拆分字符串后,判断拆分数组是否有拼接SQL注入风险
47 | * @param content String
48 | * @param pattern Pattern
49 | * @return boolean
50 | */
51 | protected boolean hasEvalAdditive(String content, Pattern pattern) {
52 | Matcher m = pattern.matcher(content);
53 | int offset = 0;
54 | int count = 0;
55 | List prefixes = new ArrayList<>();
56 | while(m.find(offset) && count++ < 9999) {
57 | prefixes.add(content.substring(0, m.start()));
58 | offset = m.end();
59 | }
60 | return hasEvalAdditive(prefixes);
61 | }
62 |
63 | /**
64 | * 判断数组是否有拼接SQL注入风险
65 | * @param prefixes List
66 | * @return boolean
67 | */
68 | protected boolean hasEvalAdditive(List prefixes) {
69 | return prefixes.stream()
70 | .anyMatch(prefix -> SQLiUtil.hasVulOnSQLJoinStr(prefix, null, null));
71 | }
72 |
73 | protected boolean ignoreMethodName(PsiExpression expression) {
74 | PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class);
75 | if (methodCallExpression != null &&
76 | SecExpressionUtils.hasFullQualifiedName(methodCallExpression, "java.lang.String", "format")) {
77 | methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class);
78 | }
79 | if (methodCallExpression == null) {
80 | return false;
81 | }
82 | String methodName = MethodCallUtils.getMethodName(methodCallExpression);
83 | if (methodName != null) { // 排除日志打印语句
84 | String lowerMethodName = methodName.toLowerCase();
85 | return lowerMethodName.contains("log") ||
86 | lowerMethodName.contains("trace") ||
87 | lowerMethodName.contains("debug") ||
88 | lowerMethodName.contains("info") ||
89 | lowerMethodName.contains("alarm") ||
90 | lowerMethodName.contains("warn") ||
91 | lowerMethodName.contains("error") ||
92 | lowerMethodName.contains("fatal") ||
93 | lowerMethodName.contains("ok") ||
94 | lowerMethodName.contains("succ") ||
95 | lowerMethodName.contains("fail") ||
96 | lowerMethodName.contains("print");
97 | }
98 | return false;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/MVELRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1018
15 | * org/mvel2/MVEL eval * 1 false # MVEL # RCE
16 | * org/mvel2/MVEL evalToBoolean * 1 false # MVEL # RCE
17 | * org/mvel2/MVEL evalToString * 1 false # MVEL # RCE
18 | * org/mvel2/MVEL executeAllExpression * 1 false # MVEL # RCE
19 | * org/mvel2/MVEL executeExpression * 1 false # MVEL # RCE
20 | * org/mvel2/MVEL executeSetExpression * 1 false # MVEL # RCE
21 | * org/mvel2/MVELRuntime execute * 2 false # MVEL # RCE
22 | * org/mvel2/compiler/Accessor getValue * 0 false # MVEL # RCE
23 | * org/mvel2/compiler/CompiledAccExpression getValue * 0 false # MVEL # RCE
24 | * org/mvel2/compiler/CompiledExpression getDirectValue * 0 false # MVEL # RCE
25 | * org/mvel2/compiler/ExecutableStatement getValue * 0 false # MVEL # RCE
26 | * org/mvel2/jsr223/MvelCompiledScript eval * 0 false # MVEL # RCE
27 | * org/mvel2/jsr223/MvelScriptEngine eval * 1 false # MVEL # RCE
28 | * org/mvel2/jsr223/MvelScriptEngine evaluate * 1 false # MVEL # RCE
29 | * org/mvel2/templates/TemplateRuntime eval * 1 false # MVEL # RCE
30 | * org/mvel2/templates/TemplateRuntime execute * 1 false # MVEL # RCE
31 | */
32 | public class MVELRCE extends BaseLocalInspectionTool {
33 |
34 | public static final String MESSAGE = InspectionBundle.message("mvel.rce.type.msg");
35 |
36 | @Override
37 | @NotNull
38 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
39 | return new JavaElementVisitor() {
40 | @Override
41 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
42 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "eval")
43 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "evalToBoolean")
44 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "evalToString")
45 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "executeAllExpression")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "executeExpression")
47 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVEL", "executeSetExpression")
48 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.MVELRuntime", "execute")
49 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.compiler.Accessor", "getValue")
50 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.compiler.CompiledAccExpression", "getValue")
51 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.compiler.CompiledExpression", "getDirectValue")
52 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.compiler.ExecutableStatement", "getValue")
53 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.jsr223.MvelCompiledScript", "eval")
54 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.jsr223.MvelScriptEngine", "eval")
55 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.jsr223.MvelScriptEngine", "evaluate")
56 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.templates.TemplateRuntime", "eval")
57 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.mvel2.templates.TemplateRuntime", "execute"))
58 | holder.registerProblem(
59 | expression,
60 | MESSAGE,
61 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
62 | }
63 | };
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/utils/SQLiUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.utils;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 | import org.jetbrains.annotations.Nullable;
20 |
21 | import java.util.Arrays;
22 | import java.util.List;
23 | import java.util.regex.Pattern;
24 | import java.util.stream.Collectors;
25 |
26 | public class SQLiUtil {
27 |
28 | public static final Pattern whereInEndPattern = Pattern.compile("(where|and|or)\\s+\\S+?\\s+in\\s*\\(?\\s*$", Pattern.CASE_INSENSITIVE);
29 | public static final Pattern likeEndPatterh = Pattern.compile("\\S+?\\s+like\\s+('|\")%?$", Pattern.CASE_INSENSITIVE);
30 |
31 | public static final Pattern placeholderPattern = Pattern.compile("%(\\d\\$\\d{0,5})?s", Pattern.CASE_INSENSITIVE);
32 | public static final Pattern dollarVarPattern = Pattern.compile("\\$\\{(\\S+?)\\}");
33 |
34 |
35 | /**
36 | * 判断SQL拼接点的字符串集合是否有SQL注入风险
37 | * @param SQLJoinStrList List
38 | * @return boolean
39 | */
40 | public static boolean hasVulOnSQLJoinStrList(@NotNull List> SQLJoinStrList) {
41 | for(List sqlJoinStr : SQLJoinStrList) {
42 | if (sqlJoinStr.size() < 2 || sqlJoinStr.size() > 3) {
43 | continue;
44 | }
45 | if (sqlJoinStr.size() == 2 && hasVulOnSQLJoinStr(sqlJoinStr.get(0), sqlJoinStr.get(1), null)) {
46 | return true;
47 | }
48 | if (sqlJoinStr.size() == 3 && hasVulOnSQLJoinStr(sqlJoinStr.get(0), sqlJoinStr.get(1), sqlJoinStr.get(2))) {
49 | return true;
50 | }
51 | }
52 | return false;
53 | }
54 |
55 | /**
56 | * 判断SQL拼接点的字符串是否有SQL注入风险
57 | * @param prefix String
58 | * @param var String
59 | * @param suffix String
60 | * @return boolean
61 | */
62 | public static boolean hasVulOnSQLJoinStr(@NotNull String prefix, @Nullable String var, @Nullable String suffix) {
63 | List fragments = Arrays.stream(prefix.split("[\\s|(]+"))
64 | .map(String::trim)
65 | .filter(item -> !item.isEmpty())
66 | .collect(Collectors.toList());
67 | int seg_size = fragments.size();
68 | if (seg_size == 0 ||
69 | fragments.get(seg_size - 1).trim().endsWith("=") ||
70 | fragments.get(seg_size - 1).trim().endsWith(">=") ||
71 | fragments.get(seg_size - 1).trim().endsWith("<=")
72 | ) {
73 | return true;
74 | }
75 |
76 | for(int i = seg_size - 1; i >= 0; i--) {
77 | String frag = fragments.get(i);
78 | if (frag.equals("limit") ||
79 | frag.equals("by") ||
80 | frag.equals("having")
81 | ) {
82 | continue;
83 | }
84 |
85 | if (frag.equals("where") || frag.equals("set")) {
86 | if (suffix != null && (
87 | suffix.trim().startsWith("=") ||
88 | suffix.trim().startsWith(">") ||
89 | suffix.trim().startsWith("<")
90 | )) {
91 | return false;
92 | }
93 | return true;
94 | }
95 |
96 | if (frag.equals("values")) {
97 | return true;
98 | }
99 |
100 | if (frag.equals("from") ||
101 | frag.equals("into") ||
102 | frag.equals("join") ||
103 | frag.equals("select") ||
104 | frag.equals("update")
105 | ) {
106 | return false;
107 | }
108 | }
109 | return true;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/PredictableSeed.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.codeInspection.ProblemHighlightType;
21 | import com.intellij.codeInspection.ProblemsHolder;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.psi.*;
24 | import com.itkim.inspector.BaseLocalInspectionTool;
25 | import com.itkim.inspector.fix.DeleteElementQuickFix;
26 | import com.itkim.inspector.utils.InspectionBundle;
27 | import com.itkim.inspector.utils.SecExpressionUtils;
28 | import org.jetbrains.annotations.Nls;
29 | import org.jetbrains.annotations.NotNull;
30 |
31 | /**
32 | * 1054: 固定的随机数种子风险
33 | *
34 | * ref: https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-4347
35 | */
36 | public class PredictableSeed extends BaseLocalInspectionTool {
37 | public static final String MESSAGE = InspectionBundle.message("predictable.seed.msg");
38 | private static final String QUICK_FIX_NAME = InspectionBundle.message("predictable.seed.fix");
39 |
40 | @Override
41 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
42 | return new JavaElementVisitor() {
43 | @Override
44 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
45 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.security.SecureRandom", "setSeed")) {
46 | PsiExpression[] args = expression.getArgumentList().getExpressions();
47 | if (args.length != 1) { return ; }
48 | PsiExpression arg0 = args[0];
49 | if (arg0 instanceof PsiLiteralExpression) {
50 | holder.registerProblem(
51 | expression,
52 | MESSAGE,
53 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
54 | new DeleteElementQuickFix(expression, QUICK_FIX_NAME)
55 | );
56 | }
57 | }
58 | }
59 |
60 | @Override
61 | public void visitNewExpression(PsiNewExpression expression) {
62 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.security.SecureRandom")) {
63 | PsiExpressionList expressionList = expression.getArgumentList();
64 | if (expressionList != null && expressionList.getExpressions().length != 0) {
65 | holder.registerProblem(
66 | expression,
67 | MESSAGE,
68 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
69 | new PredictableSeedQuickFix(expressionList)
70 | );
71 | }
72 | }
73 | }
74 | };
75 | }
76 |
77 | public static class PredictableSeedQuickFix implements LocalQuickFix {
78 |
79 | private final SmartPsiElementPointer argList;
80 |
81 | public PredictableSeedQuickFix(PsiExpressionList expressionList) {
82 | this.argList = SmartPointerManager.createPointer(expressionList);
83 | }
84 |
85 | @Override
86 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
87 | return QUICK_FIX_NAME;
88 | }
89 |
90 | @Override
91 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
92 | PsiExpressionList args = argList.getElement();
93 | if (args != null) {
94 | for(PsiExpression arg : args.getExpressions()) {
95 | arg.delete();
96 | }
97 | }
98 | }
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/WeakHashInspector.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.BaseLocalInspectionTool;
22 | import com.itkim.inspector.utils.InspectionBundle;
23 | import com.itkim.inspector.utils.SecExpressionUtils;
24 | import com.siyeh.ig.psiutils.MethodCallUtils;
25 | import org.jetbrains.annotations.NotNull;
26 |
27 | import java.util.HashSet;
28 | import java.util.Set;
29 |
30 | /**
31 | * MD2, MD4, MD5 为脆弱的消息摘要算法
32 | *
33 | * MD5的安全性受到严重损害。在4核2.6GHz的机器上,碰撞攻击可以在秒级完成。选择前缀碰撞攻击可以在小时级完成。
34 | *
35 | * ref:
36 | * https://en.wikipedia.org/wiki/MD5#Security
37 | */
38 | public class WeakHashInspector extends BaseLocalInspectionTool {
39 | public static final String MESSAGE = InspectionBundle.message("weak.hash.inspector.msg");
40 |
41 | private static final Set WeakHashNames = new HashSet() {{
42 | add("MD2");
43 | add("MD4");
44 | add("MD5");
45 | }};
46 |
47 | @Override
48 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
49 | return new JavaElementVisitor() {
50 | @Override
51 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
52 | String methodCallName = MethodCallUtils.getMethodName(expression);
53 |
54 | PsiMethod method = expression.resolveMethod();
55 | if (method == null) { return ; }
56 |
57 | PsiClass containingClass = method.getContainingClass();
58 | if (containingClass == null) { return ; }
59 |
60 | String methodQualifiedName = containingClass.getQualifiedName();
61 |
62 | if ("java.security.MessageDigest".equals(methodQualifiedName) && "getInstance".equals(methodCallName)) {
63 | checkZeroArgs(expression);
64 | } else if ("org.apache.commons.codec.digest.DigestUtils".equals(methodQualifiedName)) {
65 | if ("getDigest".equals(methodCallName)) {
66 | checkZeroArgs(expression);
67 | } else if (
68 | "getMd5Digest".equals(methodCallName) ||
69 | "getMd2Digest".equals(methodCallName) ||
70 | "md2".equals(methodCallName) ||
71 | "md2Hex".equals(methodCallName) ||
72 | "md5".equals(methodCallName) ||
73 | "md5Hex".equals(methodCallName)
74 | ) {
75 | registerProblem(expression);
76 | }
77 | }
78 | }
79 |
80 | @Override
81 | public void visitNewExpression(PsiNewExpression expression) {
82 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.codec.digest.DigestUtils")) {
83 | checkZeroArgs(expression);
84 | }
85 | }
86 |
87 | private void checkZeroArgs(PsiCallExpression expression) {
88 | PsiExpressionList argList = expression.getArgumentList();
89 | if (argList == null) { return ; }
90 | PsiExpression[] args = argList.getExpressions();
91 | if (args.length > 0 && args[0] instanceof PsiLiteralExpression) {
92 | String mdName = SecExpressionUtils.getLiteralInnerText(args[0]);
93 | if (null != mdName && WeakHashNames.contains(mdName.toUpperCase())) {
94 | registerProblem(expression);
95 | }
96 | }
97 | }
98 |
99 | private void registerProblem(PsiExpression expression) {
100 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
101 | }
102 | };
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/jdbc/JDBCUnserialize.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.jdbc;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.intellij.psi.PsiNewExpression;
9 | import com.itkim.inspector.BaseLocalInspectionTool;
10 | import com.itkim.inspector.utils.InspectionBundle;
11 | import com.itkim.inspector.utils.SecExpressionUtils;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | /**
15 | * 1043
16 | * javax/sql/DataSource getConnection * -1 false # JDBC反序列化sink # JDBC
17 | *
18 | * java/sql/Driver connect (Ljava/lang/String;Ljava/util/Properties;) 1 false # JDBC # JDBC
19 | * java/sql/DriverManager getConnection (Ljava/lang/String;) 1 false # JDBC # JDBC
20 | * java/sql/DriverManager getConnection (Ljava/lang/String;Ljava/util/Properties;) 1 false # JDBC # JDBC
21 | * java/sql/DriverManager getConnection (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) 1 false # JDBC # JDBC
22 | * org/springframework/boot/jdbc/DataSourceBuilder url (Ljava/lang/String;) 1 false # JDBC # JDBC
23 | * org/jdbi/v3/core/Jdbi create (Ljava/lang/String;) 1 false # JDBC # JDBC
24 | * org/jdbi/v3/core/Jdbi create (Ljava/lang/String;Ljava/util/Properties;) 1 false # JDBC # JDBC
25 | * org/jdbi/v3/core/Jdbi create (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) 1 false # JDBC # JDBC
26 | * org/jdbi/v3/core/Jdbi open (Ljava/lang/String;) 1 false # JDBC # JDBC
27 | * org/jdbi/v3/core/Jdbi open (Ljava/lang/String;Ljava/util/Properties;) 1 false # JDBC # JDBC
28 | * org/jdbi/v3/core/Jdbi open (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) 1 false # JDBC # JDBC
29 | * com/zaxxer/hikari/HikariConfig (Ljava/util/Properties;) 1 false # JDBC # JDBC
30 | * com/zaxxer/hikari/HikariConfig setJdbcUrl (Ljava/lang/String;) 1 false # JDBC # JDBC
31 | * org/springframework/jdbc/datasource/AbstractDriverBasedDataSource setUrl (Ljava/lang/String;) 1 false # JDBC # JDBC
32 | * org/springframework/jdbc/datasource/DriverManagerDataSource (Ljava/lang/String;) 1 false # JDBC # JDBC
33 | * org/springframework/jdbc/datasource/DriverManagerDataSource (Ljava/lang/String;Ljava/util/Properties;) 1 false # JDBC # JDBC
34 | * org/springframework/jdbc/datasource/DriverManagerDataSource (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) 1 false # JDBC # JDBC
35 | */
36 | public class JDBCUnserialize extends BaseLocalInspectionTool {
37 | public static final String MESSAGE = InspectionBundle.message("jdbc.unserialize.type.msg");
38 |
39 | @Override
40 | @NotNull
41 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
42 | return new JavaElementVisitor() {
43 | @Override
44 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
45 | if (SecExpressionUtils.hasFullQualifiedName(expression, "javax.sql.DataSource", "getConnection")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.sql.Driver", "connect")
47 | || SecExpressionUtils.hasFullQualifiedName(expression, "java.sql.DriverManager", "getConnection")
48 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.jdbc.DataSourceBuilder", "url")
49 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.jdbi.v3.core.Jdbi", "create")
50 | || SecExpressionUtils.hasFullQualifiedName(expression, "jorg.jdbi.v3.core.Jdbi", "open")
51 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.zaxxer.hikari.HikariConfig", "setJdbcUrl")
52 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.jdbc.datasource.AbstractDriverBasedDataSource", "setUrl")) {
53 | holder.registerProblem(
54 | expression,
55 | MESSAGE,
56 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
57 | }
58 | }
59 |
60 | @Override
61 | public void visitNewExpression(PsiNewExpression expression) {
62 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.jdbc.datasource.DriverManagerDataSource")
63 | || SecExpressionUtils.hasFullQualifiedName(expression, "com.zaxxer.hikari.HikariConfig")) {
64 | holder.registerProblem(
65 | expression,
66 | MESSAGE,
67 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
68 | }
69 | }
70 | };
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/BaseLocalInspectionTool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector;
17 |
18 | import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
19 | import com.intellij.psi.*;
20 | import com.itkim.inspector.utils.SecExpressionUtils;
21 | import org.apache.commons.codec.digest.MurmurHash3;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.jetbrains.annotations.Nullable;
24 |
25 | public abstract class BaseLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool {
26 |
27 | public enum VulnElemType {
28 | ASSIGNMENT_EXPRESSION,
29 | LOCAL_VARIABLE,
30 | CLASS_FIELD
31 | }
32 |
33 | /**
34 | * 本方法针对可利用安全设置修复的漏洞,例如:
35 | * DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
36 | * dbf.setFeature(...);
37 | * 检查变量 (如dbf) 所在 scope 是否满足 visitor 的要求。
38 | * 若变量定义与使用分离(如dbf定义为类成员,但初始化在某一方法内),则assignElem指初始化元素,resolvedElem为定义元素
39 | *
40 | * (1) 对于变量在方法/静态块/构造块内初始化, scope 为当前方法/静态块/构造块
41 | * (2) 对于变量是类成员变量,并且在定义时赋值,有两种情况
42 | * (2.1) 对于 static 成员变量,检查该类的静态块是否满足 visitor 要求
43 | * (2.2) 对于非 static 成员变量,检查该类的构造块是否满足 visitor 要求
44 | * @param assignElem PsiElement
45 | * @param resolvedElem PsiElement
46 | * @param visitor PsiElementVisitor
47 | * @return boolean
48 | */
49 | protected boolean checkVariableUseFix(@Nullable PsiElement assignElem, @Nullable PsiElement resolvedElem, @NotNull BaseFixElementWalkingVisitor visitor) {
50 | PsiMethod method = SecExpressionUtils.getParentOfMethod(assignElem);
51 | if (method != null) {
52 | method.accept(visitor);
53 | return visitor.isFix();
54 | }
55 |
56 | PsiClassInitializer initializer = SecExpressionUtils.getParentOfClassInitializer(assignElem);
57 | if (initializer != null) {
58 | initializer.accept(visitor);
59 | return visitor.isFix();
60 | }
61 |
62 | if (resolvedElem instanceof PsiField) {
63 | PsiField field = (PsiField)resolvedElem;
64 | if (field.hasModifierProperty(PsiModifier.STATIC)) {
65 | return checkStaticInitializersHasFix((PsiClass)field.getParent(), visitor);
66 | } else {
67 | return checkConstructorHasFix((PsiClass)field.getParent(), visitor);
68 | }
69 | }
70 |
71 | return false;
72 | }
73 |
74 | private boolean checkConstructorHasFix(PsiClass aClass, BaseFixElementWalkingVisitor visitor) {
75 | PsiClassInitializer[] initializers = aClass.getInitializers();
76 | for (PsiClassInitializer initializer : initializers) {
77 | if (!initializer.hasModifierProperty(PsiModifier.STATIC)) {
78 | initializer.accept(visitor);
79 | if (visitor.isFix()) {
80 | return true;
81 | }
82 | }
83 | }
84 |
85 | PsiMethod[] constructors = aClass.getConstructors();
86 | for(PsiMethod constructor : constructors) {
87 | constructor.accept(visitor);
88 | if(visitor.isFix()) {
89 | return true;
90 | }
91 | }
92 | return false;
93 | }
94 |
95 | private boolean checkStaticInitializersHasFix(PsiClass aClass, BaseFixElementWalkingVisitor visitor) {
96 | PsiClassInitializer[] initializers = aClass.getInitializers();
97 | for(PsiClassInitializer initializer : initializers) {
98 | if (initializer.hasModifierProperty(PsiModifier.STATIC)) {
99 | initializer.accept(visitor);
100 | if (visitor.isFix()) {
101 | return true;
102 | }
103 | }
104 | }
105 | return false;
106 | }
107 |
108 | public static int getVulnSign(@NotNull PsiElement element) {
109 | return getVulnSign(
110 | SecExpressionUtils.getElementFQName(element),
111 | element.getText()
112 | );
113 | }
114 |
115 | public static int getVulnSign(@NotNull String fqname, @NotNull String elementText) {
116 | return MurmurHash3.hash32(String.format("%s|%s", fqname, elementText));
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/dos/PatternDOS.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.dos;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.*;
6 | import com.itkim.inspector.BaseLocalInspectionTool;
7 | import com.itkim.inspector.utils.InspectionBundle;
8 | import com.itkim.inspector.utils.SecExpressionUtils;
9 | import com.siyeh.ig.psiutils.MethodCallUtils;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | import java.util.regex.Pattern;
14 |
15 | /**
16 | * 1039
17 | * 正则表达式拒绝服务攻击(RegexDos)
18 | *
19 | * 当编写校验的正则表达式存在缺陷或者不严谨时, 攻击者可以构造特殊的字符串来大量消耗服务器的系统资源,造成服务器的服务中断或停止。
20 | * ref: https://cloud.tencent.com/developer/article/1041326
21 | *
22 | * check:
23 | * java.util.regex.Pattern#compile args:0
24 | * java.util.regex.Pattern#matchers args:0
25 | *
26 | * fix:
27 | * (1) optimize Regular Expressions
28 | * (2) use com.google.re2j
29 | *
30 | * notes:
31 | * `isExponentialRegex` method copy from CodeQL
32 | */
33 | public class PatternDOS extends BaseLocalInspectionTool {
34 | public static final String MESSAGE = InspectionBundle.message("pattern.matches.type.msg");
35 |
36 | public static boolean isExponentialRegex(String s) {
37 | return
38 | // Example: ([a-z]+)+
39 | Pattern.matches(".*\\([^()*+\\]]+\\]?(\\*|\\+)\\)(\\*|\\+).*", s) ||
40 | // Example: (([a-z])?([a-z]+))+
41 | Pattern.matches(".*\\((\\([^()]+\\)\\?)?\\([^()*+\\]]+\\]?(\\*|\\+)\\)\\)(\\*|\\+).*", s) ||
42 | // Example: (([a-z])+)+
43 | Pattern.matches(".*\\(\\([^()*+\\]]+\\]?\\)(\\*|\\+)\\)(\\*|\\+).*", s) ||
44 | // Example: (a|aa)+
45 | Pattern.matches(".*\\(([^()*+\\]]+\\]?)\\|\\1+\\??\\)(\\*|\\+).*", s) ||
46 | // Example: (.*[a-z]){n} n >= 10
47 | Pattern.matches(".*\\(\\.\\*[^()*+\\]]+\\]?\\)\\{[1-9][0-9]+,?[0-9]*\\}.*", s);
48 | }
49 |
50 | // @Override
51 | // @NotNull
52 | // public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
53 | // return new JavaElementVisitor() {
54 | // @Override
55 | // public void visitMethodCallExpression(PsiMethodCallExpression expression) {
56 | // if (SecExpressionUtils.hasFullQualifiedName(expression, "java.util.regex.Pattern", "matches")) {
57 | // holder.registerProblem(
58 | // expression,
59 | // MESSAGE,
60 | // ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
61 | // }
62 | // }
63 | // };
64 | // }
65 |
66 | @NotNull
67 | @Override
68 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
69 | return new JavaElementVisitor() {
70 | @Override
71 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
72 | if (MethodCallUtils.isCallToRegexMethod(expression)) { // `isCallToRegexMethod` judges include java.util.regex.Pattern
73 | String methodName = MethodCallUtils.getMethodName(expression);
74 | if (methodName != null && (methodName.equals("compile") || methodName.equals("matches"))) {
75 | PsiExpression[] expressions = expression.getArgumentList().getExpressions();
76 | if (expressions.length > 0) {
77 | PsiLiteralExpression literal = getLiteralExpression(expressions[0]);
78 | if (literal != null && isExponentialRegex(SecExpressionUtils.getLiteralInnerText(literal))) {
79 | holder.registerProblem(expressions[0], MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
80 | }
81 | }
82 | }
83 | }
84 | }
85 | };
86 | }
87 |
88 | @Nullable
89 | private PsiLiteralExpression getLiteralExpression(PsiExpression expression) {
90 | if (expression instanceof PsiReferenceExpression) {
91 | PsiElement elem = ((PsiReferenceExpression) expression).resolve();
92 | if (elem instanceof PsiVariable) {
93 | PsiExpression initializer = ((PsiVariable) elem).getInitializer();
94 | if (initializer instanceof PsiLiteralExpression) {
95 | return (PsiLiteralExpression) initializer;
96 | }
97 | }
98 | } else if (expression instanceof PsiLiteralExpression) {
99 | return (PsiLiteralExpression) expression;
100 | }
101 | return null;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/sqli/PolyadicExpressionSQLi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.sqli;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.JavaElementVisitor;
21 | import com.intellij.psi.PsiElementVisitor;
22 | import com.intellij.psi.PsiExpression;
23 | import com.intellij.psi.PsiPolyadicExpression;
24 | import com.itkim.inspector.utils.InspectionBundle;
25 | import com.itkim.inspector.utils.SQLiUtil;
26 | import com.itkim.inspector.utils.SecExpressionUtils;
27 | import org.jetbrains.annotations.NotNull;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | import java.util.stream.Collectors;
32 |
33 | /**
34 | * 1048: 多项式拼接型SQL注入漏洞
35 | *
36 | * eg.
37 | * (1) "select *" + " from table" + " where id =" + id;
38 | * (2) "select * from table" + " where id = " + getUserId();
39 | */
40 | public class PolyadicExpressionSQLi extends BaseSQLi {
41 | public static final String MESSAGE = InspectionBundle.message("polyadic.expression.sqli.msg");
42 | // private static final String QUICK_FIX_NAME = InspectionBundle.message("polyadic.expression.sqli.fix");
43 |
44 | // private final ShowHelpCommentQuickFix showHelpCommentQuickFix = new ShowHelpCommentQuickFix(QUICK_FIX_NAME, SQL_INJECTION_HELP_COMMENT);
45 |
46 | @NotNull
47 | @Override
48 | public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
49 | return new JavaElementVisitor() {
50 |
51 | @Override
52 | public void visitPolyadicExpression(PsiPolyadicExpression expression) {
53 | List exps = SecExpressionUtils.deconPolyadicExpression(expression);
54 | if (exps.isEmpty() || ignoreMethodName(expression)) {
55 | return;
56 | }
57 |
58 | String expStr = exps.stream()
59 | .map(item -> SecExpressionUtils.getText(item, true))
60 | .collect(Collectors.joining());
61 | if (isSql(expStr)) {
62 | List sql_segments = new ArrayList<>();
63 | StringBuilder sb = new StringBuilder();
64 |
65 | boolean hasVar = false;
66 | for (PsiExpression exp : exps) {
67 | if (SecExpressionUtils.isSqliCareExpression(exp)) {
68 | String s = SecExpressionUtils.getLiteralInnerText(exp);
69 | if (s == null) {
70 | if (!sb.toString().isEmpty()) {
71 | sql_segments.add(sb.toString());
72 | }
73 |
74 | if (!SecExpressionUtils.isText(exp)) {
75 | hasVar = true;
76 | }
77 |
78 | sb.append(" ? ");
79 | } else {
80 | sb.append(s);
81 | }
82 | } else {
83 | sb.append(" ? ");
84 | }
85 | }
86 | // 末段要 drop 掉,不用查
87 |
88 | if (sql_segments.isEmpty() || Boolean.FALSE.equals(hasVar) || !hasEvalAdditive(sql_segments)) {
89 | // 对于 "select * from " + getTable() + " where id = %s" 的情况
90 | // getTable() 被忽略了,要考虑后面 %s 的问题
91 | if (hasPlaceholderProblem(expStr)) {
92 | holder.registerProblem(expression, PlaceholderStringSQLi.MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
93 | }
94 | return;
95 | }
96 | holder.registerProblem(expression, MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
97 | }
98 | }
99 |
100 | private boolean hasPlaceholderProblem(String content) {
101 | return SQLiUtil.placeholderPattern.matcher(content).find() &&
102 | isSql(content) &&
103 | hasEvalAdditive(content, SQLiUtil.placeholderPattern);
104 | }
105 | };
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/ssrf/SpringSSRF.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.ssrf;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1068
15 | * org/springframework/web/reactive/function/client/WebClient create (Ljava/lang/String;)Lorg/springframework/web/reactive/function/client/WebClient; 1 true # spring-webflux ssrf # SSRF
16 | * org/springframework/web/reactive/function/client/WebClient baseUrl (Ljava/lang/String;)Lorg/springframework/web/reactive/function/client/WebClient$Builder; 1 true # spring-webflux ssrf # SSRF
17 | * org/springframework/web/client/RestTemplate getForEntity (Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/Object;)Lorg/springframework/http/ResponseEntity; 1 false # spring ssrf # SSRF
18 | * org/springframework/web/client/RestTemplate exchange (Ljava/lang/String;Lorg/springframework/http/HttpMethod;Lorg/springframework/http/HttpEntity;Ljava/lang/Class;[Ljava/lang/Object;)Lorg/springframework/http/ResponseEntity; 1 false # spring ssrf # SSRF
19 | * org/springframework/web/client/RestTemplate execute (Ljava/lang/String;Lorg/springframework/http/HttpMethod;Lorg/springframework/web/client/RequestCallback;Lorg/springframework/web/client/ResponseExtractor;[Ljava/lang/Object;)Ljava/lang/Object; 1 false # spring ssrf # SSRF
20 | * org/springframework/web/client/RestTemplate getForObject (Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/Object;)Ljava/lang/Object; 1 false # spring ssrf # SSRF
21 | * org/springframework/web/client/RestTemplate postForEntity (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Object;)Lorg/springframework/http/ResponseEntity; 1 false # spring ssrf # SSRF
22 | * org/springframework/web/client/RestTemplate postForObject (Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/Object;)Ljava/lang/Object; 1 false # spring ssrf # SSRF
23 | * org/springframework/web/client/RestTemplate put (Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V 1 false # spring ssrf # SSRF
24 | * org/springframework/web/client/RestTemplate headForHeaders (Ljava/lang/String;[Ljava/lang/Object;)Lorg/springframework/http/HttpHeaders; 1 false # spring ssrf # SSRF
25 | * org/springframework/web/client/RestTemplate optionsForAllow (Ljava/lang/String;[Ljava/lang/Object;)Ljava/util/Set; 1 false # spring ssrf # SSRF
26 | * org/springframework/web/client/RestTemplate delete (Ljava/lang/String;[Ljava/lang/Object;)V 1 false # spring ssrf # SSRF
27 | */
28 | public class SpringSSRF extends BaseLocalInspectionTool {
29 | public static final String MESSAGE = InspectionBundle.message("spring.ssrf.msg");
30 |
31 | @Override
32 | @NotNull
33 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
34 | return new JavaElementVisitor() {
35 | @Override
36 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
37 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.reactive.function.client.WebClient", "create")
38 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.reactive.function.client.WebClient", "baseUrl")
39 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "getForEntity")
40 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "exchange")
41 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "execute")
42 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "getForObject")
43 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "postForEntity")
44 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "postForObject")
45 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "put")
46 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "headForHeaders")
47 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "optionsForAllow")
48 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.springframework.web.client.RestTemplate", "delete")) {
49 | holder.registerProblem(
50 | expression,
51 | MESSAGE,
52 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
53 | }
54 | }
55 | };
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/PublicControllerOnSpring.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.codeInspection.ProblemHighlightType;
21 | import com.intellij.codeInspection.ProblemsHolder;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.psi.*;
24 | import com.intellij.util.ObjectUtils;
25 | import com.itkim.inspector.BaseLocalInspectionTool;
26 | import com.itkim.inspector.utils.InspectionBundle;
27 | import org.jetbrains.annotations.Nls;
28 | import org.jetbrains.annotations.NotNull;
29 |
30 | import java.util.HashSet;
31 | import java.util.Set;
32 |
33 | /**
34 | * 1072: "@RequestMapping" 方法应当为 "public"
35 | *
36 | * SpringBoot中,以@RequestMapping等注解的方法,尽管使用private描述符也可被api映射。
37 | * 因此,对api使用private是个迷惑的写法,应一直使用public。
38 | *
39 | * 该Inspector会检查如下注解
40 | * \@RequestMapping
41 | * \@GetMapping
42 | * \@PostMapping
43 | * \@PutMapping
44 | * \@DeleteMapping
45 | * \@PatchMapping
46 | *
47 | * ref: https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-3751
48 | */
49 | public class PublicControllerOnSpring extends BaseLocalInspectionTool {
50 | public static final String MESSAGE = InspectionBundle.message("public.controller.on.spring.msg");
51 | private static final String QUICK_FIX_NAME = InspectionBundle.message("public.controller.on.spring.fix");
52 |
53 | private static final Set requestMappingAnnotations = new HashSet() {{
54 | add("org.springframework.web.bind.annotation.RequestMapping");
55 | add("org.springframework.web.bind.annotation.GetMapping");
56 | add("org.springframework.web.bind.annotation.PostMapping");
57 | add("org.springframework.web.bind.annotation.PutMapping");
58 | add("org.springframework.web.bind.annotation.DeleteMapping");
59 | add("org.springframework.web.bind.annotation.PatchMapping");
60 | }};
61 |
62 | private final PublicControllerOnSpringQuickFix publicControllerOnSpringQuickFix = new PublicControllerOnSpringQuickFix();
63 |
64 | @Override
65 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
66 | return new JavaElementVisitor() {
67 | @Override
68 | public void visitAnnotation(PsiAnnotation annotation) {
69 | if (Boolean.FALSE.equals(requestMappingAnnotations.contains(annotation.getQualifiedName()))) {
70 | return ;
71 | }
72 |
73 | PsiModifierList modifierList = ObjectUtils.tryCast(annotation.getParent(), PsiModifierList.class);
74 | if (modifierList == null) {
75 | return ;
76 | }
77 |
78 | if (!modifierList.hasModifierProperty(PsiModifier.PUBLIC)) {
79 | holder.registerProblem(
80 | modifierList,
81 | MESSAGE,
82 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
83 | publicControllerOnSpringQuickFix
84 | );
85 | }
86 | }
87 | };
88 | }
89 |
90 | public static class PublicControllerOnSpringQuickFix implements LocalQuickFix {
91 |
92 | @Override
93 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
94 | return QUICK_FIX_NAME;
95 | }
96 |
97 | @Override
98 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
99 | PsiElement elem = descriptor.getPsiElement();
100 | PsiModifierList modifierList = ObjectUtils.tryCast(elem, PsiModifierList.class);
101 | if (modifierList == null) {
102 | return ;
103 | }
104 |
105 | for (PsiElement child : modifierList.getChildren()) {
106 | if (child instanceof PsiKeyword &&
107 | (child.textMatches(PsiKeyword.PRIVATE) || child.textMatches(PsiKeyword.PROTECTED))
108 | ) {
109 | child.delete();
110 | break;
111 | }
112 | }
113 |
114 | PsiElement lastElement = modifierList.getLastChild();
115 | if (lastElement instanceof PsiKeyword) {
116 | modifierList.addBefore(JavaPsiFacade.getElementFactory(project).createKeyword(PsiKeyword.PUBLIC), lastElement);
117 | } else {
118 | modifierList.add(JavaPsiFacade.getElementFactory(project).createKeyword(PsiKeyword.PUBLIC));
119 | }
120 |
121 | }
122 |
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/dos/NettyResponseSplitting.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.dos;
17 |
18 | import com.intellij.codeInspection.LocalQuickFix;
19 | import com.intellij.codeInspection.ProblemDescriptor;
20 | import com.intellij.codeInspection.ProblemHighlightType;
21 | import com.intellij.codeInspection.ProblemsHolder;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.psi.*;
24 | import com.itkim.inspector.BaseLocalInspectionTool;
25 | import com.itkim.inspector.utils.InspectionBundle;
26 | import com.itkim.inspector.utils.SecExpressionUtils;
27 | import org.jetbrains.annotations.Nls;
28 | import org.jetbrains.annotations.NotNull;
29 |
30 | /**
31 | * 1051: Netty响应拆分攻击
32 | *
33 | * ref:
34 | * (1) https://github.com/github/codeql/blob/main/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.java
35 | * (2) http://www.infosecwriters.com/Papers/DCrab_HTTP_Response.pdf
36 | */
37 | public class NettyResponseSplitting extends BaseLocalInspectionTool {
38 | public static final String MESSAGE = InspectionBundle.message("netty.response.splitting.msg");
39 | private static final String QUICK_FIX_NAME = InspectionBundle.message("netty.response.splitting.fix");
40 |
41 | @Override
42 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
43 | return new JavaElementVisitor() {
44 | @Override
45 | public void visitNewExpression(PsiNewExpression expression) {
46 | if (SecExpressionUtils.hasFullQualifiedName(expression, "io.netty.handler.codec.http.DefaultHttpHeaders")) {
47 | if (expression.getArgumentList() != null) {
48 | PsiExpression[] args = expression.getArgumentList().getExpressions();
49 | if (args.length > 0 && args[0] instanceof PsiLiteralExpression &&
50 | Boolean.FALSE.equals(((PsiLiteralExpression)args[0]).getValue())
51 | ) {
52 | holder.registerProblem(
53 | expression,
54 | MESSAGE,
55 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
56 | new NettyResponseSplittingQuickFix(0)
57 | );
58 | }
59 | }
60 | }
61 | if (SecExpressionUtils.hasFullQualifiedName(expression, "io.netty.handler.codec.http.DefaultHttpResponse")) {
62 | if (expression.getArgumentList() != null) {
63 | PsiExpression[] args = expression.getArgumentList().getExpressions();
64 |
65 | // DefaultHttpResponse 第2位参数会有问题 (0位算起)
66 | if (args.length > 2 && args[2] instanceof PsiLiteralExpression &&
67 | Boolean.FALSE.equals(((PsiLiteralExpression)args[2]).getValue())
68 | ) {
69 | holder.registerProblem(
70 | expression,
71 | MESSAGE,
72 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
73 | new NettyResponseSplittingQuickFix(2)
74 | );
75 | }
76 | }
77 | }
78 | }
79 | };
80 | }
81 |
82 | public static class NettyResponseSplittingQuickFix implements LocalQuickFix {
83 |
84 | private int fixArgIndex;
85 |
86 | public NettyResponseSplittingQuickFix(int fixArgIndex) {
87 | this.fixArgIndex = fixArgIndex;
88 | }
89 |
90 | @Override
91 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
92 | return QUICK_FIX_NAME;
93 | }
94 |
95 | @Override
96 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
97 | PsiNewExpression expression = (PsiNewExpression) descriptor.getPsiElement();
98 | if (expression.getArgumentList() != null) {
99 | PsiExpression[] args = expression.getArgumentList().getExpressions();
100 | if (args.length > fixArgIndex && args[fixArgIndex] instanceof PsiLiteralExpression) {
101 | PsiLiteralExpression problemExpression = (PsiLiteralExpression)args[fixArgIndex];
102 | PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
103 | problemExpression.replace(factory.createExpressionFromText("true", null));
104 | }
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/sqli/PlaceholderStringSQLi.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.sqli;
17 |
18 | import com.intellij.codeInspection.ProblemHighlightType;
19 | import com.intellij.codeInspection.ProblemsHolder;
20 | import com.intellij.psi.*;
21 | import com.itkim.inspector.utils.InspectionBundle;
22 | import com.itkim.inspector.utils.SQLiUtil;
23 | import com.itkim.inspector.utils.SecExpressionUtils;
24 | import com.siyeh.ig.psiutils.ExpressionUtils;
25 | import org.jetbrains.annotations.NotNull;
26 | import org.jetbrains.annotations.Nullable;
27 |
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.List;
31 |
32 |
33 | /**
34 | * 1047: 占位符拼接型SQL注入漏洞
35 | *
36 | * eg.
37 | *
38 | * (1) String.format("select * from table where id = %s", id);
39 | * (2) String.format("select * from table where id = %1$3s", id);
40 | */
41 | public class PlaceholderStringSQLi extends BaseSQLi {
42 | public static final String MESSAGE = InspectionBundle.message("placeholder.string.sqli.msg");
43 | // private static final String QUICK_FIX_NAME = InspectionBundle.message("placeholder.string.sqli.fix");
44 |
45 | // private final ShowHelpCommentQuickFix showHelpCommentQuickFix = new ShowHelpCommentQuickFix(QUICK_FIX_NAME, SQL_INJECTION_HELP_COMMENT);
46 |
47 | @NotNull
48 | @Override
49 | public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
50 | return new JavaElementVisitor() {
51 |
52 | @Override
53 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
54 | if (!SecExpressionUtils.hasFullQualifiedName(expression, "java.lang.String", "format")) {
55 | return;
56 | }
57 | PsiExpression[] args = expression.getArgumentList().getExpressions();
58 | if (!(args.length > 0)) {
59 | return;
60 | }
61 | if (ignoreMethodName(expression)) {
62 | return;
63 | }
64 |
65 | int idx = 0;
66 | PsiType arg0Type = args[idx].getType();
67 | if (arg0Type != null && "Locale".equals(arg0Type.getPresentableText())) {
68 | idx += 1;
69 | }
70 | String content = getLiteralOrVariableLiteral(args[idx]);
71 |
72 | if (content != null &&
73 | SQLiUtil.placeholderPattern.matcher(content).find() &&
74 | isSql(content)
75 | ) {
76 | List split_cont_by_placeholder = new ArrayList<>(Arrays.asList(SQLiUtil.placeholderPattern.split(content)));
77 | if (content.endsWith(split_cont_by_placeholder.get(split_cont_by_placeholder.size() - 1))) {
78 | split_cont_by_placeholder.remove(split_cont_by_placeholder.size() - 1);
79 | }
80 |
81 | List concat_cont = new ArrayList<>();
82 | StringBuilder sb = new StringBuilder();
83 | idx += 1;
84 | for (String seg : split_cont_by_placeholder) {
85 | sb.append(seg);
86 | if (idx < args.length &&
87 | SecExpressionUtils.isSqliCareExpression(args[idx]) &&
88 | getLiteralOrVariableLiteral(args[idx]) == null
89 | ) {
90 | concat_cont.add(sb.toString());
91 | }
92 | sb.append(" ? ");
93 | idx += 1;
94 | }
95 |
96 | if (hasEvalAdditive(concat_cont)) {
97 | holder.registerProblem(
98 | expression,
99 | MESSAGE,
100 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING
101 | );
102 | }
103 | }
104 | }
105 | };
106 | }
107 |
108 | @Nullable
109 | private String getLiteralOrVariableLiteral(@Nullable PsiExpression expression) {
110 | String content = null;
111 | if (ExpressionUtils.isLiteral(expression)) {
112 | content = SecExpressionUtils.getLiteralInnerText(expression);
113 | } else {
114 | PsiLocalVariable localVariable = ExpressionUtils.resolveLocalVariable(expression);
115 | if (localVariable != null) {
116 | PsiExpression localVariableInitializer = localVariable.getInitializer();
117 | if (localVariableInitializer != null && ExpressionUtils.isLiteral(localVariableInitializer)) {
118 | content = SecExpressionUtils.getLiteralInnerText(localVariableInitializer);
119 | }
120 | }
121 | }
122 | return content;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/GroovyRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1019
15 | * groovy/lang/GroovyClassLoader parseClass (Lgroovy/lang/GroovyCodeSource;) 1 false # groovy # RCE
16 | * groovy/lang/GroovyClassLoader parseClass (Lgroovy/lang/GroovyCodeSource;Z) 1 false # groovy # RCE
17 | * groovy/lang/GroovyClassLoader parseClass (Ljava/io/InputStream;Ljava/lang/String;) 1 false # groovy # RCE
18 | * groovy/lang/GroovyClassLoader parseClass (Ljava/io/Reader;Ljava/lang/String;) 1 false # groovy # RCE
19 | * groovy/lang/GroovyClassLoader parseClass (Ljava/lang/String;) 1 false # groovy # RCE
20 | * groovy/lang/GroovyClassLoader parseClass (Ljava/lang/String;Ljava/lang/String;) 1 false # groovy # RCE
21 | * groovy/lang/GroovyShell evaluate (Lgroovy/lang/GroovyCodeSource;) 1 false # groovy # RCE
22 | * groovy/lang/GroovyShell evaluate (Ljava/io/Reader;) 1 false # groovy # RCE
23 | * groovy/lang/GroovyShell evaluate (Ljava/io/Reader;Ljava/lang/String;) 1 false # groovy # RCE
24 | * groovy/lang/GroovyShell evaluate (Ljava/lang/String;) 1 false # groovy # RCE
25 | * groovy/lang/GroovyShell evaluate (Ljava/lang/String;Ljava/lang/String;) 1 false # groovy # RCE
26 | * groovy/lang/GroovyShell evaluate (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;) 1 false # groovy # RCE
27 | * groovy/lang/GroovyShell evaluate (Ljava/net/URI;) 1 false # groovy # RCE
28 | * groovy/lang/GroovyShell parse (Ljava/io/Reader;) 1 false # groovy # RCE
29 | * groovy/lang/GroovyShell parse (Ljava/io/Reader;Ljava/lang/String;) 1 false # groovy # RCE
30 | * groovy/lang/GroovyShell parse (Ljava/lang/String;) 1 false # groovy # RCE
31 | * groovy/lang/GroovyShell parse (Ljava/lang/String;Ljava/lang/String;) 1 false # groovy # RCE
32 | * groovy/lang/GroovyShell parse (Ljava/net/URI;) 1 false # groovy # RCE
33 | * groovy/lang/GroovyShell run (Lgroovy/lang/GroovyCodeSource;Ljava/util/List;) 1 false # groovy # RCE
34 | * groovy/lang/GroovyShell run (Lgroovy/lang/GroovyCodeSource;[Ljava/lang/String;) 1 false # groovy # RCE
35 | * groovy/lang/GroovyShell run (Ljava/io/Reader;Ljava/lang/String;Ljava/util/List;) 1 false # groovy # RCE
36 | * groovy/lang/GroovyShell run (Ljava/io/Reader;Ljava/lang/String;[Ljava/lang/String;) 1 false # groovy # RCE
37 | * groovy/lang/GroovyShell run (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;) 1 false # groovy # RCE
38 | * groovy/lang/GroovyShell run (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;) 1 false # groovy # RCE
39 | * groovy/lang/GroovyShell run (Ljava/net/URI;Ljava/util/List;) 1 false # groovy # RCE
40 | * groovy/lang/GroovyShell run (Ljava/net/URI;[Ljava/lang/String;) 1 false # groovy # RCE
41 | * groovy/util/Eval me (Ljava/lang/String;) 1 false # groovy # RCE
42 | * groovy/util/Eval me (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;) 3 false # groovy # RCE
43 | * groovy/util/Eval x (Ljava/lang/Object;Ljava/lang/String;) 2 false # groovy # RCE
44 | * groovy/util/Eval xy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;) 3 false # groovy # RCE
45 | * groovy/util/Eval xyz (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;) 4 false # groovy # RCE
46 | * org/codehaus/groovy/control/CompilationUnit compile * 0 false # groovy # RCE
47 | * org/codehaus/groovy/tools/javac/JavaAwareCompilationUnit compile * -1 false # groovy # RCE
48 | */
49 | public class GroovyRCE extends BaseLocalInspectionTool {
50 | public static final String MESSAGE = InspectionBundle.message("groovy.rce.type.msg");
51 |
52 | @Override
53 | @NotNull
54 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
55 | return new JavaElementVisitor() {
56 | @Override
57 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
58 | if (SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.GroovyClassLoader", "parseClass")
59 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.GroovyShell", "evaluate")
60 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.GroovyShell", "parse")
61 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.lang.GroovyShel", "run")
62 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.util.Eval", "me")
63 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.util.Eval", "x")
64 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.util.Eval", "xy")
65 | || SecExpressionUtils.hasFullQualifiedName(expression, "groovy.util.Eval", "xyz")
66 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.codehaus.groovy.control.CompilationUnit", "compile")
67 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit", "compile")
68 | ) {
69 | holder.registerProblem(
70 | expression,
71 | MESSAGE,
72 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
73 | }
74 | }
75 | };
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/rce/JEXLRCE.java:
--------------------------------------------------------------------------------
1 | package com.itkim.inspector.rule.rce;
2 |
3 | import com.intellij.codeInspection.ProblemHighlightType;
4 | import com.intellij.codeInspection.ProblemsHolder;
5 | import com.intellij.psi.JavaElementVisitor;
6 | import com.intellij.psi.PsiElementVisitor;
7 | import com.intellij.psi.PsiMethodCallExpression;
8 | import com.itkim.inspector.BaseLocalInspectionTool;
9 | import com.itkim.inspector.utils.InspectionBundle;
10 | import com.itkim.inspector.utils.SecExpressionUtils;
11 | import org.jetbrains.annotations.NotNull;
12 |
13 | /**
14 | * 1021
15 | * org/apache/commons/jexl3/Expression callable * 0 false # jexl # RCE
16 | * org/apache/commons/jexl3/Expression evaluate * 0 false # jexl # RCE
17 | * org/apache/commons/jexl3/JexlEngine getProperty (Lorg/apache/commons/jexl2/JexlContext;Ljava/lang/Object;Ljava/lang/String;) 3 false # jexl # RCE
18 | * org/apache/commons/jexl3/JexlEngine getProperty (Ljava/lang/Object;Ljava/lang/String;) 2 false # jexl # RCE
19 | * org/apache/commons/jexl3/JexlEngine setProperty (Lorg/apache/commons/jexl2/JexlContext;Ljava/lang/Object;Ljava/lang/String;) 3 false # jexl # RCE
20 | * org/apache/commons/jexl3/JexlEngine setProperty (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;) 2 false # jexl # RCE
21 | * org/apache/commons/jexl3/JexlExpression callable * 0 false # jexl # RCE
22 | * org/apache/commons/jexl3/JexlExpression evaluate * 0 false # jexl # RCE
23 | * org/apache/commons/jexl3/JexlScript callable * 0 false # jexl # RCE
24 | * org/apache/commons/jexl3/JexlScript execute * 0 false # jexl # RCE
25 | * org/apache/commons/jexl3/JxltEngine$Expression evaluate * 0 false # jexl # RCE
26 | * org/apache/commons/jexl3/JxltEngine$Expression prepare * 0 false # jexl # RCE
27 | * org/apache/commons/jexl3/JxltEngine$Template evaluate * 0 false # jexl # RCE
28 | * org/apache/commons/jexl3/Script callable * 0 false # jexl # RCE
29 | * org/apache/commons/jexl3/Script execute * 0 false # jexl # RCE
30 | * org/apache/commons/jexl2/Expression callable * 0 false # jexl # RCE
31 | * org/apache/commons/jexl2/Expression evaluate * 0 false # jexl # RCE
32 | * org/apache/commons/jexl2/JexlEngine getProperty (Lorg/apache/commons/jexl2/JexlContext;Ljava/lang/Object;Ljava/lang/String;) 3 false # jexl # RCE
33 | * org/apache/commons/jexl2/JexlEngine getProperty (Ljava/lang/Object;Ljava/lang/String;) 2 false # jexl # RCE
34 | * org/apache/commons/jexl2/JexlEngine setProperty (Lorg/apache/commons/jexl2/JexlContext;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;) 3 false # jexl # RCE
35 | * org/apache/commons/jexl2/JexlEngine setProperty (Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;) 2 false # jexl # RCE
36 | * org/apache/commons/jexl2/JexlExpression callable * 0 false # jexl # RCE
37 | * org/apache/commons/jexl2/JexlExpression evaluate * 0 false # jexl # RCE
38 | * org/apache/commons/jexl2/JexlScript callable * 0 false # jexl # RCE
39 | * org/apache/commons/jexl2/JexlScript execute * 0 false # jexl # RCE
40 | * org/apache/commons/jexl2/Script callable * 0 false # jexl # RCE
41 | * org/apache/commons/jexl2/Script execute * 0 false # jexl # RCE
42 | * org/apache/commons/jexl2/UnifiedJEXL$Expression evaluate * 0 false # jexl # RCE
43 | * org/apache/commons/jexl2/UnifiedJEXL$Expression prepare * 0 false # jexl # RCE
44 | * org/apache/commons/jexl2/UnifiedJEXL$Template evaluate * 0 false # jexl # RCE
45 | */
46 | public class JEXLRCE extends BaseLocalInspectionTool {
47 |
48 | public static final String MESSAGE = InspectionBundle.message("jexl.rce.type.msg");
49 |
50 | @Override
51 | @NotNull
52 | public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
53 | return new JavaElementVisitor() {
54 | @Override
55 | public void visitMethodCallExpression(PsiMethodCallExpression expression) {
56 | if (SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.Expression", "callable")
57 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.Expression", "evaluate")
58 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlEngine", "getProperty")
59 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlEngine", "setProperty")
60 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlExpression", "callable")
61 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlExpression", "evaluate")
62 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlScript", "callable")
63 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JexlScript", "evaluate")
64 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JxltEngine$Expression", "evaluate")
65 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JxltEngine$Expression", "prepare")
66 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.JxltEngine$Template", "evaluate")
67 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.Script", "callable")
68 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl3.Script", "execute")
69 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.Expression", "callable")
70 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.Expression", "evaluate")
71 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlEngine", "getProperty")
72 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlEngine", "setProperty")
73 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlExpression", "callable")
74 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlExpression", "evaluate")
75 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlScript", "callable")
76 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.JexlScript", "execute")
77 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.Script", "callable")
78 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.Script", "execute")
79 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.UnifiedJEXL$Expression", "evaluate")
80 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.UnifiedJEXL$Expression", "prepare")
81 | || SecExpressionUtils.hasFullQualifiedName(expression, "org.apache.commons.jexl2.UnifiedJEXL$Template", "evaluate")
82 | )
83 | holder.registerProblem(
84 | expression,
85 | MESSAGE,
86 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
87 | }
88 | };
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/itkim/inspector/rule/other/ReplacePseudorandomGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 momosecurity.
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 com.itkim.inspector.rule.other;
17 |
18 | import com.intellij.codeInsight.FileModificationService;
19 | import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
20 | import com.intellij.codeInspection.LocalQuickFix;
21 | import com.intellij.codeInspection.ProblemDescriptor;
22 | import com.intellij.codeInspection.ProblemHighlightType;
23 | import com.intellij.codeInspection.ProblemsHolder;
24 | import com.intellij.openapi.application.ApplicationManager;
25 | import com.intellij.openapi.editor.Document;
26 | import com.intellij.openapi.editor.Editor;
27 | import com.intellij.openapi.editor.EditorFactory;
28 | import com.intellij.openapi.project.Project;
29 | import com.intellij.psi.*;
30 | import com.intellij.psi.search.PsiShortNamesCache;
31 | import com.intellij.util.ObjectUtils;
32 | import com.itkim.inspector.BaseLocalInspectionTool;
33 | import com.itkim.inspector.utils.InspectionBundle;
34 | import com.itkim.inspector.utils.SecExpressionUtils;
35 | import org.jetbrains.annotations.Nls;
36 | import org.jetbrains.annotations.NotNull;
37 |
38 | /**
39 | * 1055: 不安全的伪随机数生成器
40 | *
41 | * java.util.Random依赖与一个伪随机数生成器。
42 | * 应使用更安全的java.security.SecureRandom。
43 | *
44 | * ref: https://rules.sonarsource.com/java/type/Security%20Hotspot/RSPEC-2245
45 | */
46 | public class ReplacePseudorandomGenerator extends BaseLocalInspectionTool {
47 | public static final String MESSAGE = InspectionBundle.message("replace.pseudorandom.generator.msg");
48 | public static final String QUICK_FIX_NAME = InspectionBundle.message("replace.pseudorandom.generator.fix");
49 |
50 | private final ReplacePseudorandomGeneratorQuickFix replacePseudorandomGeneratorQuickFix =
51 | new ReplacePseudorandomGeneratorQuickFix();
52 |
53 | @Override
54 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
55 | return new JavaElementVisitor() {
56 | @Override
57 | public void visitNewExpression(PsiNewExpression expression) {
58 | if (SecExpressionUtils.hasFullQualifiedName(expression, "java.util.Random")) {
59 | holder.registerProblem(
60 | expression,
61 | MESSAGE,
62 | ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
63 | replacePseudorandomGeneratorQuickFix
64 | );
65 | }
66 | }
67 | };
68 | }
69 |
70 | public static class ReplacePseudorandomGeneratorQuickFix implements LocalQuickFix {
71 | @Override
72 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getFamilyName() {
73 | return QUICK_FIX_NAME;
74 | }
75 |
76 | @Override
77 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
78 | PsiNewExpression newExp = ObjectUtils.tryCast(descriptor.getPsiElement(), PsiNewExpression.class);
79 | if (newExp == null) {
80 | return ;
81 | }
82 |
83 | PsiElement parent = newExp.getParent();
84 | PsiTypeElement typeElement = null;
85 | if (parent instanceof PsiAssignmentExpression) {
86 | // 变量初始化, parent指向声明点
87 | PsiAssignmentExpression assignmentExpression = ObjectUtils.tryCast(parent, PsiAssignmentExpression.class);
88 | if (assignmentExpression != null) {
89 | PsiReference lRef = assignmentExpression.getLExpression().getReference();
90 | if (lRef != null) {
91 | parent = lRef.resolve();
92 | }
93 | }
94 | }
95 |
96 | if (parent instanceof PsiLocalVariable) {
97 | // 变量声明同时初始化
98 | PsiLocalVariable localVariable = ObjectUtils.tryCast(parent, PsiLocalVariable.class);
99 | if (localVariable != null) {
100 | typeElement = localVariable.getTypeElement();
101 | }
102 | } else if (parent instanceof PsiField) {
103 | // field 变量
104 | PsiField field = ObjectUtils.tryCast(parent, PsiField.class);
105 | if (field != null) {
106 | typeElement = field.getTypeElement();
107 | }
108 | }
109 |
110 | if (typeElement == null) {
111 | return ;
112 | }
113 |
114 | PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
115 | typeElement.replace(factory.createTypeElementFromText("SecureRandom", null));
116 | PsiNewExpression secureNewExp = (PsiNewExpression)factory.createExpressionFromText("new SecureRandom()", null);
117 | newExp.replace(secureNewExp);
118 |
119 | // point NewExpression to element in file
120 | secureNewExp = ObjectUtils.tryCast(((PsiVariable) parent).getInitializer(), PsiNewExpression.class);
121 | if (secureNewExp == null) return ;
122 |
123 | // import java.security.SecureRandom
124 | try {
125 | PsiFile file = descriptor.getPsiElement().getContainingFile();
126 | Document document = PsiDocumentManager.getInstance(project).getDocument(file);
127 | PsiJavaCodeReferenceElement secureRefElem = secureNewExp.getClassOrAnonymousClassReference();
128 |
129 | if (document != null && secureRefElem != null) {
130 | Editor[] editors = EditorFactory.getInstance().getEditors(document, project);
131 | if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
132 | if (secureRefElem.getReferenceName() == null) return;
133 |
134 | ApplicationManager.getApplication().runWriteAction(() -> {
135 | PsiClass[] classes = PsiShortNamesCache.getInstance(project)
136 | .getClassesByName(secureRefElem.getReferenceName(), secureRefElem.getResolveScope());
137 | for (PsiClass clazz : classes) {
138 | if ("java.security.SecureRandom".equals(clazz.getQualifiedName())) {
139 | (new AddImportAction(project, secureRefElem, editors[0], new PsiClass[]{clazz}) {
140 | @Override
141 | protected void bindReference(PsiReference ref, PsiClass targetClass) {
142 | ref.bindToElement(targetClass);
143 | }
144 | }).execute();
145 | }
146 | }
147 | });
148 | }
149 | } catch (Exception ignore) {}
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------