自己最近也剛開始學習網站安全的技術,以下有寫的不對的地方還請高手多指點啊.
網站漏洞主要集中在動态網頁中,靜态網站基本不存在什麼漏洞。
1.sql注入和跨站點腳本攻擊
2.上傳漏洞
3.文本編輯器漏洞
4.網站目錄及密碼安全
解決辦法:
1.sql注入和跨站點腳本攻擊:對這類漏洞來說就是用一些安全掃描工具進行檢測,然後修複,以下是我個人總結的一點小知識:
對于asp網站:
一。跨站點攻擊
1.在需要使用者或管理者輸入資料的地方用js去除危險字元
js腳本:
function RemoveBad(strTemp) {
strTemp = strTemp.replace(/[$ <> & % ' ( ) + - = " ; / ]/g, "")
return strTemp;
}
//asp腳本方法
<%
'過濾掉危險的html和特殊字元,防止跨網站攻擊
function nohtml(str)
dim re
Set re=new RegExp
re.IgnoreCase =true
re.Global=True
re.Pattern="(/<.[^/<]*/>)"
str=re.replace(str," ")
re.Pattern="(/<//[^/<]*/>)"
str=re.replace(str,"")
re.Pattern="([/'/&/-/+/=/(/)/;/[/]/{/}])" '去除特殊符号
str=re.replace(str,"")
nohtml=str
set re=nothing
end function
'對要顯示的資料進行編碼,防止顯示危險字元
function showdata(str)
showdata=server.HTMLEncode(nohtml(str))
end function
%>
對于aspx網站來說,有一個通用的安全檢測類是很重要的,以下是個人總結:
namespace DZ.Security
{
//輸入資料安全性相關
public class Sec
{
#region 檢測輸入的内容是否有攻擊的可能性
/// <summary>
/// 檢測輸入的内容是否有攻擊的可能性
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string par_queryString_forStr(string str)
{
//大于20很可能是注入攻擊
string str_process = null;
if (str.Length > 20)
{
str_process = str.Substring(0, 20);
}
else
{
str_process = str;
}
return str_process;
}
#endregion
#region 檢測int 類型的id号的和法性
/// <summary>
/// 檢測int 類型的id号的和法性
/// </summary>
/// <param name="str">要檢測的字元</param>
/// <returns></returns>
public static string par_queryString_forId(string str)
{
//ID數字 整型 最大值65535 不超過5個數字
string str_process = null;
if (str.Length > 5)
{
str_process = str.Substring(0, 5);
}
else
{
str_process = str;
}
return str_process;
}
#endregion
#region 硬性過濾髒字元串
/// <summary>
/// 硬性過濾髒字元串
/// </summary>
/// <param name="str">要處理的字元串</param>
/// <returns></returns>
public static string par_filter_forNews(string str)
{
//硬性過濾
//依次為 **競争對手,拿我的免費産品賣錢的家夥
string[] filterStr = {
**
//領風五年,域名:
};
int filterLen = filterStr.Length;
for (int i = 0; i < filterLen; i++)
{
str = str.Replace(filterStr[i], "");
}
return str;
}
#endregion
#region 對危險的html,Sql标記和特殊符号進行過濾
/// <summary>
/// 對危險的html,Sql标記和特殊符号進行過濾
/// </summary>
/// <param name="strHtml">要過濾的字元串</param>
/// <returns>過濾後的字元串</returns>
public static string FilterToTxt(string strHtml)
{
string[] aryReg = {
@"<script[^>]*?>.*?</script>",
@"<(///s*)?!?((/w+:)?/w+)(/w+(/s*=?/s*(([""'])(//[""'tbnr]|[^/7])*?/7|/w+)|.{0})|/s)*?(///s*)?>",
@"([/r/n])[/s]+",
@"&(quot|#34);",
@"&(amp|#38);",
@"&(lt|#60);",
@"&(gt|#62);",
@"&(nbsp|#160);",
@"&(iexcl|#161);",
@"&(cent|#162);",
@"&(pound|#163);",
@"&(copy|#169);",
@"&#(/d+);",
@"-->",
@"<!--.*/n",
@"select",
@"delete",
@"update",
@"insert into",
@"Insert",
@"Delete",
@"update",
@"create",
@"drop",
@"exec",
@"dri",
@"[^/w/[email protected]]"
};
string strOutput = strHtml;
for (int i = 0; i < aryReg.Length; i++)
{
Regex regex = new Regex(aryReg[i], RegexOptions.IgnoreCase);
strOutput = regex.Replace(strOutput, string.Empty);
}
return strOutput;
}
#endregion
}
//資料加密,解密
public class EncAndDec
{
public string _QueryStringKey = "logowang"; //URL傳輸參數加密Key abcdefgh
public string _PassWordKey = "hgfedcba"; //PassWord加密Key
#region url 參數加密解密
public static string UrlDecode(string input)
{
return HttpUtility.UrlDecode(input);
}
public static string UrlEncode(string input)
{
return HttpUtility.UrlEncode(input);
}
#endregion
#region md5字元串加密
/// <summary>
/// md5字元串加密
/// </summary>
/// <param name="str">要加密字元串</param>
/// <returns></returns>
public string MD5Encrypt(string str)
{
try
{
byte[] hashvalue = (new MD5CryptoServiceProvider()).ComputeHash(Encoding.UTF8.GetBytes(str));
return BitConverter.ToString(hashvalue);
}
catch
{
return String.Empty;
}
}
#endregion
#region 加密解密相關
/// <summary>
/// 加密URL傳輸的字元串
/// </summary>
/// <param name="QueryString">要加密的字元串</param>
/// <returns></returns>
public string EncryptQueryString(string QueryString)
{
return Encrypt(QueryString, _QueryStringKey);
}
/// <summary>
/// 解密URL傳輸的字元串
/// </summary>
/// <param name="QueryString">要解密的字元串</param>
/// <returns></returns>
public string DecryptQueryString(string QueryString)
{
return Decrypt(QueryString, _QueryStringKey);
}
///
/// 加密帳号密碼
///
///
///
public string EncryptPassWord(string PassWord)
{
return Encrypt(PassWord, _PassWordKey);
}
/// <summary>
/// 解密帳号密碼
/// </summary>
/// <param name="PassWord"></param>
/// <returns></returns>
public string DecryptPassWord(string PassWord)
{
return Decrypt(PassWord, _PassWordKey);
}
/// <summary>
/// DEC 加密過程
/// </summary>
/// <param name="pToEncrypt">要加密的字元串</param>
/// <param name="sKey">加密密鑰</param>
/// <returns></returns>
public string Encrypt(string pToEncrypt, string sKey)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider(); //把字元串放到byte數組中
byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
//byte[] inputByteArray=Encoding.Unicode.GetBytes(pToEncrypt);
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); //建立加密對象的密鑰和偏移量
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); //原文使用ASCIIEncoding.ASCII方法的GetBytes方法
System.IO.MemoryStream ms = new System.IO.MemoryStream(); //使得輸入密碼必須輸入英文文本
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
ret.ToString();
return ret.ToString();
}
/// <summary>
/// DEC 解密過程
/// </summary>
/// <param name="pToDecrypt">要解密的字元串</param>
/// <param name="sKey">解密密鑰</param>
/// <returns></returns>
public string Decrypt(string pToDecrypt, string sKey)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
for (int x = 0; x < pToDecrypt.Length / 2; x++)
{
int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
inputByteArray[x] = (byte)i;
}
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); //建立加密對象的密鑰和偏移量,此值重要,不能修改
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
StringBuilder ret = new StringBuilder(); //建立StringBuild對象,CreateDecrypt使用的是流對象,必須把解密後的文本變成流對象
return System.Text.Encoding.Default.GetString(ms.ToArray());
}
/// <summary>
/// 檢查己加密的字元串是否與原文相同
/// </summary>
/// <param name="EnString">加密的url</param>
/// <param name="FoString">加密的Password</param>
/// <param name="Mode">1:檢測url參數,2:檢測Password</param>
/// <returns></returns>
public bool ValidateString(string EnString, string FoString, int Mode)
{
switch (Mode)
{
default:
case 1:
if (Decrypt(EnString, _QueryStringKey) == FoString.ToString())
{
return true;
}
else
{
return false;
}
case 2:
if (Decrypt(EnString, _PassWordKey) == FoString.ToString())
{
return true;
}
else
{
return false;
}
}
}
#endregion
}
}
2.在需要顯示資料的地方用Html.encode()方法進行編碼,如下:
在執行頁中我們加入:
strUserName =server.HTMLEncode(Request.QueryString("userName"))
和
strUserName =server.HTMLEncode(Request.Form("userName"))
二。sql輸入攻擊
主要是在資料查詢頁面,對傳過來的參數進行安全檢測,避免不符合要求的參數進行資料庫查詢。如下:
if(Not IsNumeric(id)) then
Response.write("沒有相關資料")
else
進行資料查詢并顯示資料
end if
2.上傳漏洞:主要是對使用者上傳的檔案進行檢測,這個特别是在編寫程式時特别重要,以下是我用到的aspx。上傳檢測代碼:
#region 實作圖檔上傳lblhasPic,FileUpload1 lbladdArtic
protected void upLoadPic(Label lblp, Label lblisSuccess, FileUpload fileload)
{
lblisSuccess.Text = "";
lblp.ForeColor = System.Drawing.Color.Red;
if (fileload.HasFile)
{
string fileContentType = fileload.PostedFile.ContentType;
#region 擷取上傳檔案的檔案名并判斷檔案的合法性
bool fileOk = true;
string name = fileload.PostedFile.FileName; // 用戶端檔案路徑
FileInfo file = new FileInfo(name);
string fileName = file.Name; // 檔案名稱
if (fileName.Contains(";"))//上傳檔案含有分号,很有能是上傳圖檔木馬的前兆
{
fileOk = false;
}
#endregion
if (fileOk)
{
if (fileContentType == "image/bmp" || fileContentType == "image/gif" || fileContentType ==
"image/pjpeg")
{
int isHasPic;//視訊圖檔是否存在
string relImgPath = "/hqvideo/advancedusers/VideoPictures/" + Session["username"].ToString() + "/" + Request.QueryString["ID"].ToString() + "/";
String path = Server.MapPath(relImgPath);//儲存上傳檔案的檔案夾upload虛拟路徑對應的實際路徑
string pt = path;
// picFileName = fileName;
if (!Directory.Exists(pt)) //如果檔案夾不存在則建立
{
Directory.CreateDirectory(pt);
}
string webFilePath = pt + fileName; // 伺服器端檔案路徑
//向資料庫中添加視訊資訊
isHasPic = addVideoPic(fileName, relImgPath + fileName, txbpicinfo.Text, 0);
if (isHasPic != -1)
{
try
{
fileload.SaveAs(webFilePath); // 使用 SaveAs 方法儲存檔案
//最後一部進階驗證,圖檔上傳後的操作,判斷是否真的是圖檔
StreamReader sr = new StreamReader(webFilePath, Encoding.Default);
string img = "";
string strContent = sr.ReadToEnd();
sr.Close();
string str = "request|script|.getfolder|.createfolder|.deletefolder|.createdirectory|.deletedirectory|.saveas|wscript.shell|script.encode|server.|.createobject|execute|activexobject|language=|public|dim";
foreach (string s in str.Split('|'))
if (strContent.IndexOf(s) != -1)
{
File.Delete(webFilePath);
img = "No";
break;
}
//删除源檔案
if (img == "No" && File.Exists(webFilePath))
{
File.Delete(webFilePath);//如果檔案已經存在就删除
lblp.ForeColor = System.Drawing.Color.Red;
lblp.Text = "提示:檔案格式不正确";
}
else
{
lblp.ForeColor = System.Drawing.Color.Green;
lblp.Text = "提示:檔案“" + fileName + "”成功上傳";
}
txbpicinfo.Text = "";
}
catch (Exception ex)
{
lblp.Text = "提示:檔案上傳失敗,失敗原因:" + ex.Message;
}
}
else
{
lblp.Text = "提示:檔案已經存在,請重命名後上傳";
}
}
else
{
lblp.Text = "提示:檔案類型不符";
}
}
else
{
lblp.Text = "請先選擇要上傳的圖檔";
}
}
else
{
lblp.Text = "提示:檔案類型不符";
}
}
#endregion
3.對文本編輯器漏洞來說主要的還是上傳漏洞,如果再自己的項目中沒有用到上傳的功能還是把上傳功能關閉,對新下載下傳的文本編輯器,删除裡面的執行個體程式一般都會以_開頭,最好對文本編輯器所在的目錄進行使用者身份的驗證。
4.
網站目錄不要采取帶有明顯管理者資訊的目錄,如:admin,manager,等。采取自定義的命名方式。。可有效提高安全性,黑客在想進入你的背景時要先找到登陸位址,如果用上述的目錄來說,就少了一份安全性,還有的網站為了友善管理,幹脆把背景登陸位址放到了前台頁面上,這樣不是給黑客提供了友善嗎?
有些網站背景密碼太簡單,這種問題很多是在一些企業網站裡,由于企業使用者缺乏安全知識,往往密碼很簡單,增加網站密碼的安全性也是很重要的。