Dapper giving unhandled exception when trying to insert data to database - c#

I'm writing a C# plugin for Autodesk Navisworks that will iterate through a bunch of 3D elements and write their properties (Category and Family of the element for now) into an Azure database.
I'm using Dapper as ORM. When I try to insert the data in the database Navisworks crashes giving an unhadled exception.
I tried the ssame procedure with plain sql and everything works fine so I'm quite sure it's Dapper's Execute function giving the exception.
This is my object:
internal class NavisTest
{
public string Category { get; set; }
public string Family { get; set; }
public NavisTest(string category, string family)
{
Category = category;
Family = family;
}
}
This is the sql command:
const string navisTestSql = "insert into NavisTest " +
"(Category, Family) " +
"values (#category, #family);";
And this is the main logic:
using (SqlConnection connection = new SqlConnection(
NavisDbSettings.ConnectToDB().ConnectionString))
{
// Open connection to db
connection.Open();
using (SqlTransaction transaction = connection.BeginTransaction())
{
NavisTest navisTest = new NavisTest(
"Wall",
"Concrete Wall 01");
connection.Execute(NavisDbSqlCommands.navisTestSql, navisTest, transaction: transaction);
// Commit database transaction
transaction.Commit();
}
}
So when this runs Navisworks just crashes, but if I do with a normal SqlCommand everything works fine.
(Also I basically copied the code to insert to the db from another application I have that works perfectly)
Also, if I try to surround the code in a try-catch clause, it still fails (it's an unhandled exception).
I really don't understand what I'm doing wrong.
Any ideas?

Related

How to Fix CA2100: SQL security vulnerability In Legacy code when SQL query is coming to function from outside of it?

While working on legacy code, I ran into Specific scenario and made a dummy example to show the issue to ask for any suggestions. I get following error:
`
Program.cs(37,1) : warning : CA2100 : Microsoft.Security : The query string passed to 'OleDbCommand.CommandText.set(string)' in 'Program.Read(OleDbConnection, string)' could contain the following variables 'sqlQuery'. If any of these variables could come from user input, consider using a stored procedure or a parameterized SQL query instead of building the query with string concatenations.
My Code is:
class Program
{
static void Main ()
{
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Newfolder\database1.mdb";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
try
{
connection.Open();
string strsql = "SELECT * FROM Table1";
Read(connection,strsql);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
static void Read (OleDbConnection connection,string sqlQuery)
{
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = sqlQuery;
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader["PName"]);
}
}
}
Now I cannot go with the solution to suppress warning. There are several complicated situations from which i get these warnings, this is just a dummy simple example to show workflow.
So although the query being executed is safe, but since it comes outside of the function, it asks me to changed it to parametrized query.
As in Read() function, although my input paramter sqlQuery is not from user, but it will come from outside as an input parameter and I cannot move sqlQuery code within the Read() function, it will always come from outside based on which certain decisions are made.
So what can I do to make this redundant warning disapper?
My dummy Access databse snapshot is this:
I have tried going through Microsoft official documentation on it, but i was not able to come up with solution

SQL request working fine in SQL Server Management Studio but returning an error when send with sqlCommand C#

I have this statement:
SELECT [nozzles].[nozzle_tag],[nozzles].[id]
FROM [dispensers]
INNER JOIN [nozzles]
ON [dispenser_id] = [dispensers].[id]
INNER JOIN (SELECT * FROM assets
WHERE [i4_Device_Name] = 'EH004T_SOURCE2'
AND [i4_site_name] = 'Les Loges - H2e Station (EH004R)')assets
ON [asset_id] = [assets].[id]
WHERE [dispenser_tag] ='Dispenser 2';
It works perfectly fine when I execute it inside SSMS.
The problem is, when run this SQL by using SQLcommand, I get an error with this message:
Incorrect syntax near 'Loges'.
I don't understand why.
The command above is extracted from a log file, it is exactly what is send using SQLCommand.
C# code is:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(HySoSQLCommandBuilder.GetAllNozzleOfDispenser(locationID, dispenserTag), connection))
{
logger.Info("SQL request {request}", HySoSQLCommandBuilder.GetAllNozzleOfDispenser(locationID, dispenserTag));
using (SqlDataReader reader = command.ExecuteReader())
{
try
{
while (reader.Read())
if (reader.HasRows)
{
list.Add(new nozzle((string)reader["nozzle_tag"], (int)reader["id"]));
}
}
catch { }
}
}
With HySoSQLCommandBuilder.GetAllNozzleOfDispenser() being fairly straight forward:
public static string GetAllNozzleOfDispenser(AssetLocationID assetLocation, string dispenserTag)
{
return $#"SELECT [nozzles].[nozzle_tag],[nozzles].[id]
FROM [dispensers]
INNER JOIN [nozzles]
ON [dispenser_id] = [dispensers].[id]
INNER JOIN (SELECT * FROM assets
WHERE [i4_Device_Name] = '{assetLocation.i4DeviceName}'
AND [i4_site_name] = '{assetLocation.i4SiteName}')assets
ON [asset_id] = [assets].[id]
WHERE [dispenser_tag] ='{dispenserTag}';";
}
None of the injected values are accessible from outside the code. They do not come form a editable field accessible from a user. If SQL injection happens, then that means that it is in the source, done by someone that worked on the code, and can already do whatever they want to the database without the need to encode an SQL injection.
changed the code so it uses SQLparameters instead and now it's working. I don't understand why it wasn't working and that annoy me alot, because fixing an issue without understanding it is not how it should work. but at least now it works.

SQL - Injection on Purpose in ASP.NET Core 2.1.7

I'm a college student and I'm in a class about computer security. I have a final project that I had to come up with so I decided to do a project where I create my own website and run a DoS attack and SQL Injection (I will also be doing a buffer overflow attack on my own VM). So I am creating a website using ASP.NET using Visual Studio 2019. I have not really worked with ASP.NET and I'm just trying to make a basic website. So far I have a webpage where you can view "Customers" and you can search for one. So I am creating this code so that I can SQL Inject and I understand the correct way to implement this. Here is my code so far
This a model class where my actual vulnerable SQL Command is being run
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Text;
namespace bullAndTrue.Models
{
public class CustomerContext
{
public string ConnectionString { get; set; }
public CustomerContext(string connectionString)
{
this.ConnectionString = connectionString;
}
private MySqlConnection GetConnection()
{
return new MySqlConnection(ConnectionString);
}
public List<Customer> GetCustomers(string name)
{
List<Customer> customerList = new List<Customer>();
using(MySqlConnection conn = GetConnection())
{
conn.Open();
MySqlCommand myCmd = new MySqlCommand("SELECT * FROM Customers WHERE firstName LIKE '%" + name + "%'", conn);
using(var reader= myCmd.ExecuteReader())
{
while(reader.Read())
{
customerList.Add(new Customer()
{
idCustomers = Convert.ToInt32(reader["idCustomers"]),
firstName = reader["firstName"].ToString(),
lastName = reader["lastName"].ToString(),
address = reader["address"].ToString()
});
}
}
}
return customerList;
}
}
}
Here we can see my command
SELECT * FROM Customers WHERE firstName LIKE '%userInput%'
is the vulnerable part. Here I should be able to input ';-- and get the list of all customers. Instead of getting a list of all customers I get an error instead (Which is awesome that there are security options but that's the whole point of this project is to skip security!)
Error:
MySql.Data.MySqlClient.MySqlException: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '--%'' at line 1'
I have been trying to figure out how to bypass this error and get the query I need. I have been trying to use different versions of dependencies but I can't figure out what is blocking me from doing the injection. Here are a list of my relative dependencies:
MySql.Data Version= 8.0.22
Microsoft.AspNetCore Version= 2.1.7
My server is running on an AWS instance and its running MySQL version 5.5 (Lowest I could go; Maybe this is the problem?)
This is my first time posting so hopefully I'm doing it right. If you need more information I will be happy to post it. Any help is appreciated!
In MySQL, the -- (double-dash) comment style requires the second dash
to be followed by at least one whitespace or control character (such
as a space, tab, newline, and so on). This syntax differs slightly
from standard SQL comment syntax, as discussed in Section 1.7.2.4,
“'--' as the Start of a Comment”
Ref: https://dev.mysql.com/doc/refman/8.0/en/comments.html

Usage of MySQL Parameter for creating new user

So I am using a MySQL Server version 8.0.16 and if I try to let dynamically create a new user, i do receive a Error message what says: >>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax. to use near '$password' at line 1<<.
What i can't understand, becouse if i replace the Parameters with the actual value and try it with the shell it works perfectly. I let my code connect as root so and checked if the connection is open what it is. So if I stepped into the code and checked if the parameters are correct everything looked fine. I also added >>'<< at the beginning and end of thext strings that should replace the parameters but it didn't changed the error or what happened.
public bool CreateNewUser(string name, string password, string host)
{
string query = "CREATE USER $name#$host IDENTIFIED BY $password;";
List<MySqlParameter> mies = new List<MySqlParameter>
{
new MySqlParameter("$name", name),
new MySqlParameter("$password", password),
new MySqlParameter("$host", host)
};
return InsertIntoQuery(query, mies);
}
//The InsertIntoQuery looks like this
private bool InsertIntoQuery(string sql, List<MySqlParameter> sqlParameters = null)
{
bool retBl = false;
try
{
using (var SqlConnection = new MySqlConnection(ConnectionStr))
{
SqlConnection.Open();
using (var cmd = new MySqlCommand(sql, SqlConnection))
{
if (sqlParameters != null)
foreach (var item in sqlParameters)
cmd.Parameters.AddWithValue(item.ParameterName, item.Value);
cmd.Prepare();
var retValNonQuery = cmd.ExecuteNonQuery();
retBl = (retValNonQuery > 0) ? true : false;
}
}
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.Message);
}
return retBl;
}
I would expect it to create a new user but it doesn't.
No, for CREATE USER command I don't think you can pass command parameter likewise. Rather substitute the value as is like below using string interpolation syntax.
string query = $"CREATE USER '{name}#{host} IDENTIFIED BY {password}";
For an older C# version consider using string.Format()
string query = string.Format("CREATE USER '{0}'#'{1}' IDENTIFIED BY '{2}'",name,host,password);
Per OP's comment: You can't cause it's not a DML operation. If you are worried about SQL Injection probably cause input value is coming from user input then you will have sanitize it someway and moreover if you observe the input are quoted.
Again, I would suggest that this kind of admin operation should go in a DB bootstrap script and not in your application code.

c# odbc update query doesnt work properly

Hi I'm having a lot of truble doing a program in c#
i have to connect to SQLANYWHERE 11 and do an update to a table
could u tell me where I'm wrong?
program go well until i reach the:
int number = wCommand.ExecuteNonQuery(); line
the program doesnt crash but tables get not updated
string dns = "Dsn=dattest;Uid=******;Pwd=******;";
OdbcDataReader reader;
OdbcCommand wCommand;
ODBCClass dst1 = new ODBCClass(dns);
queryins = "UPDATE dba.Sala_export_dati_macchina_produzione SET stato='p'";
// +"WHERE id_prd_lav_ord_lav='"+ id_prd_lav_ord_lav + "'";
wCommand = dst1.GetCommand(queryins);
int number = wCommand.ExecuteNonQuery();
Console.WriteLine("executed "+ number);
this is the odbc class that i'm using
public class ODBCClass
{
OdbcConnection oConnection;
OdbcCommand oCommand;
public ODBCClass(string DataSourceName)
{
oConnection = new OdbcConnection(DataSourceName);
try
{
oConnection.Open();
System.Diagnostics.Trace.WriteLine("Connessione stabilita con il database " + DataSourceName);
}
catch (OdbcException caught)
{
System.Diagnostics.Trace.WriteLine(caught.Message);
}
}
public void CloseConnection()
{
oConnection.Close();
}
public OdbcCommand GetCommand(string Query)
{
oCommand = new OdbcCommand
{
Connection = oConnection,
CommandText = Query
};
return oCommand;
}
public void Dispose()
{
oConnection.Close();
}
}
EDIT
just in case i've tried to change connection string with this pattern:
#"Driver={SQL Anywhere 11};DatabaseName=my_db_name;EngineName=my_server_name;uid=username;pwd=password;LINKs=tcpip(host=host_ip_address)"
and always the system gave me no error on connection in both cases
Ok guys that was kinda strange.
Let me explain the whole thing. I was doing that program for a customer that asked a software which could link my mysql db and a sybase db of another company.
The problem was that the DBMS of that company when is opened on the server block all kind of external editing to the db with which is connected.
So select query worked regularly but update and insert were blocked by that client...
I've passed 4 day with a perfect working program but that company didn't told me this "little" thing.
So be aware of DBMS they are cruel.

Categories

Resources