2015-01-07 3 views
0

Привет Я довольно новичок в MVc и C# Мне было интересно, могу ли я использовать модель безопасности для предотвращения инъекций SQL? Я создал модель, которая содержит переменные, которые мы получаем из ввода клиента, а затем формирует из них инструкцию SQL. Мне было интересно, достаточно ли встроенной безопасности в MVC для предотвращения инъекций SQL? Пожалуйста, взгляните на код, и все предложения приветствуются.MVC 4 SQL string injection Security

Модель

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace DataBaseTest.Models 
{ 
    public class BedroomModel 
    { 
    public string YrBlt1 { get; set; } 
    public string YrBlt2 { get; set; } 
    public string TotLivArea1 { get; set; } 
    public string TotLivArea2 { get; set; } 
    public string LotArea1 { get; set; } 
    public string LotArea2 { get; set; } 
    public string Bedrooms { get; set; } 
    public string SalePrice1 { get; set; } 
    public string SalePrice2 { get; set; } 
    public string SaleDate { get; set; } 
    public string AssesVal1 { get; set; } 
    public string AssesVal2 { get; set; } 
    public string Style { get; set; } 
    public string ArchStyle { get; set; } 
    public string TaxUnit { get; set; } 

    // Criteria added during SQL Queries 
    public string YearBuilt { get; set; } 
    public string LivingArea{ get; set; } 
    public string LotArea { get; set; } 
    public string SalePriceA { get; set; } 
    public string SaleDateA { get; set; } 
    public string AssesVal { get; set; } 
    public string StyleA { get; set; } 
    public string ArchStyleA { get; set; } 
    public string ParcelId { get; set; } 
    public string QuickRefId { get; set; } 
    public string TaxunitA { get; set; } 
    public string Address { get; set; } 
    public string ValCode { get; set; } 
    public string BedroomA { get; set; } 

Тогда наш SQL

[HttpPost] 
    public ActionResult Index(DataBaseTest.Models.BedroomModel user,DataTable dtFindResults) 
    { 
     StringBuilder sbSQL = new StringBuilder(); 
     //// define a list of CustomerModel objects 
     DataSet tempDS = new DataSet(); 

     //string xSQL = "SELECT PropertyAddress,PropertyTypeDesc,PropertyID FROM KDOR_vwPropertyGeneral ORDER BY PropertyAddress"; 
     System.Data.SqlClient.SqlDataAdapter DbCmd = new System.Data.SqlClient.SqlDataAdapter(); 
     string sqlWhereCont = " WHERE "; 
     sbSQL.Append("SELECT "); 
     //sbSQL.Append(SessionHandler.AddressPointsPointsIDColumn + " AS PointsID,"); 
     sbSQL.Append("pg.PropertyNumberSearch,"); 
     sbSQL.Append("pg.QuickRefID,"); 
     sbSQL.Append("pg.PropertyAddress,"); 
     sbSQL.Append("crb.fmsstyle,"); 
     sbSQL.Append("srb.farchstyle,"); 
     sbSQL.Append("pt.TransferValidityCode,"); 
     sbSQL.Append("pg.TaxingUnitGroupCode,"); 
     sbSQL.Append("pt.Price,"); 
     sbSQL.Append("pt.SaleDate,"); 
     sbSQL.Append("crb.fyrblt,"); 
     sbSQL.Append("crb.vResBldgDep_tla_value,"); 
     sbSQL.Append("lm.facres,"); 
     sbSQL.Append("crb.frmbed"); 
     sbSQL.Append(" FROM KDOR_vwPropertyGeneral pg "); 
     sbSQL.Append(" Left Join cama_ResBldg crb ON pg.PropertyID = crb.PropertyID And pg.AdHocTaxYear = crb.AdHocTaxYear "); 
     sbSQL.Append(" Left Join sales_ResBldg srb ON pg.PropertyID = srb.PropertyID"); 
     sbSQL.Append(" Left Join KDOR_vwPropertyTransfer pt On pg.PropertyID = pt.PropertyID"); 
     sbSQL.Append(" Left Join cama_LandMkt lm ON pg.PropertyID = lm.PropertyID And pg.AdHocTaxYear = lm.AdHocTaxYear"); 
     if (!string.IsNullOrEmpty(user.YrBlt1)||!string.IsNullOrEmpty(user.YrBlt2)) 
     { 
      //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'"); 
      //sqlWhereCont = "AND "; 
      sbSQL.Append(sqlWhereCont +"crb.fyrblt >="+ user.YrBlt1+ " And crb.fyrblt <= " + user.YrBlt2); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.TotLivArea1) || !string.IsNullOrEmpty(user.TotLivArea2)) 
     { 
      //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'"); 
      //sqlWhereCont = "AND "; 
      sbSQL.Append(sqlWhereCont + "crb.vResBldgDep_tla_value >=" + user.TotLivArea1 + " And crb.vResBldgDep_tla_value <= " + user.TotLivArea2); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.LotArea1) || !string.IsNullOrEmpty(user.LotArea2)) 
     { 
      //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'"); 
      //sqlWhereCont = "AND "; 
      sbSQL.Append(sqlWhereCont + "lm.facres >=" + user.LotArea1 + " And lm.facres <= " + user.LotArea2); 
      sqlWhereCont = "AND "; 
     } 

     if (!string.IsNullOrEmpty(user.Bedrooms)) 
     { 
      sbSQL.Append(sqlWhereCont + "crb.frmbed = '" + user.Bedrooms + "'"); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.SalePrice1) || !string.IsNullOrEmpty(user.SalePrice2)) 
     { 
      //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'"); 
      //sqlWhereCont = "AND "; 
      sbSQL.Append(sqlWhereCont + "pt.Price >=" + user.SalePrice1 + " And pt.Price <= " + user.SalePrice2); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.SaleDate)) 
     { 
      sbSQL.Append(sqlWhereCont + "pt.SaleDate = '" + user.SaleDate + "'"); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.AssesVal1) || !string.IsNullOrEmpty(user.AssesVal2)) 
     { 
      //sbSQL.Append(sqlWhereCont +"PropertyAddress = '" + user.Address + "'"); 
      //sqlWhereCont = "AND "; 
      sbSQL.Append(sqlWhereCont + "crb.vResBldgDep_tla_value >=" + user.AssesVal1 + " And crb.vResBldgDep_tla_value <= " + user.AssesVal2); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.Style)) 
     { 
      sbSQL.Append(sqlWhereCont + "crb.fmsstyle = '" + user.Style + "'"); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.ArchStyle)) 
     { 
      sbSQL.Append(sqlWhereCont + "srb.farchstyle = '" + user.ArchStyle + "'"); 
      sqlWhereCont = "AND "; 
     } 
     if (!string.IsNullOrEmpty(user.TaxUnit)) 
     { 
      sbSQL.Append(sqlWhereCont + "pg.TaxingUnitGroupCode = '" + user.TaxUnit + "'"); 
      sqlWhereCont = "AND "; 
     } 
     sbSQL.Append(" ORDER BY "); 
     sbSQL.Append(" pg.QuickRefID "); 


     //// populate a list of CustomerModel objects from database 
     string MyConnectionString = ConfigurationManager.ConnectionStrings["WLConnection"].ConnectionString; 
     System.Data.SqlClient.SqlConnection cnn = new System.Data.SqlClient.SqlConnection(MyConnectionString); 
     System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sbSQL.ToString(), cnn); 
     cmd.CommandTimeout = 30000; 
     DbCmd.SelectCommand = cmd; 
     DbCmd.Fill(tempDS, "ResultSet"); 
     DataTable resultSet = tempDS.Tables["ResultSet"]; 
     var vm = new List<BedroomModel>(); 
     foreach (DataRow dr in tempDS.Tables[0].Rows) 
     { 
      vm.Add(new BedroomModel 
      { 
       BedroomA = dr.ItemArray[12].ToString(), 
       YearBuilt = dr.ItemArray[9].ToString(), 
       LivingArea = dr.ItemArray[7].ToString(), 
       LotArea = dr.ItemArray[3].ToString(), 
       SaleDateA = dr.ItemArray[8].ToString(), 
       SalePriceA = dr.ItemArray[10].ToString(), 
       AssesVal = dr.ItemArray[5].ToString(), 
       StyleA = dr.ItemArray[3].ToString(), 
       ArchStyleA = dr.ItemArray[4].ToString(), 
       ParcelId = dr.ItemArray[0].ToString(), 
       QuickRefId = dr.ItemArray[1].ToString(), 
       TaxunitA = dr.ItemArray[6].ToString(), 
       Address = dr.ItemArray[2].ToString(), 
       ValCode = dr.ItemArray[5].ToString(), 


      }); 
      } 
     //DbCmd.Fill(dtFindResults); 
     //var x = dtFindResults.Rows.Count; 
     cnn.Close(); 
     return View("Result",vm); 
     //// return the list of CustomerModel objects to our View 
     //return View("Result", resultSet); 
     //return View(ViewBag.data); 
    } 
+5

Одним словом, * no *. Используйте параметризованные запросы. Всегда. Вы можете построить запрос сам по себе динамически на основе пользовательского ввода, но значения, исходящие от пользователя, всегда должны передаваться как параметры, а не конкатенироваться непосредственно в запросе. –

+3

Вы строите строку SQL на лету на основе пользовательского ввода. Это фактический пример того, как * not * защищать от SQL-инъекции. –

+0

любые предложения о том, как построить его динамически и безопасно? @PrestonGuillot –

ответ

5

параметризованные запросы являются обязательными. Однако это не мешает вам создавать динамические запросы, вам просто нужно подойти по-другому.

Это нормально для принятия решений на основе ввода пользователем; это не штраф, чтобы объединить эти значения в запрос.

Быстрый пример:

using(IDbCommand cmd = GetCommand()) 
{ 
    string lotSize = "12345"; 
    bool includeLotSize = !string.IsNullOrWhiteSpace(lotSize); 

    var sb = new StringBuilder(); 
    sb.AppendLine("SELECT Col1, Col2 FROM dbo.Foo"); 

    // you might also vary the columns returned based on what the user asked for 

    if(includeLotSize) 
    { 
     sb.AppendLine("WHERE LotSize = @LotSize"); 

     // The query will expect the lot size, so add a parameter here to pass 
     // the lot size value. 
     cmd.Parameters.Add(new SqlParameter("LotSize", lotSize)); 
    } 
} 

Обратите внимание, что многие из ваших строковых свойств выглядят как они могли бы быть более конкретный тип (целый, дробный, ИНТ, указывающий на поиск в базе данных, и т.д.). Это не препятствует внедрению SQL, но его можно использовать для проверки (а также сделать ваши модели просмотра более чистыми).

Также обратите внимание, что существует множество способов подключения к базе данных в .Net, но убедитесь, что вы правильно распоряжаетесь своими ресурсами (обратите внимание на добавленный вами оператор using).

+0

Спасибо Тиму, это первый раз, когда я работаю в Интернете, и я не думаю, что мы будем атакованы, но я не хочу рисковать, могу ли я использовать модель для ввода sql? строка stringizeize = user.lotsize; –

+1

Вы можете продолжать использовать модель для сбора пользовательского ввода. Дело в том, что только вход пользователя в базу данных передается как параметр, а не как строка. Вы должны иметь возможность использовать шаблон в своем ответе для замены кода, например, 'sbSQL.Append (sqlWhereCont +" crb.fyrblt> = "+ user.YrBlt1 +" и crb.fyrblt <= "+ user.YrBlt2);' –

+0

Tim если я использую строку в методе, не мог бы все-таки разрешить SQL-инъекции, так как я все равно получаю пользовательский ввод? @Tim Medora –