什麼是sql注入?
所謂SQL注入,就是通過把SQL指令插入到Web表單送出或輸入域名或頁面請求的查詢字元串,最終達到欺騙伺服器執行惡意的SQL指令。具體來說,它是利用現有應用程式,将(惡意的)SQL指令注入到背景資料庫引擎執行的能力,它可以通過在Web表單中輸入(惡意)SQL語句得到一個存在安全漏洞的網站上的資料庫,而不是按照設計者意圖去執行SQL語句。 [1] 比如先前的很多影視網站洩露VIP會員密碼大多就是通過WEB表單遞交查詢字元暴出的,這類表單特别容易受到SQL注入式攻擊
sql注入導緻原因?
SQL注入的産生原因通常表現在以下幾方面:
①不當的類型處理;
②不安全的資料庫配置;
③不合理的查詢集處理;
④不當的錯誤處理;
⑤轉義字元處理不合适;
⑥多個送出處理不當。
簡單例子
@Aspect
@Component
public class LogAspect {
/**
* 切面類
*/
private Logger logger = LoggerFactory.getLogger(getClass());
// 存在SQL注入風險
private static final String IS_SQL_INJECTION = "輸入參數存在SQL注入風險";
private static final String UNVALIDATED_INPUT = "輸入參數含有非法字元";
private static final String ERORR_INPUT = "輸入的參數非法";
//切入點
@Pointcut("execution(public * com.kevin.library.controller.*.*(..))")
public void webLog() {
}
//前置通知
@Before("webLog()")
public void before(JoinPoint joinPoint)throws Throwable {
// 接收到請求,記錄請求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 記錄下請求内容
logger.info("URL : " + request.getRequestURL().toString());
logger.info("HTTP_METHOD : " + request.getMethod());
logger.info("IP : " + request.getRemoteAddr());
logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
//後置通知
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void afterReturning(Object ret) throws Throwable {
// 處理完請求,傳回内容
logger.info("方法的傳回值 : " + ret);
}
//後置異常通知
@AfterThrowing("webLog()")
public void returnThrowing(JoinPoint joinPoint) {
logger.info("方法異常時執行");
}
//最終通知
@After("webLog()")
public void after(JoinPoint joinPoint) {
logger.info("方法最終執行");
}
//環繞通知
@Around("webLog()")
public Object arround(ProceedingJoinPoint pjp) {
logger.info("方法環繞start.....");
try {
Object[] args =pjp.getArgs();// 參數
//String str = String.valueOf(args);
String st = Arrays.toString(args );
if (!IllegalStrFilterUtil.sqlStrFilter(str)) {
logger.info(IS_SQL_INJECTION);
new RuntimeException(ERORR_INPUT);
}
if (!IllegalStrFilterUtil.isIllegalStr(str)) {
logger.info(UNVALIDATED_INPUT);
new RuntimeException(ERORR_INPUT);
}
Object o = pjp.proceed();
logger.info("方法環繞proceed,結果是 :" + o);
return o;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}
public class IllegalStrFilterUtil {
private static Logger logger = LoggerFactory.getLogger(IllegalStrFilterUtil.class);
private static final String REGX = "!|!|@|◎|#|#|(\\$)|¥|%|%|(\\^)|……|(\\&)|※|(\\*)|×|(\\()|(|(\\))|)|_|——|(\\+)|+|(\\|)|§ ";
/**
* 對常見的sql注入攻擊進行攔截
*
* @param input
* @return
* true 表示參數不存在SQL注入風險
* false 表示參數存在SQL注入風險
*/
public static Boolean sqlStrFilter(String input) {
if (input == null || input.trim().length() == 0) {
return false;
}
input = input.toUpperCase();
if (input.indexOf("DELETE") >= 0 || input.indexOf("ASCII") >= 0 || input.indexOf("UPDATE") >= 0 || input.indexOf("SELECT") >= 0
|| input.indexOf("'") >= 0 || input.indexOf("SUBSTR(") >= 0 || input.indexOf("COUNT(") >= 0 || input.indexOf(" OR ") >= 0
|| input.indexOf(" AND ") >= 0 || input.indexOf("DROP") >= 0 || input.indexOf("EXECUTE") >= 0 || input.indexOf("EXEC") >= 0
|| input.indexOf("TRUNCATE") >= 0 || input.indexOf("INTO") >= 0 || input.indexOf("DECLARE") >= 0 || input.indexOf("MASTER") >= 0) {
logger.error("該參數怎麼SQL注入風險:sInput=" + input);
return false;
}
logger.info("通過sql檢測");
return true;
}
/**
* 對非法字元進行檢測
*
* @param input
* @return
* true 表示參數不包含非法字元
* false 表示參數包含非法字元
*/
public static Boolean isIllegalStr(String input) {
if (input == null || input.trim().length() == 0) {
return false;
}
input = input.trim();
Pattern compile = Pattern.compile(REGX, Pattern.CASE_INSENSITIVE);
Matcher matcher = compile.matcher(input);
logger.info("通過字元串檢測");
return matcher.find();
}
}