// public CheckResult retCheck; /// <summary> /// コンストラクタ /// </summary> /// <param name="checker">コピーコンストラクタ(ライトコピー)</param> public Checker(Checker checker) { //retCheck = new CheckResult(); loginUrl = checker._loginUrl; homeUrl = checker._homeUrl; getOnlyUrl = checker._getOnlyUrl; formdata = checker._formdata; //参照渡し formdatas = checker.formdatas; checkResult = checker.checkResult; firstResponse = checker.firstResponse; }
// public CheckResult retCheck; /// <summary> /// コンストラクタ /// </summary> /// <param name="checker">コピーコンストラクタ(ライトコピー)</param> public Checker(Checker checker) { //retCheck = new CheckResult(); loginUrl = checker._loginUrl; homeUrl = checker._homeUrl; getOnlyUrl = checker._getOnlyUrl; formdata = checker._formdata; //参照渡し formdatas = checker.formdatas; checkResult = checker.checkResult; firstResponse = checker.firstResponse; }
/// <summary> /// URLからフォームを抽出し、FormDataをリターンするメソッド /// </summary> /// <param name="postdata">Postするバイトデータ</param> /// <returns>取得したフォームデータの配列</returns> public void searchForms(String postdata) { firstResponse = getResponse(loginUrl, postdata, null, null); //(2)HtmlDocumentクラスにHTMLをセット HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); doc.OptionAutoCloseOnEnd = false; //最後に自動で閉じる(?) doc.OptionCheckSyntax = false; //文法チェック。 doc.OptionFixNestedTags = true; //閉じタグが欠如している場合の処理 HtmlNode.ElementsFlags.Remove("form"); doc.LoadHtml(firstResponse.body); /* * System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); * System.Diagnostics.Debug.Write(firstResponse.body); * DefaultTraceListener dtl = (DefaultTraceListener)Debug.Listeners["Default"]; * dtl.LogFileName = "./debug.txt"; */ Debug.WriteLine(firstResponse.body); ArrayList dataList = new ArrayList(); // FORMの解析 HtmlAgilityPack.HtmlNodeCollection nodecol = doc.DocumentNode.SelectNodes("//form"); HtmlAgilityPack.HtmlNodeCollection nodecola = doc.DocumentNode.SelectNodes("//input"); HtmlAgilityPack.HtmlNodeCollection nodecolas = doc.DocumentNode.SelectNodes("//meta"); if (nodecol != null) { foreach (HtmlNode elements in nodecol) { FormData formData = new FormData((String)elements.GetAttributeValue("name", ""), (String)elements.GetAttributeValue("action", "")); //System.Console.WriteLine("ACTION:" + elements.GetAttribute("action") + System.Environment.NewLine); recSearchform(elements, ref formData); dataList.Add(formData); } } formdatas = (FormData[])dataList.ToArray(typeof(FormData)); }
//Urlにcookie持ってpostして結果を返すメソッド private CheckerWebResponse getResponse(String url, String post, CookieContainer cookie, String referer) { HttpWebRequest httpConnection = (HttpWebRequest)WebRequest.Create(url); httpConnection.AllowAutoRedirect = false; httpConnection.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) SessionFixationChecker"; if (referer != null) { httpConnection.Referer = referer; } //Proxy設定 デバッグ用 //System.Net.WebProxy proxy = new System.Net.WebProxy("localhost", 8080); //httpConnection.Proxy = proxy; //Set Cookie if (cookie == null) { cookie = new CookieContainer(); } else { CookieCollection collection = cookie.GetCookies(new Uri(url)); /* * foreach (var dic in collection) * { * Console.Write(dic); * } */ } httpConnection.CookieContainer = cookie; //連送防止用Sleep //System.Threading.Thread.Sleep(100); //POST if (post != null) { if (post != "") { httpConnection.Method = "POST"; httpConnection.ContentType = "application/x-www-form-urlencoded"; } } //Do Not Expect 100 httpConnection.ServicePoint.Expect100Continue = false; //ストリームを開いてPOST //(これ以降設定をいじれなくなるのでここまでで設定を終わらせる if (post != null) { if (post != "") { httpConnection.GetRequestStream().Write(Encoding.ASCII.GetBytes(post), 0, Encoding.ASCII.GetBytes(post).Length); } } //Get Response try { CheckerWebResponse resp = new CheckerWebResponse(); HttpWebResponse httpResponse = (HttpWebResponse)httpConnection.GetResponse(); Stream resStream = httpResponse.GetResponseStream(); MemoryStream ms = new MemoryStream(); while (true) { byte[] tmp = new byte[1024]; int len = resStream.Read(tmp, 0, 1024); if (len <= 0) { break; } else { ms.Write(tmp, 0, len); } } byte[] byteData = ms.ToArray(); ms.Close(); Encoding encode = EncodeLib.GetCode(byteData); if (encode != null) { resp.body = encode.GetString(byteData); } else { //デフォルトではUnicode resp.body = Encoding.Unicode.GetString(byteData); } //クッキーを入手 String cookietext = httpResponse.Headers["Set-Cookie"]; resStream.Close(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.location = httpResponse.Headers["Location"]; resp.statusCode = httpResponse.StatusCode.GetHashCode(); return(resp); } catch (System.Net.WebException ex) { //HTTPプロトコルエラーかどうか調べる if (ex.Status == System.Net.WebExceptionStatus.ProtocolError) { //HttpWebResponseを取得 System.Net.HttpWebResponse erresp = (System.Net.HttpWebResponse)ex.Response; String cookietext = erresp.Headers["Set-Cookie"]; String location = erresp.Headers["Location"]; CheckerWebResponse resp = new CheckerWebResponse(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.statusCode = erresp.StatusCode.GetHashCode(); resp.body = erresp.StatusDescription; resp.location = location; return(resp); } else { Console.WriteLine(ex.Message); //HttpWebResponseを取得 System.Net.HttpWebResponse erresp = (System.Net.HttpWebResponse)ex.Response; if (ex.Response == null) { throw new Exception(ex.Message); } String cookietext = erresp.Headers["Set-Cookie"]; CheckerWebResponse resp = new CheckerWebResponse(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.statusCode = 900; resp.body = erresp.StatusDescription; return(resp); } } }
/// <summary> /// 実際にチェックを行うメソッド /// </summary> public void checkSessions() { //LoginURL Test //ログイン前に振ってる物のチェック //CheckerWebResponse firstResponse = getResponse(loginUrl, null, null); //HomeURL Test //ログイン前に振った物をそのまま利用してるもの String formText = ""; foreach (KeyValuePair <string, FormInput> pair in formdata.table) { if (pair.Key != null && !pair.Key.Equals("")) { formText += Uri.EscapeDataString(pair.Key) + "=" + Uri.EscapeDataString(pair.Value.value) + "&"; } } formText = formText.Substring(0, formText.Length - 1); CheckerWebResponse secondResponse = getResponse(homeUrl, formText, firstResponse.cookieContainer, loginUrl); //セッションアダプション用 //振るタイミングは、ログイン画面を開いた後から、ログインをクリックする前までの間 CookieContainer cookieCont = copyContainer(secondResponse.cookieContainer, homeUrl); Hashtable randomSessiontable = new Hashtable(); bool checkRand = false; Hashtable mergeTable = new Hashtable(); foreach (DictionaryEntry dic in firstResponse.cookietable) { mergeTable[dic.Key] = dic.Value; } foreach (DictionaryEntry dic in secondResponse.cookietable) { mergeTable[dic.Key] = dic.Value; } foreach (DictionaryEntry dic in mergeTable) { CookieData tmp = (CookieData)dic.Value; if (isSession(tmp)) { checkRand = true; Random rand = new Random(); String randst = ""; char[] randchar = new char[tmp.value.Length]; for (int i = 0; i < tmp.value.Length; ++i) { randst += rand.Next(9); } cookieCont.GetCookies(new Uri(homeUrl))[tmp.name].Value = randst; randomSessiontable.Add(tmp.name, randst); } } CheckerWebResponse secondRandomSessionResponse = null; if (checkRand) { secondRandomSessionResponse = getResponse(homeUrl, formText, cookieCont, loginUrl); } else { secondRandomSessionResponse = new CheckerWebResponse(); secondRandomSessionResponse.body = null; } //セッションが一画面ごとに変わっていないかチェックするためのもの CheckerWebResponse secondResponseFixedCheckResult = null; if (secondResponse.statusCode >= 300 && secondResponse.statusCode <= 399) { secondResponseFixedCheckResult = getResponse(secondResponse.location, null, secondResponse.cookieContainer, loginUrl); } else if (getOnlyUrl != null) { secondResponseFixedCheckResult = getResponse(getOnlyUrl, null, secondResponse.cookieContainer, loginUrl); } //Check Hashtable firstCookietable = firstResponse.cookietable; Hashtable secondCookietable = secondResponse.cookietable; Hashtable secondResponseFixedChecktable = null; Hashtable secondRandomCookietable = secondRandomSessionResponse.cookietable; //ログイン前に割り振ったセッションをそのまま利用していないかのチェック fixChecker(firstCookietable, secondCookietable); //ログイン後にセッションを毎回変えているかのチェック if (secondResponseFixedCheckResult != null) { secondResponseFixedChecktable = secondResponseFixedCheckResult.cookietable; fixChecker(secondCookietable, secondResponseFixedChecktable); } //ログイン直前に割り振られた偽セッションをそのまま利用していないかのチェック foreach (DictionaryEntry dic in randomSessiontable) { String key = (String)dic.Key; if (secondRandomCookietable.ContainsKey(key)) { if ((String)randomSessiontable[key] == ((CookieData)secondRandomCookietable[key]).value) { ((CookieData)secondRandomCookietable[key]).fix = true; } } else { secondRandomCookietable.Add(key, new CookieData(key, (String)randomSessiontable[key], null, null, null, false, false)); ((CookieData)secondRandomCookietable[key]).fix = true; } } //レスポンス生成 CheckResult retCheck = new CheckResult(); //Set body retCheck.firstBody = firstResponse.body; retCheck.secondBody = secondResponse.body; if (secondResponseFixedCheckResult != null) { retCheck.secondResponseFixedCheckBody = secondResponseFixedCheckResult.body; } retCheck.secondRandomBody = secondRandomSessionResponse.body; //レスポンスにセット retCheck.firstCookieCheck = firstCookietable; retCheck.secondCookieCheck = secondCookietable; retCheck.secondRandomCookieCheck = secondRandomCookietable; if (secondResponseFixedCheckResult != null) { retCheck.secondResponseFixedCheck = secondResponseFixedChecktable; } checkResult = retCheck; }
//Urlにcookie持ってpostして結果を返すメソッド private CheckerWebResponse getResponse(String url, String post, CookieContainer cookie, String referer) { HttpWebRequest httpConnection = (HttpWebRequest)WebRequest.Create(url); httpConnection.AllowAutoRedirect = false; httpConnection.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) SessionFixationChecker"; if (referer != null) { httpConnection.Referer = referer; } //Proxy設定 デバッグ用 //System.Net.WebProxy proxy = new System.Net.WebProxy("localhost", 8080); //httpConnection.Proxy = proxy; //Set Cookie if (cookie == null) { cookie = new CookieContainer(); } else { CookieCollection collection = cookie.GetCookies(new Uri(url)); /* foreach (var dic in collection) { Console.Write(dic); } */ } httpConnection.CookieContainer = cookie; //連送防止用Sleep //System.Threading.Thread.Sleep(100); //POST if (post != null) { if (post != "") { httpConnection.Method = "POST"; httpConnection.ContentType = "application/x-www-form-urlencoded"; } } //Do Not Expect 100 httpConnection.ServicePoint.Expect100Continue = false; //ストリームを開いてPOST //(これ以降設定をいじれなくなるのでここまでで設定を終わらせる if (post != null) { if (post != "") { httpConnection.GetRequestStream().Write(Encoding.ASCII.GetBytes(post), 0, Encoding.ASCII.GetBytes(post).Length); } } //Get Response try { CheckerWebResponse resp = new CheckerWebResponse(); HttpWebResponse httpResponse = (HttpWebResponse)httpConnection.GetResponse(); Stream resStream = httpResponse.GetResponseStream(); MemoryStream ms = new MemoryStream(); while (true) { byte[] tmp = new byte[1024]; int len = resStream.Read(tmp, 0, 1024); if (len <= 0) { break; } else { ms.Write(tmp, 0, len); } } byte[] byteData = ms.ToArray(); ms.Close(); Encoding encode = EncodeLib.GetCode(byteData); if (encode != null) { resp.body = encode.GetString(byteData); } else { //デフォルトではUnicode resp.body = Encoding.Unicode.GetString(byteData); } //クッキーを入手 String cookietext = httpResponse.Headers["Set-Cookie"]; resStream.Close(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.location = httpResponse.Headers["Location"]; resp.statusCode = httpResponse.StatusCode.GetHashCode(); return resp; } catch (System.Net.WebException ex) { //HTTPプロトコルエラーかどうか調べる if (ex.Status == System.Net.WebExceptionStatus.ProtocolError) { //HttpWebResponseを取得 System.Net.HttpWebResponse erresp = (System.Net.HttpWebResponse)ex.Response; String cookietext = erresp.Headers["Set-Cookie"]; String location = erresp.Headers["Location"]; CheckerWebResponse resp = new CheckerWebResponse(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.statusCode = erresp.StatusCode.GetHashCode(); resp.body = erresp.StatusDescription; resp.location = location; return resp; } else { Console.WriteLine(ex.Message); //HttpWebResponseを取得 System.Net.HttpWebResponse erresp = (System.Net.HttpWebResponse)ex.Response; if (ex.Response == null) { throw new Exception(ex.Message); } String cookietext = erresp.Headers["Set-Cookie"]; CheckerWebResponse resp = new CheckerWebResponse(); resp.cookieContainer = cookie; resp.cookietable = makeCookieTable(cookietext); resp.statusCode = 900; resp.body = erresp.StatusDescription; return resp; } } }
/// <summary> /// URLからフォームを抽出し、FormDataをリターンするメソッド /// </summary> /// <param name="postdata">Postするバイトデータ</param> /// <returns>取得したフォームデータの配列</returns> public void searchForms(String postdata) { firstResponse = getResponse(loginUrl, postdata, null,null); //(2)HtmlDocumentクラスにHTMLをセット HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); doc.OptionAutoCloseOnEnd = false; //最後に自動で閉じる(?) doc.OptionCheckSyntax = false; //文法チェック。 doc.OptionFixNestedTags = true; //閉じタグが欠如している場合の処理 HtmlNode.ElementsFlags.Remove("form"); doc.LoadHtml(firstResponse.body); /* System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Debug.Write(firstResponse.body); DefaultTraceListener dtl = (DefaultTraceListener)Debug.Listeners["Default"]; dtl.LogFileName = "./debug.txt"; */ Debug.WriteLine(firstResponse.body); ArrayList dataList = new ArrayList(); // FORMの解析 HtmlAgilityPack.HtmlNodeCollection nodecol = doc.DocumentNode.SelectNodes("//form"); HtmlAgilityPack.HtmlNodeCollection nodecola = doc.DocumentNode.SelectNodes("//input"); HtmlAgilityPack.HtmlNodeCollection nodecolas = doc.DocumentNode.SelectNodes("//meta"); if (nodecol != null) { foreach (HtmlNode elements in nodecol) { FormData formData = new FormData((String)elements.GetAttributeValue("name", ""), (String)elements.GetAttributeValue("action", "")); //System.Console.WriteLine("ACTION:" + elements.GetAttribute("action") + System.Environment.NewLine); recSearchform(elements, ref formData); dataList.Add(formData); } } formdatas = (FormData[])dataList.ToArray(typeof(FormData)); }
/// <summary> /// 実際にチェックを行うメソッド /// </summary> public void checkSessions() { //LoginURL Test //ログイン前に振ってる物のチェック //CheckerWebResponse firstResponse = getResponse(loginUrl, null, null); //HomeURL Test //ログイン前に振った物をそのまま利用してるもの String formText = ""; foreach (KeyValuePair<string, FormInput> pair in formdata.table) { if (pair.Key != null && !pair.Key.Equals("")) { formText += Uri.EscapeDataString(pair.Key) + "=" + Uri.EscapeDataString(pair.Value.value) + "&"; } } formText = formText.Substring(0, formText.Length - 1); CheckerWebResponse secondResponse = getResponse(homeUrl, formText, firstResponse.cookieContainer,loginUrl); //セッションアダプション用 //振るタイミングは、ログイン画面を開いた後から、ログインをクリックする前までの間 CookieContainer cookieCont = copyContainer(secondResponse.cookieContainer, homeUrl); Hashtable randomSessiontable = new Hashtable(); bool checkRand = false; Hashtable mergeTable = new Hashtable(); foreach (DictionaryEntry dic in firstResponse.cookietable) { mergeTable[dic.Key] = dic.Value; } foreach (DictionaryEntry dic in secondResponse.cookietable) { mergeTable[dic.Key] = dic.Value; } foreach (DictionaryEntry dic in mergeTable) { CookieData tmp = (CookieData)dic.Value; if (isSession(tmp)) { checkRand = true; Random rand = new Random(); String randst = ""; char[] randchar = new char[tmp.value.Length]; for (int i = 0; i < tmp.value.Length; ++i) { randst += rand.Next(9); } cookieCont.GetCookies(new Uri(homeUrl))[tmp.name].Value = randst; randomSessiontable.Add(tmp.name, randst); } } CheckerWebResponse secondRandomSessionResponse = null; if (checkRand) { secondRandomSessionResponse = getResponse(homeUrl, formText, cookieCont,loginUrl); } else { secondRandomSessionResponse = new CheckerWebResponse(); secondRandomSessionResponse.body = null; } //セッションが一画面ごとに変わっていないかチェックするためのもの CheckerWebResponse secondResponseFixedCheckResult = null; if (secondResponse.statusCode >= 300 && secondResponse.statusCode <= 399) { secondResponseFixedCheckResult = getResponse(secondResponse.location, null, secondResponse.cookieContainer,loginUrl); } else if (getOnlyUrl != null) { secondResponseFixedCheckResult = getResponse(getOnlyUrl, null, secondResponse.cookieContainer,loginUrl); } //Check Hashtable firstCookietable = firstResponse.cookietable; Hashtable secondCookietable = secondResponse.cookietable; Hashtable secondResponseFixedChecktable = null; Hashtable secondRandomCookietable = secondRandomSessionResponse.cookietable; //ログイン前に割り振ったセッションをそのまま利用していないかのチェック fixChecker(firstCookietable, secondCookietable); //ログイン後にセッションを毎回変えているかのチェック if (secondResponseFixedCheckResult != null) { secondResponseFixedChecktable = secondResponseFixedCheckResult.cookietable; fixChecker(secondCookietable, secondResponseFixedChecktable); } //ログイン直前に割り振られた偽セッションをそのまま利用していないかのチェック foreach (DictionaryEntry dic in randomSessiontable) { String key = (String)dic.Key; if (secondRandomCookietable.ContainsKey(key)) { if ((String)randomSessiontable[key] == ((CookieData)secondRandomCookietable[key]).value) { ((CookieData)secondRandomCookietable[key]).fix = true; } } else { secondRandomCookietable.Add(key, new CookieData(key, (String)randomSessiontable[key], null, null, null, false, false)); ((CookieData)secondRandomCookietable[key]).fix = true; } } //レスポンス生成 CheckResult retCheck = new CheckResult(); //Set body retCheck.firstBody = firstResponse.body; retCheck.secondBody = secondResponse.body; if (secondResponseFixedCheckResult != null) retCheck.secondResponseFixedCheckBody = secondResponseFixedCheckResult.body; retCheck.secondRandomBody = secondRandomSessionResponse.body; //レスポンスにセット retCheck.firstCookieCheck = firstCookietable; retCheck.secondCookieCheck = secondCookietable; retCheck.secondRandomCookieCheck = secondRandomCookietable; if (secondResponseFixedCheckResult != null) retCheck.secondResponseFixedCheck = secondResponseFixedChecktable; checkResult = retCheck; }