📄 findsqlinjection.java
字号:
/* * FindBugs - Find bugs in Java programs * Copyright (C) 2004,2005 University of Maryland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package edu.umd.cs.findbugs.detect;import java.util.Iterator;import java.util.regex.Pattern;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.AALOAD;import org.apache.bcel.generic.ConstantPoolGen;import org.apache.bcel.generic.GETFIELD;import org.apache.bcel.generic.GETSTATIC;import org.apache.bcel.generic.INVOKEINTERFACE;import org.apache.bcel.generic.INVOKEVIRTUAL;import org.apache.bcel.generic.Instruction;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InvokeInstruction;import org.apache.bcel.generic.LDC;import org.apache.bcel.generic.MethodGen;import org.apache.bcel.generic.NOP;import org.apache.bcel.generic.Type;import edu.umd.cs.findbugs.BugInstance;import edu.umd.cs.findbugs.BugReporter;import edu.umd.cs.findbugs.Detector;import edu.umd.cs.findbugs.annotations.CheckForNull;import edu.umd.cs.findbugs.ba.BasicBlock;import edu.umd.cs.findbugs.ba.CFG;import edu.umd.cs.findbugs.ba.CFGBuilderException;import edu.umd.cs.findbugs.ba.ClassContext;import edu.umd.cs.findbugs.ba.DataflowAnalysisException;import edu.umd.cs.findbugs.ba.EdgeTypes;import edu.umd.cs.findbugs.ba.Location;import edu.umd.cs.findbugs.ba.constant.Constant;import edu.umd.cs.findbugs.ba.constant.ConstantDataflow;import edu.umd.cs.findbugs.ba.constant.ConstantFrame;import edu.umd.cs.findbugs.ba.type.TopType;import edu.umd.cs.findbugs.ba.type.TypeDataflow;import edu.umd.cs.findbugs.ba.type.TypeFrame;import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;/** * Find potential SQL injection vulnerabilities. * * @author David Hovemeyer * @author Bill Pugh * @author Matt Hargett */public class FindSqlInjection implements Detector { private static class StringAppendState { // remember the smallest position at which we saw something that concerns us int sawOpenQuote = Integer.MAX_VALUE; int sawCloseQuote = Integer.MAX_VALUE; int sawComma = Integer.MAX_VALUE; int sawAppend = Integer.MAX_VALUE; int sawUnsafeAppend = Integer.MAX_VALUE; int sawTaint = Integer.MAX_VALUE; public boolean getSawOpenQuote(InstructionHandle handle) { return sawOpenQuote <= handle.getPosition(); } public boolean getSawCloseQuote(InstructionHandle handle) { return sawCloseQuote <= handle.getPosition(); } public boolean getSawComma(InstructionHandle handle) { return sawComma <= handle.getPosition(); } public boolean getSawAppend(InstructionHandle handle) { return sawAppend <= handle.getPosition(); } public boolean getSawUnsafeAppend(InstructionHandle handle) { return sawUnsafeAppend <= handle.getPosition(); } public boolean getSawTaint(InstructionHandle handle) { return sawTaint <= handle.getPosition(); } public void setSawOpenQuote(InstructionHandle handle) { sawOpenQuote = Math.min(sawOpenQuote, handle.getPosition()); } public void setSawCloseQuote(InstructionHandle handle) { sawCloseQuote = Math.min(sawCloseQuote, handle.getPosition()); } public void setSawComma(InstructionHandle handle) { sawComma = Math.min(sawComma, handle.getPosition()); } public void setSawAppend(InstructionHandle handle) { sawAppend = Math.min(sawAppend, handle.getPosition()); } public void setSawUnsafeAppend(InstructionHandle handle) { sawUnsafeAppend = Math.min(sawUnsafeAppend, handle.getPosition()); } public void setSawTaint(InstructionHandle handle) { sawTaint = Math.min(sawTaint, handle.getPosition()); } public void setSawInitialTaint() { sawTaint = 0; } } BugReporter bugReporter; public FindSqlInjection(BugReporter bugReporter) { this.bugReporter = bugReporter; } public void visitClassContext(ClassContext classContext) { JavaClass javaClass = classContext.getJavaClass(); Method[] methodList = javaClass.getMethods(); for (Method method : methodList) { MethodGen methodGen = classContext.getMethodGen(method); if (methodGen == null) continue; try { analyzeMethod(classContext, method); } catch (DataflowAnalysisException e) { bugReporter.logError("FindSqlInjection caught exception while analyzing " + methodGen, e); } catch (CFGBuilderException e) { bugReporter.logError("FindSqlInjection caught exception while analyzing " + methodGen, e); } catch (RuntimeException e) { System.out.println("Exception while checking for SQL injection in " + methodGen + " in " + javaClass.getSourceFileName()); e.printStackTrace(System.out); } } } private boolean isStringAppend(Instruction ins, ConstantPoolGen cpg) { if (ins instanceof INVOKEVIRTUAL) { INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) ins; if (invoke.getMethodName(cpg).equals("append") && invoke.getClassName(cpg).startsWith("java.lang.StringB")) { String sig = invoke.getSignature(cpg); char firstChar = sig.charAt(1); return firstChar == '[' || firstChar == 'L'; } } return false; } private boolean isConstantStringLoad(Location location, ConstantPoolGen cpg) throws CFGBuilderException { Instruction ins = location.getHandle().getInstruction(); if (ins instanceof LDC) { LDC load = (LDC) ins; Object value = load.getValue(cpg); if (value instanceof String) { return true; } } return false; } static final Pattern openQuotePattern = Pattern.compile("((^')|[^\\p{Alnum}]')$"); public static boolean isOpenQuote(String s) { return openQuotePattern.matcher(s).find(); } static final Pattern closeQuotePattern = Pattern.compile("^'($|[^\\p{Alnum}])"); public static boolean isCloseQuote(String s) { return closeQuotePattern.matcher(s).find(); } private StringAppendState updateStringAppendState(Location location, ConstantPoolGen cpg, StringAppendState stringAppendState) throws CFGBuilderException { InstructionHandle handle = location.getHandle(); Instruction ins = handle.getInstruction(); if (!isConstantStringLoad(location, cpg)) { throw new IllegalArgumentException("instruction must be LDC"); } LDC load = (LDC) ins; Object value = load.getValue(cpg); String stringValue = ((String) value).trim(); if (stringValue.startsWith(",") || stringValue.endsWith(",")) stringAppendState.setSawComma(handle); if (isOpenQuote(stringValue)) stringAppendState.setSawOpenQuote(handle); if (isCloseQuote(stringValue)) stringAppendState.setSawCloseQuote(handle); return stringAppendState; } private boolean isPreparedStatementDatabaseSink(Instruction ins, ConstantPoolGen cpg) { if (!(ins instanceof INVOKEINTERFACE)) { return false; } INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins; String methodName = invoke.getMethodName(cpg); String interfaceName = invoke.getClassName(cpg); if (methodName.equals("prepareStatement") && interfaceName.equals("java.sql.Connection")) { return true; } return false; } private boolean isExecuteDatabaseSink(Instruction ins, ConstantPoolGen cpg) { if (!(ins instanceof INVOKEINTERFACE)) { return false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -