#眉標=VSTS2008、FxCop、SQL Injection #副標=Visual Studio Team System 2008實戰攻略(11) #大標=SQL Injection程式碼檢測 #作者=文/圖 歐宣修 ============= 程式1 DocumentExternallyVisibleMembers.cs public override TargetVisibilities TargetVisibility { get { return TargetVisibilities.ExternallyVisible; //…(1) } } public override ProblemCollection Check(Member member) { AssemblyNode assembly = member.DeclaringType. DeclaringModule.ContainingAssembly; bool assemblyHasDocComments; if (member.IsSpecialName) //…(2) { return this.Problems; } if (!processedAssemblies.TryGetValue(assembly. Name, out assemblyHasDocComments)) //…(3) { string path = Path.Combine(Path. GetDirectoryName(assembly.Location), Path.GetFileNameWithoutExtension(assembly. Location)) + ".xml"; if (File.Exists(path)) { XmlDocument doc = new XmlDocument(); doc.Load(path); foreach (XmlElement element in doc. SelectNodes("/doc/members/member")) //…(4) { string memberName = element.Attributes ["name"].Value; if (memberName.IndexOf(":") == 1) { memberName = memberName.Substring( 2); } documentedMemberIds.Add(memberName, element); } assemblyHasDocComments = true; } else { assemblyHasDocComments = false; } processedAssemblies.Add(assembly.Name, assemblyHasDocComments); } if (assemblyHasDocComments) //…(5) { string memberId = member.FullName; if (!documentedMemberIds.ContainsKey( memberId)) //…(6) { this.Problems.Add(new Problem(this. GetResolution())); } } return this.Problems; } ================ ===<反灰>============= Class1.cs /// /// Method1 Comments /// public void Method1() { } public void Method2() { } ================ ============= 程式2 SqlInjection.cs public override ProblemCollection Check(Member member) { if (member is Method) //…(1) VisitStatements(((Method)member).Body. Statements); else if (member is PropertyNode) { PropertyNode propNode = (PropertyNode) member; if (propNode.Setter != null) VisitStatements(propNode.Setter.Body. Statements); } return this.Problems; } public override void VisitExpression(Expression expression) { MethodCall methodCall; methodCall = expression as MethodCall; if (methodCall == null) return; //…(2) bool isSqlStatement = false; bool isCallHandleSqlParameter = false; foreach (Expression operand in methodCall. Operands) //…(3) { Literal literal = operand as Literal; if (isSqlStatement == false && literal != null) { string statement = literal.Value.ToString(). ToLower(); if (statement.IndexOf("select") >= 0 && statement.IndexOf("from") >= 0 && statement. IndexOf("where") >= 0) //…(4) { isSqlStatement = true; continue; } } MethodCall subMethodCall = operand as MethodCall; if (isSqlStatement && subMethodCall != null) { MemberBinding memberBinding = (MemberBinding)subMethodCall.Callee; //…(5) if (memberBinding.BoundMember.FullName. IndexOf("HandleSqlParameter") >= 0) //Pass isCallHandleSqlParameter = true; } } if (isSqlStatement && !isCallHandleSqlParameter) this.Problems.Add(new Problem(this. GetResolution(null))); } ================ ===<反灰>============= "select * from MyTable where Id = '" + param1 + "' "; Literal MethodCall Literal ================ ===<反灰>============= public void TestSql1(string param1) { string sql = "select * from MyTable where Id = '" + param1 + "' "; } public void TestSql2(string param1) { string sql2 = "select * from MyTable where Id = @Id "; } public void TestSql3(string param1) { string sql3 = "select * from MyTable where Id = '" + HandleSqlParameter(param1) + "' "; } ================