1.任意文件读取(高危)
详细描述
很多网站由于业务需求,往往需要提供文件(附件)下载的功能块,但是如果对下载的文件没有做限制,直接通过绝对路径对其文件进行下载,那么,恶意用户就可以利用这种方式下载服务器的敏感文件,对服务器进行进一步的威胁和攻击。
漏洞验证
验证URL:
http://127.0.0.1:8090/webapp/asset///…//…//…//…//…//…//…//…//…//…//…/etc/passwd
处理方法
1.创建非root用户,应用系统文件归属于该用户,用非root用户启动应用系统。
2.不允许访问路径包含 …/。
if (request.getRequestURI().contains("../")) {
response.sendError(404);
}
2.跨站点攻击
详细描述
CSRF。用户以当前身份浏览到flash或者恶意网站时,JS/flash可以迫使用户浏览器向任意CGI发起请求,此请求包含 用户身份标识,CGI如无限制则会以用户身份进行操作。如:以用户身份发起的转账请求等。CSRF攻击可以从站外和 站内发起。从站内发起CSRF攻击,需要利用网站本身的业务,比如“自定义头像”功能,恶意用户指定自己的头像URL 是一个修改用户信息的链接,当其他已登录用户浏览恶意用户头像时,会自动向这个链接发送修改信息请求。从站外 发送请求,则需要恶意用户在自己的服务器上,放一个自动提交修改个人信息的htm页面,并把页面地址发给受害者 用户,受害者用户打开时,会发起一个请求。如果恶意用户能够知道网站管理后台某项功能的URL,就可以直接攻击 管理员,强迫管理员执行恶意用户定义的操作。
处理办法
方法一
public static boolean checkReferer(HttpServletRequest req) {
String referer = req.getHeader("Referer"); // 取得引用来源
String serverName = req.getServerName(); // 取得服务器信息
String a = req.getPathInfo();
if ((null == referer || (referer.indexOf(serverName) < 0))
&&req.getPathInfo().indexOf("index.html")<0
&&req.getPathInfo().indexOf("exception.htm")<0
&&req.getPathInfo().indexOf("ssoIndex.htm")<0
&&req.getPathInfo().indexOf("uamsIndex.htm")<0
&&req.getPathInfo().indexOf("indexportal.html")<0
&&!req.getPathInfo().equals("/")
&&!req.getPathInfo().equals("")
&&req.getPathInfo().indexOf("login")<0)
{
return false;
}
return true;
}
方法二 filter
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
//继承自WebMvcConfigurationSupport会导致jsonformat配置失效,swagger访问不到,此处改为implements WebMvcConfigurer
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private RefererInterceptor refererInterceptor;
/**
* 添加过滤器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(refererInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/", "/captcha.jpg","/swagger-ui.html");
}
@Bean
public RefererInterceptor getInterceptor() {
return new RefererInterceptor();
}
}
import com.common.util.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Component
public class RefererInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger = LoggerFactory.getLogger(RefererInterceptor.class);
/**
* 白名单
*/
@Resource
private AppProperties appProperties;
/**
* 是否开启referer校验
*/
private Boolean check = true;
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
if (!check) {
return true;
}
String referer = req.getHeader("referer");
logger.info("referer: "+referer);
String host = req.getServerName();
logger.info("host: "+host);
// get post请求
if ("GET".equals(req.getMethod())||"POST".equals(req.getMethod())) {
if (host.equals("localhost")){
return true;
}
//当没有传refer头时,判断是不是白名单ip服务器的跨组件调用
if (referer == null) {
String ip = IpUtils.getIpAddr(req);
logger.info("ip:"+ip);
for (String s : appProperties.getRefererDomain()) {
logger.info("s:"+s);
Pattern p=Pattern.compile(s);
Matcher matcher=p.matcher(ip);
if (matcher.find()) {
logger.info("---host通过校验----host: "+host);
return true;
}
Matcher matcher2=p.matcher(host);
if (matcher2.find()) {
logger.info("---host通过校验----host: "+host);
return true;
}
}
// 状态置为404
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
logger.info("refer为空且不在白名单内");
return false;
}
java.net.URL url = null;
try {
url = new java.net.URL(referer);
} catch (MalformedURLException e) {
// URL解析异常,也置为404
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
logger.info("URL解析异常");
return false;
}
// 首先判断请求域名和referer域名是否相同
if (!host.equals(url.getHost())) {
// 如果不等,判断是否在白名单中
if (appProperties.getRefererDomain() != null) {
for (String s : appProperties.getRefererDomain()) {
Pattern p=Pattern.compile(s);
Matcher matcher=p.matcher(url.getHost());
if (matcher.find()) {
logger.info("---refer通过校验----host: " + s);
return true;
}
}
}
logger.info("---未通过校验host与refer不匹配,且不在白名单----");
return false;
}
logger.info("---域名与refer相同--通过校验----");
}
return true;
}
}
SQL注入
漏洞描述
数据库中存储的用户隐私信息泄漏;通过操作数据库对某些网页进行篡改等
防御措施:
数据和代码分开处理;过滤数据库操作特殊字符,数据库操作使用预编译语句
private static String reg = "(\\b(.*(?i)truncate.*table|.*(?i)insert.*into|.*(?i)delete.*from|.*(?i)drop.*table|.*(?i)select.*from)|.*(?i)script.*|.*(?i)alert.*\\b)";
private static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
if (!isErrorParams(request))
{
response.sendError(404);
return;
}
//判断请求参数中是否含有脚本和特殊字符
private boolean isErrorParams(HttpServletRequest request){
Enumeration<?> enumeration = request.getParameterNames(); // 在请求中取得参数
while (enumeration.hasMoreElements())
{
Object keyObj = enumeration.nextElement(); // 取得key
if (keyObj!=null)
{
String value = request.getParameter(keyObj.toString());
try {
String newParam = URLDecoder.decode(value, "UTF-8");
if (!newParam.equals(value)) {
value = newParam;
}
} catch (UnsupportedEncodingException e) {
}
if((isSpecialStr(value) || value.contains("../") || value.contains("..\\") )){
return false;
}
}
}
return true;
}
private boolean isSpecialStr(String str)
{
boolean retFlag = false;
Matcher m = sqlPattern.matcher(str);
if (m.find())
{
retFlag = true;
}
return retFlag;
}