web安全架构(上)

开始之前这们说一下,web网站其实防御也相当重要,不管是服务器防御,后台数据防御,数据库防御都是必须滴,那我们说说常见的几种。后续再给大家分享 api接口安全性设计,黑名单白名单,以及防御DDOS。

XSS攻击,SQL注入,防盗链,csrf模拟请求,文件上传漏洞,忘记密码漏洞,Api接口幂等,其他问题等等,,,,,,

什么是XSS?

Xss就是javascript 脚本攻击,就是在表单提交的时候提交一个小脚本,因为浏览器默认是支持脚本的,所以写个小脚本不做处理的话问题就很大。

如何防御?

1,通过后台编写一个过滤器拦截所有getParameter参数 重写httpservletwrapp方法。

2,通过工具类将参数特殊字符转换成html源代码保存。

// 重写HttpServletRequestWrapper 防止XSS攻击

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest 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);
}
return value;
}
}

好啦这个Xss现在就可以简单防御啦,下面我们说说sql注入

什么是sql注入?

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

如何防御?

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

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

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

防盗链

什么是防盗链?

防盗链就是A网站有一张图片,B网站要引用过来使用到自己网站,引用图片和样式,js等等。

如何防御?

防御思路:

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

2,通过动静分离或者前后端分离。通过nginx配置。

@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);
}

这里贴的只是示列代码具体优化还得你自己去优化。

什么是csrf模拟请求?

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

也就是通俗一点来说就是,大量请求你的接口,通过抓包工具请求分析,伪造token访问你的接口,攻击服务器降低服务器数据库性能。

如何解决防御?

1,MVCC方案

 多版本并发控制,该策略主要使用 update with condition(更新带条件来防止)来保证多次外部请求调用对系统的影响是一致的。在系统设计的过程中,合理的使用乐观锁,通过 version 或者 updateTime(timestamp)等其他条件,来做乐观锁的判断条件,这样保证更新操作即使在并发的情况下,也不会有太大的问题。例如

select * from tablename where condition=#condition# // 取出要跟新的对象,带有版本 versoin

update tableName set name=#name#,version=version+1 where version=#version#

在更新的过程中利用 version 来防止,其他操作对对象的并发更新,导致更新丢失。为了避免失败,通常需要一定的重试机制。

2.去重表

在插入数据的时候,插入去重表,利用数据库的唯一索引特性,保证唯一的逻辑。

3,悲观锁

select for update,整个执行过程中锁定该订单对应的记录。注意:这种在 DB 读大于写的情况下尽量少用。

4,Token机制,防止页面重复提交

把token放在redis 里面通过限流方式,每个token只能使用一次,网络延迟或者重试机制解决这个问题。

public class TokenUtils {
private static Map<String, Object> tokenMap = new HashMap<String, Object>();
// 获取token
public static String getToken() {
// 1.生成令牌
String token = "token-" + System.currentTimeMillis();
// 2.存入tokenMap
tokenMap.put(token, token);
return token;
}
// 验证token,并且删除对应的token
public static Boolean exisToken(String token) {
// 1.从集合中获取token
Object result = tokenMap.get(token);
if (result == null) {
return false;
}
// 2.删除对应的token
tokenMap.remove(token);
return true;
}
}

文件上传漏洞

什么是文件上传漏洞?

上传漏洞这个顾名思义,就是攻击者通过上传木马文件,直接得到WEBSHELL,危害等级超级高,现在的入侵中上传漏洞也是常见的漏洞。 导致该漏洞的原因在于代码作者没有对访客提交的数据进行检验或者过滤不严,可以直接提交修改过的数据绕过扩展名的检验。

如何解决防御?

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

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

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

4)通过文件流解析判断文件类型。

这里给一个图片的判断方式

web安全架构

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();
// 是图片格式
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;
}

忘记密码漏洞

什么是忘记密码漏洞?

我在这里分析一个常见的qq漏洞,现在很多都还有人家盗用别人密码,然后通过qq发送消息,找你借钱或者转账到某个地方,黑客就是通过 抓包分析暴力破解密码(写一个程序破解验证码,如果是4位纯数字可想而知),然后盗取你的短信验证码登录,如果发生了这样的情况,如果是qq的话你就一直发短信验证码,联系客户还得一段时间。因为大家都知道qq验证码都是4位所以别人很好破解,我这里说的都是真实案例,因为楼主以前也被别人这样操作过,但是我就一直发短信验证码后面就找回来啦。

如何防御

忘记密码验证码最好在6-8位 最好是加字符,字母组合。

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

使用黑名单和白名单机制,防御攻击(OAuth2.0协议)。

赞(4) 打赏
特别声明:除特殊标注,本站文章均为原创,遵循CC BY-NC 3.0,转载请注明出处。三伏磨 » web安全架构(上)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏