12

Google turns up all sorts of discussions on sanitizing queries for web access but I'm not finding anything addressing what I'm concerned with:

Sanitizing user input data in a c# program. This must be done by a reversible transformation, not by removal. As a simple example of the problem I don't want to mangle Irish names.

What's the best approach and is there any library function that does it?

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
  • 7
    Do you mean passing data that might contain apostrophes to a SQL query? If you use SQL Parameter objects, that shouldn't be a problem. You'll get your sanitization, and any significant characters in your data should be properly escaped. – Robert Harvey Aug 13 '10 at 17:53
  • 1
    Agreed, parameterized queries is the way to go. – driis Aug 13 '10 at 17:57
  • I only generate SQL queries through my business logic. – Jeroen Aug 13 '10 at 18:11
  • @RobertHarvey, sql parameter is not enough. Entering apostrophe returns SqlException: "Unclosed quotation mark after the character string ')'" – usefulBee Sep 02 '15 at 16:10
  • @usefulBee Anything with an apostrophe needs to be in a parameter. – Loren Pechtel Mar 17 '19 at 23:41

2 Answers2

10

It depends on what SQL Database you are using. For instance if you want a single quote literal in MySQL you need to use a backslash, Dangerous: ' and an escaped escaped character literal: \'. For MS-SQL things are completely different, Dangerous: ' escaped:''. Nothing is removed when you escape data in this fashion, it a way of representing a control character such as a quote mark in its literal form.

Here is an example of using parameterized queries for MS-SQL and C#, taken from the Docs:

private static void UpdateDemographics(Int32 customerID,
    string demoXml, string connectionString)
{
    // Update the demographics for a store, which is stored 
    // in an xml column. 
    string commandText = "UPDATE Sales.Store SET Demographics = @demographics "
        + "WHERE CustomerID = @ID;";

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(commandText, connection);
        command.Parameters.Add("@ID", SqlDbType.Int);
        command.Parameters["@ID"].Value = customerID;

        // Use AddWithValue to assign Demographics.
        // SQL Server will implicitly convert strings into XML.
        command.Parameters.AddWithValue("@demographics", demoXml);

        try
        {
            connection.Open();
            Int32 rowsAffected = command.ExecuteNonQuery();
            Console.WriteLine("RowsAffected: {0}", rowsAffected);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

For MySQL i am not aware of a parameterized query library you can use. You should use mysql_real_escape_string() or opointally you could use this function.:

public static string MySqlEscape(this string usString)
{
    if (usString == null)
    {
        return null;
    }
    // SQL Encoding for MySQL Recommended here:
    // http://au.php.net/manual/en/function.mysql-real-escape-string.php
    // it escapes \r, \n, \x00, \x1a, baskslash, single quotes, and double quotes
    return Regex.Replace(usString, @"[\r\n\x00\x1a\\'""]", @"\$0");
}
rook
  • 66,304
  • 38
  • 162
  • 239
  • 1
    I realize this is an older post, but PHP [5.0+] does support parametrized queries through both the MySQLi (http://php.net/manual/en/book.mysqli.php) and the PDO libraries (http://php.net/manual/en/book.pdo.php). – Tieson T. Jun 19 '12 at 09:52
  • @Tieson T. and adodb, and parametrized queries is the best choice. – rook Jun 19 '12 at 17:42
  • 1
    fyi, mysql_real_escape_string is deprecated – Owen Johnson Apr 22 '13 at 18:29
  • this sounds nice, I do it whenever I can, but occasionally, I can't use parameters because of performance issues with Parameter Sniffing (my tables are huge) so I'm forced to do hard-coded SQL. Any advice on how to sanitize my SQL? – Gabriel Espinoza Jan 10 '18 at 14:21
  • @Gabriel Espinoza consider using an ORM. No one is stopping you using manual input validation, just make sure to test your code. – rook Jan 10 '18 at 22:48
0

Use a properly constructed DAL with SQL Parameter objects handed to stored procedures and you don't have to worry about this. Implement business objects and dal to abstract the user input enough that it isn't executed as SQL but rather recognized as values. examples are fun:

public class SomeDal
{
    public void CreateUser(User userToBeCreated)
    {
        using(connection bla bla)
        {
            // create and execute a command object filling its parameters with data from the User object
        }
    }
}

public class User
{
    public string Name { get; set; }
    ...
}

public class UserBL
{
    public CreateUser(User userToBeCreated)
    {
        SomeDal myDal = new SomeDal();
        myDal.CreateUser(userToBeCreated);
    }
}

public class SomeUI
{
    public void HandleCreateClick(object sender, e ButtonClickEventArgs)
    {
        User userToBeCreated = new User() { Name = txtName.Text };
        UserBL userBl = new UserBL();
        userBl.CreateUser(userToBeCreated);
    }
}
Jimmy Hoffa
  • 5,909
  • 30
  • 53
  • I see parematerized commands are the way to go but your example code has nothing to do with them! – Loren Pechtel Aug 13 '10 at 20:26
  • @Loren Pechtel: The comment says to use them, but moreover you want your users input filling a business object like User which acts as the transport to the dal which creates the commands and parameters. This abstraction seperates users from DB that much more for enhanced safety as you can create a UserValidator and other such things to make their input not just safe from SQL injection, but safe from invalid values as well. – Jimmy Hoffa Aug 13 '10 at 20:31
  • I agree you need a layer that checks the validity etc but that's separate from keeping the system from choking on Mr. O'Neil. – Loren Pechtel Aug 14 '10 at 04:51
  • Some SQL API's expose absolutely no way to parameterize statements. In my experience, such systems are not usually full-fledged database systems, but rather products that provide an SQL API as an afterthought. For example, EMC Documentum has an ANSI SQL variant called DQL with no documented way of avoiding SQL injection. – Ronnie Overby Jul 18 '17 at 15:54