首页
社区
课程
招聘
[旧帖] [原创]java如何实现伪造发信地址---针对于邮件攻击 0.00雪花
发表于: 2014-3-17 11:57 1778

[旧帖] [原创]java如何实现伪造发信地址---针对于邮件攻击 0.00雪花

2014-3-17 11:57
1778
从2012年注册以来,一直潜水到现在,现在,最终还是决定回到看雪妈妈的怀抱,在社区发表一些文章。
首先说明一下,现在大多数人都用oracle的javamail的jar来实现发邮件,在这里我不得不承认javamail确实是一款强大的工具,但是,oracle对它进行了底层封装,对于开发者来说是透明的,因此,也许是出于安全的考虑,你是不能够随意设置mail from的。那该怎么办呢?对于聪明的程序员来说,这段问题是难不倒的,各位看官看看我是怎么实现的。

一封邮件的底层实现过程是怎么样的呢?
在此,以windows系统为例:
1)进入字符模式
2)启动telnet程序:telnet smtp.163.com 25
登录成功后邮件服务器会反馈一个信息“RESPONSE:220 xxxx ESMTP sendmail xxxxx”
3)输入:HELO abc.cn(想要伪造邮件的地址域名,比如163邮箱:163.com.cn)
系统会反馈一个信息“Response: 250 abc.cn Hello [xxx.xxx.xxx.xxx],pleased to meet you”表示邮件系统认可
4)输入:MAIL FROM :xxxx@163.com (不能缺少“:”号,下面同样,邮件发送者的地址)
系统反馈信息“Response: 250 2.1.0 <xxxx@163.com> …. Sender ok”
注意:此处的地址不能伪造,不然通不过邮箱服务器的认证。
5)输入: RCPT TO :xxxx@qq.com (邮件接收者的地址)
系统反馈信息“Response: 250 2.1.0 <xxxx@qq.com> …. Recipient ok”
6)输入:DATA 回车
from:xxx(这里可以随意伪造)
to:xxx(这里可以随意伪造)
(开始输入邮件正文,完成后一定要“回车”之后输入“.”号)
.(注意是英文状态下的“.”号,表示邮件输入完毕,最后再“回车”)
7)输入:
QUIT (邮件内容输入完成,退出)
系统反馈信息“Response: 221 2.0.0 ab.cn closing connection”
到此为止邮件发送完成

下面就是我用java代码来进行的底层实现:
//邮件
class MyMail {
        String from;
        String to;
        String subject;
        String content;
        String userName;
        String pwd;

        public MyMail(String from, String to, String subject, String content, String userName, String pwd) {
                this.from = from;
                this.to = to;
                this.subject = subject;
                this.content = content;
                this.userName = this.toBASE64(userName);
                this.pwd = this.toBASE64(pwd);
        }

        /**
         * 在 MyMail 类中进行用户名、密码的转码工作
         */
        private String toBASE64(String str) {
                return (new sun.misc.BASE64Encoder().encode(str.getBytes()));
        }
}

//简单的邮件发送端类,实现发送功能
public class FakeMailSender {
        private String smtpServer;
        private int port = 25;

        private Socket socket;
        BufferedReader br;
        PrintWriter pw;
       
        /**
         * 根据发件人的邮箱地址确定SMTP邮件服务器
         */
        private void initServer(String from) {
                if(from.contains("@163")) {
                        this.smtpServer = "smtp.163.com";
                }else if(from.contains("@126")) {
                        this.smtpServer = "smtp.126.com";
                }else if(from.contains("@sina")) {
                        this.smtpServer = "smtp.sina.com";
                }else if(from.contains("@qq")) {
                        this.smtpServer = "smtp.qq.com";
                }
        }

        public void sendEmail(MyMail email) {
                try {
                        this.initServer(email.from);
                       
                        this.socket = new Socket(smtpServer, port);
                        this.br = this.getReader(socket);
                        this.pw = this.getWriter(socket);
                       
                        // 开始组装发送邮件的命令序列
                        send_Receive(null);                // 接收连接SMTP服务器成功的信息
                        send_Receive("ehlo hao");
                        send_Receive("auth login");
                        send_Receive(email.userName);
                        send_Receive(email.pwd);
                        send_Receive("mail from:<" + email.from + ">");
                        send_Receive("rcpt to:<" + email.to + ">");
                        send_Receive("data");
                       
                        // 邮件内容
                        pw.println("from:" + email.from);
                        pw.println("to:" + email.to);
                        // 主题与正文之间一定要空一行,即加上"\r\n"
                        pw.println("subject:" + email.subject + "\r\n");
                       
                        // 在控制台打印邮件内容
                        System.out.println("from:" + email.from);
                        System.out.println("to:" + email.to);                       
                        System.out.println("subject:" + email.subject + "\r\n");
                        System.out.println(email.content);
                       
                        // 邮件正文
                        pw.println(email.content);
                       
                        // 一定记得正文以"."结束
                        send_Receive(".");
                        send_Receive("quit");
                } catch (IOException e) {
                        e.printStackTrace();
                } finally {
                        try {
                                if (socket != null)
                                        socket.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }
       
        /**
         *  每发送一条命令,必须在命令后面加上"\r\n",
         *  则同时打印出smtp邮件服务器的相应状态码
         * @param command
         */
        private void send_Receive(String command) throws IOException{
                if(command != null) {
                        // 向SMTP邮件服务器发送命令,一定要记得加上"\r\n"
                        pw.print(command + "\r\n");
                        pw.flush();
                        System.out.println("用户 >> " + command);
                }
               
                char [] response = new char[1024];
                        br.read(response);
                        System.out.println(response);
        }

        /**
         * 获取 Socket 的输出流
         */
        private PrintWriter getWriter(Socket socket) throws IOException {
                OutputStream socketOut = socket.getOutputStream();
                return new PrintWriter(socketOut, true);
        }

        /**
         * 获取 Socket 的输入流
         */
        private BufferedReader getReader(Socket socket) throws IOException {
                InputStream socketIn = socket.getInputStream();
                return new BufferedReader(new InputStreamReader(socketIn));
        }

        // 测试
        public static void main(String[] args) {
                MyMail email = new MyMail("xxxx@163.com", "xxxxx@qq.com", "test", "this is a joke for fun!", "xxxx", "xxxxx");
                new FakeMailSender().sendEmail(email);
        }
}

到此就结束了哈!!!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 328
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢楼主分享
2014-3-17 14:39
0
游客
登录 | 注册 方可回帖
返回
//