常见Web安全漏洞及防御

常见Web安全漏洞

XSS攻击

什么XSS攻击手段

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

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

XSS攻击方法只是利用HTML的属性,作各种的尝试,找出注入的方法。现在对三种主要方式进行分析。
第一种:对普通的用户输入,页面原样内容输出。

打开http://go.ent.163.com/goproducttest/test.jsp(限公司IP),输 入:<script>alert(‘xss’)</script>, JS脚本顺利执行。当攻击者找到这种方法后,就可以传播这种链接格式的链接 (http://go.ent.163.com/goproducttest/test.jsp?key=JSCODE)如:http: //go.ent.163.com/goproducttest/test.jsp?key=<script>alert(‘xss’)& lt;/script>,并对JSCODE做适当伪装,如:

http://go.ent.163.com/goproducttest/test.jsp?key=%3c%73%63%72%69%70 %74%3e%61%6c%65%72%74%28%27%78%73%73%27%29%3c%2f%73%63%72%69%70%74%3e,当其 它用户当点此链接的时候,JS就运行了,造成的后果会很严重,如跳去一个有木马的页面、取得登陆用户的COOKIE等。

第二种:在代码区里有用户输入的内容

原则就是,代码区中,绝对不应含有用户输入的东西。

第三种:允许用户输入HTML标签的页面。

用户可以提交一些自定义的HTML代码,这种情况是最危险的。因为,IE浏览器默认采用的是UNICODE编码,HTML编码可以用&#ASCII方式来写,又可以使用”/”连接16进制字符串来写,使得过滤变得异常复杂,如下面的四个例子,都可以在IE中运行。

1,直接使用JS脚本。

<img src=”javascript:alert(‘xss’)” />

2,对JS脚本进行转码。

<img src=”javascript:alert(‘xss’)” />

3,利用标签的触发条件插入代码并进行转码。

<img  οnerrοr=”alert(‘xss’)” />

4,使用16进制来写(可以在傲游中运行)

<img STYLE=”background-image: /75/72/6c/28/6a/61/76/61/73/63/72/69/70/74/3a/61/6c/65/72/74/28/27/58/53/53/27/29/29″>

以上写法等于<img STYLE=”background-image: url(javascript:alert(‘XSS’))”>

 

如何防御XSS攻击

请记住两条原则:过滤输入和转义输出

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

汉子编码http://www.mytju.com/classcode/tools/encode_gb2312.asp

步骤:编写过滤器拦截所有getParameter参数,重写httpservletwrapp方法

将参数特殊字符转换成html源代码保存.

// 重写HttpServletRequestWrapper 防止XSS攻击

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

private HttpServletRequest request;

 

/**

 * @param request

 */

public XssHttpServletRequestWrapper(HttpServletRequest request) {

super(request);

this.request = request;

}

 

@Override

public String getParameter(String name) {

// 过滤getParameter参数 检查是否有特殊字符

String value = super.getParameter(name);

System.out.println("value:" + value);

if (!StringUtils.isEmpty(value)) {

// 将中文转换为字符编码格式,将特殊字符变为html源代码保存

value = StringEscapeUtils.escapeHtml(value);

System.out.println("newValue:" + value);

}

return value;

}

 

}

SpringBoot启动加上@ServletComponentScan

@SpringBootApplication

@ServletComponentScan

public class App {

 

public static void main(String[] args) {

SpringApplication.run(App.class, args);

}

 

}

 

SQL注入攻击

什么SQL注入

SQL注入:利用现有应用程序,将(恶意)的SQL命令注入到后台数据库执行一些恶意的操作。

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

SQL注入防攻击手段

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

 

 

演示案例:

http://127.0.0.1:8080/login?userName='liusi'&password='123'

http://127.0.0.1:8080/login?userName='liusi'&password='123'  or 1=1

 

@RestController

public class LoginController {

@Autowired

private UserMapper userMapper;

 

@RequestMapping("/login")

public String login(UserEntity userEntity) {

System.out.println("账号密码信息:userEntity:" + userEntity.toString());

UserEntity login = userMapper.login(userEntity);

return login == null ? "登陆失败!" : "登陆成功!";

}

 

}

 

public interface UserMapper {

 

@Select(" SELECT  * FROM user_info where userName=${userName} and password=${password}")

public UserEntity login(UserEntity userEntity);

 

}

 

 

 

 

 

 

MyBatis #与?区别

#{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符,可以防止SQL注入问题。

${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。

Http请求防盗链

什么是防盗链

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

 

如何实现防

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

使用过滤器判断请求头Referer记录请求来源

@WebFilter(filterName = "imgFilter", urlPatterns = "/imgs/*")

public class ImgFilter implements Filter {

 

@Value("${domain.name}")

private String domainName;

 

public void init(FilterConfig filterConfig) throws ServletException {

 

}

 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

String referer = req.getHeader("Referer");

if (StringUtils.isEmpty(referer)) {

request.getRequestDispatcher("/imgs/error.png").forward(request, response);

return;

}

String domain = getDomain(referer);

if (!domain.equals(domainName)) {

request.getRequestDispatcher("/imgs/error.png").forward(request, response);

return;

}

chain.doFilter(request, response);

}

 

/**

 * 获取url对应的域名

 *

 * @param url

 * @return

 */

public String getDomain(String url) {

String result = "";

int j = 0, startIndex = 0, endIndex = 0;

for (int i = 0; i < url.length(); i++) {

if (url.charAt(i) == '/') {

j++;

if (j == 2)

startIndex = i;

else if (j == 3)

endIndex = i;

}

 

}

result = url.substring(startIndex + 1, endIndex);

return result;

}

 

public void destroy() {

 

}

}

 

 

注意测试的时候,最好开启两个不同的浏览器测试,避免图片缓存的原因

 

CSRF攻击

CSRF攻击产生的原因

 

(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用也就是人们所知道的钓鱼网站。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

 

 

防御CSRF攻击手段

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

忘记密码漏洞

 

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

防御手段:

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

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

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

 

 

上传文件漏洞

漏洞描述

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

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

漏洞危害

1)可以得到WEBSHELL

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

 

 

Tomcat虚拟地址:

 

F:\itmayiedujiangke2018-06-12\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\tomcat_web

 

环境搭建

 Maven依赖

<dependencies>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>javax.servlet-api</artifactId>

<version>4.0.1</version>

</dependency>

 

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.3</version>

</dependency>

 

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.4</version>

</dependency>

 

</dependencies>

 

Index.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

 

<form action="/load/UploadServlet" method="post"

enctype="multipart/form-data">

<input type="file" name="file" /> <input type="submit" value="submit" />

</form>

</body>

</html>

 

UploadServlet

public class UploadServletextends HttpServlet {

 

/**

 * 文件上传

 */

protected void doPost(HttpServletRequest request, HttpServletResponse response) {

String root = request.getServletContext().getRealPath("/upload");

DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

try {

List<FileItem> list = upload.parseRequest(request);

for (FileItem it : list) {

// 如果是file文件类型

if (!it.isFormField()) {

it.write(new File(root + "/" + it.getName()));

response.getWriter().write("success");

}

}

} catch (Exception e) {

try {

response.getWriter().write("exception");

} catch (IOException e1) {

e1.printStackTrace();

}

e.printStackTrace();

}

}

 

}

 

 

 脚本文件

创建一个a.jsp

 

<%@page import="java.io.File"%>

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>

<%

    String root ="F:\\itmayiedu";

    File file = new File(root);

    file.delete();

%>

 

 

 

 

修复方案

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

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

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

 

 

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

 

/**

 * 文件上传

 */

protected void doPost(HttpServletRequest request, HttpServletResponse response) {

String root = request.getServletContext().getRealPath("/upload");

DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

try {

List<FileItem> list = upload.parseRequest(request);

for (FileItem it : list) {

// 如果是file文件类型

if (!it.isFormField()) {

FileType fileType = getFileType(it.getInputStream());

if (fileType == null) {

// 非图片格式

response.getWriter().write("fail");

return;

}

String imgValue = fileType.getValue();

System.out.println("imgValue:" + imgValue);

// 是图片格式

it.write(new File(root + "/" + it.getName()));

response.getWriter().write("success");

 

}

}

} catch (Exception e) {

try {

response.getWriter().write("exception");

} catch (IOException e1) {

e1.printStackTrace();

}

e.printStackTrace();

}

}

 

// 判断文件是图片格式

public static FileType getFileType(InputStream is) throws IOException {

byte[] src = new byte[28];

is.read(src, 0, 28);

StringBuilder stringBuilder = new StringBuilder("");

if (src == null || src.length <= 0) {

return null;

}

for (int i = 0; i < src.length; i++) {

int v = src[i] & 0xFF;

String hv = Integer.toHexString(v).toUpperCase();

if (hv.length() < 2) {

stringBuilder.append(0);

}

stringBuilder.append(hv);

}

FileType[] fileTypes = FileType.values();

for (FileType fileType : fileTypes) {

if (stringBuilder.toString().startsWith(fileType.getValue())) {

return fileType;

}

}

return null;

}

 

其他攻击漏洞

直接异常信息,会给攻击者以提示。 可以使用mvc中的工具,把错误码异常等进行封装

HTML注释, 会暴露功能,方便攻击。 上线时去除注释

文件上传, 如果本身功能就是上传文件去执行,那么就有可能执行非常危险的命令。 解决方式是,设置文件白名单,限制文件类型,另外还可以重新命名文件,改名为不可执行的

路径遍历, 使用相对路径来遍历未开放的目录。 方式是将JS,CSS部署在独立的服务器,使用独立域名。 其他文件不使用静态URL访问,动态参数不包含文件路径信息。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值