互联网API开放平台安全设计(一)--Web安全漏洞

什么是XSS攻击手段

XSS攻击使用Javascript脚本注入进行攻击

例如在提交表单后,展示到另一个页面,可能会受到XSS脚本注入,读取本地cookie远程发送给黑客服务器端。

<script>alert('sss')</script>

<script>window.location.href='http://www.itmayiedu.com';</script>

对应html源代码: &lt;script&gt;alert('sss')&lt;/script&gt;

 如何防御XSS攻击

将脚本特殊字符,转换成html源代码进行展示。

  1.  
    // 重写HttpServletRequestWrapper 防止XSS攻击
  2.  
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  3.  
    private HttpServletRequest request;
  4.  
     
  5.  
    /**
  6.  
    * @param request
  7.  
    */
  8.  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
  9.  
    super(request);
  10.  
    this.request = request;
  11.  
    }
  12.  
     
  13.  
    @Override
  14.  
    public String getParameter(String name) {
  15.  
    // 过滤getParameter参数 检查是否有特殊字符
  16.  
    String value = super.getParameter(name);
  17.  
    System.out.println("value:" + value);
  18.  
    if (!StringUtils.isEmpty(value)) {
  19.  
    // 将中文转换为字符编码格式,将特殊字符变为html源代码保存
  20.  
    value = StringEscapeUtils.escapeHtml(value);
  21.  
    System.out.println("newValue:" + value);
  22.  
    }
  23.  
    return value;
  24.  
    }
  25.  
     
  26.  
    }

SQL注入攻击

什么是SQL注入

SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库执行一些恶意的操作。造成SQL注入的原因是因为程序没有有效过滤用户的输入,使攻击者成功的向服务器提交恶意的SQL查询代码,程序在接收后错误的将攻击者的输入作为查询语句的一部分执行,导致原始的查询逻辑被改变,额外的执行了攻击者精心构造的恶意代码

SQL注入防攻击手段

不要使用拼接SQL语句方式、最好使用预编译方式,在mybatis编写sql语句的时候,最好使用?传参数方式,不要使用#传参数,因为#传参数方式,可能会受到sql语句攻击。

Http请求防盗链

什么是防盗链

比如A网站有一张图片,被B网站直接通过img标签属性引入,直接盗用A网站图片展示。

如何实现防盗链

  判断http请求头Referer域中的记录来源的值,如果和当前访问的域名不一致的情况下,说明该图片可能被其他服务器盗用。

  1.  
    public class ImgFilter implements Filter {
  2.  
     
  3.  
    @Value("${domain.name}")
  4.  
    private String domainName;
  5.  
     
  6.  
    public void init(FilterConfig filterConfig) throws ServletException {
  7.  
     
  8.  
    }
  9.  
     
  10.  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  11.  
    throws IOException, ServletException {
  12.  
    HttpServletRequest req = (HttpServletRequest) request;
  13.  
    String referer = req.getHeader("Referer");
  14.  
    if (StringUtils.isEmpty(referer)) {
  15.  
    request.getRequestDispatcher("/imgs/error.png").forward(request, response);
  16.  
    return;
  17.  
    }
  18.  
    String domain = getDomain(referer);
  19.  
    if (!domain.equals(domainName)) {
  20.  
    request.getRequestDispatcher("/imgs/error.png").forward(request, response);
  21.  
    return;
  22.  
    }
  23.  
    chain.doFilter(request, response);
  24.  
    }
  25.  
     
  26.  
    /**
  27.  
    * 获取url对应的域名
  28.  
    *
  29.  
    * @param url
  30.  
    * @return
  31.  
    */
  32.  
    public String getDomain(String url) {
  33.  
    String result = "";
  34.  
    int j = 0, startIndex = 0, endIndex = 0;
  35.  
    for (int i = 0; i < url.length(); i++) {
  36.  
    if (url.charAt(i) == '/') {
  37.  
    j++;
  38.  
    if (j == 2)
  39.  
    startIndex = i;
  40.  
    else if (j == 3)
  41.  
    endIndex = i;
  42.  
    }
  43.  
     
  44.  
    }
  45.  
    result = url.substring(startIndex + 1, endIndex);
  46.  
    return result;
  47.  
    }
  48.  
     
  49.  
    public void destroy() {
  50.  
     
  51.  
    }
  52.  
    }

防御CSRF攻击手段

使用图形验证码防止机器模拟接口请求攻击,在调用核心业务接口时,比如支付、下单、等接口,最好使用手机短信验证验证或者是人脸识别,防止其他用户使用Token伪造请求。

忘记密码漏洞

黑客使用抓包工具分析Http请求,在忘记密码找回时,需要发送一套短信验证码,如果验证码数字比较短的话,很容易使用暴力破解方式攻击破。

防御手段:

忘记密码验证码最好在6-8位。

一旦频繁调用接口验证时,应该使用图形验证码拦截,防止机器模拟。

使用黑名单和白名单机制,防御攻击。

上传文件漏洞

漏洞描述

上传漏洞这个顾名思义,就是攻击者通过上传木马文件,直接得到WEBSHELL,危害等级超级高,现在的入侵中上传漏洞也是常见的漏洞。

 导致该漏洞的原因在于代码作者没有对访客提交的数据进行检验或者过滤不严,可以直接提交修改过的数据绕过扩展名的检验。

漏洞危害

1)可以得到WEBSHELL

2)上传木马文件,可以导致系统瘫痪

修复方案

1)对文件格式限制,只允许某些格式上传

2)对文件格式进行校验,前端跟服务器都要进行校验(前端校验扩展名,服务器校验扩展名、Content_Type等)

3)将上传目录防止到项目工程目录之外,当做静态资源文件路径,并且对文件的权限进行设定,禁止文件下的执行权限。

判断文件流是否为图片格式

  1.  
    /**
  2.  
    * 文件上传
  3.  
    */
  4.  
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
  5.  
    String root = request.getServletContext().getRealPath("/upload");
  6.  
    DiskFileItemFactory factory = new DiskFileItemFactory();
  7.  
    ServletFileUpload upload = new ServletFileUpload(factory);
  8.  
    try {
  9.  
    List<FileItem> list = upload.parseRequest(request);
  10.  
    for (FileItem it : list) {
  11.  
    // 如果是file文件类型
  12.  
    if (!it.isFormField()) {
  13.  
    FileType fileType = getFileType(it.getInputStream());
  14.  
    if (fileType == null) {
  15.  
    // 非图片格式
  16.  
    response.getWriter().write("fail");
  17.  
    return;
  18.  
    }
  19.  
    String imgValue = fileType.getValue();
  20.  
    System.out.println("imgValue:" + imgValue);
  21.  
    // 是图片格式
  22.  
    it.write(new File(root + "/" + it.getName()));
  23.  
    response.getWriter().write("success");
  24.  
     
  25.  
    }
  26.  
    }
  27.  
    } catch (Exception e) {
  28.  
    try {
  29.  
    response.getWriter().write("exception");
  30.  
    } catch (IOException e1) {
  31.  
    e1.printStackTrace();
  32.  
    }
  33.  
    e.printStackTrace();
  34.  
    }
  35.  
    }
  36.  
     
  37.  
    // 判断文件是图片格式
  38.  
    public static FileType getFileType(InputStream is) throws IOException {
  39.  
    byte[] src = new byte[28];
  40.  
    is.read(src, 0, 28);
  41.  
    StringBuilder stringBuilder = new StringBuilder("");
  42.  
    if (src == null || src.length <= 0) {
  43.  
    return null;
  44.  
    }
  45.  
    for (int i = 0; i < src.length; i++) {
  46.  
    int v = src[i] & 0xFF;
  47.  
    String hv = Integer.toHexString(v).toUpperCase();
  48.  
    if (hv.length() < 2) {
  49.  
    stringBuilder.append(0);
  50.  
    }
  51.  
    stringBuilder.append(hv);
  52.  
    }
  53.  
    FileType[] fileTypes = FileType.values();
  54.  
    for (FileType fileType : fileTypes) {
  55.  
    if (stringBuilder.toString().startsWith(fileType.getValue())) {
  56.  
    return fileType;
  57.  
    }
  58.  
    }
  59.  
    return null;
  60.  
    }

APIGateway网关

什么是网关

随着互联网的快速发展,当前以步入移动互联、物联网时代。用户访问系统入口也变得多种方式,由原来单一的PC客户端,变化到PC客户端、各种浏览器、手机移动端及智能终端等。同时系统之间大部分都不是单独运行,经常会涉及与其他系统对接、共享数据的需求。所以系统需要升级框架满足日新月异需求变化,支持业务发展,并将框架升级为微服务架构。“API网关”核心组件是架构用于满足此些需求。

很多互联网平台已基于网关的设计思路,构建自身平台的API网关,国内主要有京东、携程、唯品会等,国外主要有Netflix、Amazon等。

网关框架框架

业界为了满足这些需求,已有相关的网关框架。

1、基于nginx平台实现的网关有:KONG、API Umbrella

2、自研发的网关有:apigee、Zuul

API网关设计

API网关是微服务架构(Microservices Architecture)标准化服务的模式。API网关定位为应用系统服务接口的网关,区别于网络技术的网关,但是原理则是一样。API网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。组件设计如下:

网关的应用场景

  1. 黑白名单:实现通过IP地址控制禁止访问网关功能,此功能是应用层面控制实现,再往前也可以通过网络传输方面进行控制访问。
  2. 日志:实现访问日志的记录,可用于分析访问、处理性能指标,同时将分析结果支持其他模块功能应用。
  3. 协议适配:实现通信协议校验、适配转换的功能。
  4.  身份认证:负责网关访问身份认证验证,此模块与“访问认证中心”通信,实际认证业务逻辑交移“访问认证中心”处理。
  5. 计流限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则。
  6. 路由:路由是API网关很核心的模块功能,此模块实现根据请求,锁定目标微服务并将请求进行转发。此模块需要与“服务发布管理中心”通信。“服务发布管理中心”实现微服务发布注册管理功能,与其通信获得目标微服务信息。

API网关部署

API网关是一个公共基础组件,无状态,可支持多套分布式部署。

posted @ 2023-06-08 09:32  小强找BUG  阅读(23)  评论(0)    收藏  举报