在日常的测试中,编码问题会引发一系列漏洞。如我们经常听说的宽字节注入、window下的特殊解码漏洞、还有大佬所说的%3F编码问题,这些都成为了安全测试中的一个重要测试项,今天给大家讲讲最近比较火的解码导致的任意账号接管。这篇文章主要讲的是邮件服务器与数据库之间存在一个有趣的解析差异—某些特殊字符的处理方式不一致导致出现的严重漏洞。谈到不一致性(inconsistency),我认为这是安全领域最重要的一个漏洞成因。它不仅是众多漏洞的核心成因,甚至催生了一类新漏洞的发现——比如HTTP请求走私(HTTP Request Smuggling)。我们看看下面两个链接:现在让我们假设一下,这两个请求路径如果我们通过curl去做请求,那么Host会是什么呢?到底是benign.com还是attacker.com,做个简单实验如下:(从上面的图中可以清晰的看出,在curl程序发起请求时,都是取后面的作为主机名) 当然,今天要讲的并不是这个,到底是谁并不重要,重要的是数据在多个程序或者组件之间传递时候要保持其一致性最为关键。如果恰巧存在不一致,那么漏洞就有可能出现。或许许多人都曾发现过这个漏洞,但从未公开透露它确实是个能赚钱的漏洞。它的测试非常简单——既不需要复杂的漏洞链组合,也不需要高深的技术。这种漏洞可能出现在Web应用的任何环节,而重点关注的是使用任意邮件服务器配合MySQL实现的密码重置功能。下面我们一起来剖析一个密码重置函数的案例: 第二步:服务器通过邮箱去数据库查询是否有这个邮件账号存在 第三步:如果存在,就生成一个token存在数据库中 第四步:服务器调用SMTP服务给用户的邮箱发送邮件重置链接 这里面存在一个问题点,就是通过服务器调用SMTP服务发送重置密码链接给用户的时候,到底是怎么传递邮箱参数的? 假设1:通过第二步查询到的邮箱发送邮件,这种一般不会存在问题 假设2:通过用户在第一步输入的邮箱发送邮件,存在问题 在SMTP服务中,对于字符是有着明确的区分的,比如我们常见的a和ã都可以被清晰的区分出来,也会被发送到对应的邮箱中去而接下来,让我们一起看看MYSQL数据库(其他类型数据库我已经试过了,好像没这个问题,所以大家不用试了)的处理其实在字符中,类似a的字符还是超级多的,我们肉眼看上去就有这些import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="root",
database="test"
)
cursor = conn.cursor()
ch='a'
for i in range(0, 0x10FFFF + 1):
if 0xD800 <= i <= 0xDFFF:
continue
try:
char = chr(i)
sql = f"SELECT %s = '{ch}' AS is_equal"
cursor.execute(sql, (char,))
result = cursor.fetchone()
if result[0]:
print(f"Unicode Character {i:04X} ({char}) is equal to '{ch}' in MySQL")
except:
print(f"Failed to process character U+{i:04X}")
continue
cursor.close()
conn.close()
我们假设一个场景,A用户在测试一个系统,这个系统是通过邮箱注册,并且有通过邮箱找回密码的功能,那么我们就可以这样测试。首先已知银行系统某个员工的邮箱账号是:zhangsan@bank.com,那么我们可以用一个账号zhangsan@bànk.com去做密码重置,因为在Mysql看来这二者没特殊处理的情况下是一样的,所以邮件会被成功发送,但是发送邮件的服务器就不这样了,它会把邮件发送到用户输入的zhangsan@bànk.com中去,这样只要我们注册这个bànk.com域名,就能成功拿到[email protected]的密码重置链接,因为画图不易,所以用别人的图替代:因为我们知道,伟大的wordpress也是通过邮箱找回密码,如果能成功利用那就妙了wp使用的也是以ci结尾的比较规则,所以在数据库查询这一步是没任何问题的,但是我们查看一下发送邮件的流程,就知道wp是很安全的它是通过将从数据库查询到的邮箱地址作为发送邮件的邮箱,这就有效的保持了一致性。到这里,我们也反思一个问题,那么这种技术是不是也可以用到其他的场景去呢?答案是肯定的推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...