问题:
网站Web攻击,主要有:sql注入,css攻击,跨站脚本攻击,挂马,缓冲区溢出等。
1. sql注入:即通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击
2. CSS攻击:通过在URL里插入script标签,然后 诱导信任它们的用户点击它们,确保恶意Javascript代码在受害人的机器上运行。这些攻击利用了用户和服务器之间的信任关系,事实上服务器没有对输入、输出进行检测,从而未拒绝javascript代码。
3. 跨站脚本攻击(也称为XSS):指利用网站漏洞从用户那里恶意盗取信息。用户在浏览网站、使用即时通讯软件、甚至在阅读电子邮件时,通常会点击其中的链接。攻击者通过在链接中插入恶意代码,就能够盗取用户信息。
4. 网页挂马:把一个木马程序上传到一个网站里面然后用木马生成器生一个网马,再上到空间里面,再加代码使得木马在打开网页里运行。
5. 缓冲区溢出:由于TCP/IP的设计是没有考虑安全问题的,这使得在网络上传输的数据是没有任何安全防护的。攻击者可以利用系统漏洞造成系统进程缓冲区溢出
解决方案:
1.定义一个过滤器用于监听http请求并获取参数
@Slf4j
public class CrosXssAndSqlInjectFilter implements Filter {
private FilterConfig filterConfig = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("=======开始进入sql和xss过滤器=======");
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//跨域设置
if (response instanceof HttpServletResponse) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
//通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie
//设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域
//httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
//请求方式
httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
//(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久
httpServletResponse.setHeader("Access-Control-Max-Age", "86400");
//首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段
httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
//sql,xss过滤
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
log.info("CrosXssAndSqlInjectFilter.......orignal url:{},ParameterMap:{}", httpServletRequest.getRequestURI(), JSONObject.toJSONString(httpServletRequest.getParameterMap()));
XssAndSqlHttpServletRequestWrapper xssAndSqlHttpServletRequestWrapper = new XssAndSqlHttpServletRequestWrapper(
httpServletRequest);
/**
* 对不需要过滤的静态资源url,作忽略处理
*/
String[] exclusionsUrls = {".js", ".gif", ".jpg", ".png", ".css", ".ico"};
String path = httpServletRequest.getServletPath();
for (String str : exclusionsUrls) {
if (path.contains(str)) {
chain.doFilter(request, response);
return;
}
}
chain.doFilter(xssAndSqlHttpServletRequestWrapper, response);
log.info("CrosXssAndSqlInjectFilter..........doFilter url:{},ParameterMap:{}", xssAndSqlHttpServletRequestWrapper.getRequestURI(), JSONObject.toJSONString(xssAndSqlHttpServletRequestWrapper.getParameterMap()));
}
}
@Override
public void destroy() {
this.filterConfig = null;
}
}
2.定义sql关键字过滤和跨网站脚本攻击处理的处理器
@Slf4j
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static Set<String> notAllowedKeyWords = new HashSet<>(0);
static {
String key = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
"char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
"table|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
"chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
String[] keyStr = key.split("\\|");
Collections.addAll(notAllowedKeyWords, keyStr);
}
private String currentUrl;
public XssAndSqlHttpServletRequestWrapper(HttpServletRequest servletRequest) {
super(servletRequest);
currentUrl = servletRequest.getRequestURI();
}
/**
* 覆盖getParameter方法,将参数名和参数值都做xss过滤。
* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
*/
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return this.cleanXSS(value);
}
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = this.cleanXSS(values[i]);
}
return encodedValues;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> values = super.getParameterMap();
if (values == null) {
return null;
}
Map<String, String[]> result = new HashMap<>();
for (String key : values.keySet()) {
String encodedKey = this.cleanXSS(key);
int count = values.get(key).length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = this.cleanXSS(values.get(key)[i]);
}
result.put(encodedKey, encodedValues);
}
return result;
}
/**
* 覆盖getHeader方法,将参数名和参数值都做xss过滤。
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取
* getHeaderNames 也可能需要覆盖
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null) {
return null;
}
return this.cleanXSS(value);
}
private String cleanXSS(String values) {
// 采用HtmlUtils实现xss过滤
String value = HtmlUtils.htmlEscape(values);
// 采用StringEscapeUtils实现xss过滤
// String value = StringEscapeUtils.escapeHtml4(values);
// String value = values.replaceAll("<", "<").replaceAll(">", ">");
// value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
// value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
// value = value.replaceAll("'", "& #39;");
// value = value.replaceAll("eval\\((.*)\\)", "");
// value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
// value = value.replaceAll("script", "");
// sql过滤
value = this.cleanSqlKeyWords(value);
return value;
}
private String cleanSqlKeyWords(String value) {
String paramValue = value;
for (String keyword : notAllowedKeyWords) {
if (paramValue.length() > keyword.length() + 4
&& (paramValue.contains(" " + keyword) || paramValue.contains(keyword + " ") || paramValue.contains(" " + keyword + " "))) {
String replacedString = "INVALID";
paramValue = StringUtils.replace(paramValue, keyword, replacedString);
log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword
+ ")" + ";参数:" + value + ";过滤后的参数:" + paramValue);
}
}
return paramValue;
}
}