渗透测试问题与修复

博客介绍了网站的几种高危漏洞,包括任意文件读取、跨站点攻击和SQL注入。对任意文件读取漏洞给出验证URL,并提供创建非root用户、限制访问路径等处理方法;还提及跨站点攻击的处理办法和SQL注入的防御措施。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值