Security of printing SqlException.Message to console - c#

While i've been debugging my code, I've been writing the output to the console so that I can monitor the errors and sql output. Naturally to protect against sql injection I have parameterised the queries where needed. After reading some articles online regarding the methods by which some injection attacking programs work, I now question whether the below practice is a good idea anymore.
Consider the following method.
public void MyQuery(int item_id)
{
string sql = "SELECT * FROM table WHERE item_id = #id";
SqlCommand sqlQuery = new SqlCommand(sql,conn);
sqlQuery.Parameters.Add("#id", SqlDbType.Int).Value = item_id;
try
{
conn.Open();
sqlQuery.ExecuteNonQuery();
conn.Close();
}
catch (SqlException ex)
{
Console.WriteLine(sql);
Console.WriteLine(ex.Message);
}
}
on my dev machine the console output is fine - no risk here. But if i were to leave the code as it is now when the application was live, would that potentially open up other avenues to exploit?
Im aware that if i were to have done MessageBox.Show(ex.Message); that would certainly be bad due to it being in your face.

You're deploying a WinForms application that connects to a SQL Server with credentials that apparently allow the application to write to that SQL Server.
Leaking SQL errors to the console is the least of your worries.
A malicious user can simply use the credentials used by your application to execute arbitrary SQL on that server.
Anything you deploy on a client machine must be considered insecure. Leaking queries is not the problem (the user could decompile your application or check its resources and inspect the SQL strings), the problem is that the client has a direct database connection.
If you want to prevent the client to know where the database is, what its credentials are and what queries your application executes, you must remove all this code from your application, and let the database stuff happen on a different machine altogether. You can then talk to this machine through a web service, for example.
Then the web service handles authentication, and refuses to execute any action for a user that isn't authenticated.

Related

Can not connect to Sql database in C# asp mvc application with Entity Framework BUT the same code works with Winform application

First of all, please excuse me if it sounds too rooky. I consider myself novice in MVC applications.
I have ran into a strange problem and there does not seem to be any way out of this, at least so far..I have looked everywhere and left no stone unturned to get it worked. Finally I turned to this forum.
This is my first post, so any mistakes please overlook and guide me.
The problem is multifaceted...
The High Level Details...
I have created a C# ASP MVC Web Application waiting to be uploaded on a Remote Server (Client Machine)
The application uses Entity Framework - Code First approach
Connects to the database with Windows Authentication system
Scene1: Where the application worked
I have tested the application on my machine and it worked flawlessly.
I have Express edition of Sql Server Management Studio installed on my system.
Scene2: Where the application failed. The Problem - Big Picture
It works great on my system but while testing it on the Remote Server it crashes
The application fails to connect to the Remote Server Sql Database. As soon as it tries to connect to the database, it crashes with an error message "Login failed for user '<UserName>."
I have checked everything in the connection string - like -
Data source name is correct
Initial Catlog also points at the correct database name
Integrated Security = true
There is no UserID or password mentioned
Connection string worked great on my system. But it does work on the Client Machine and shows the error above.
Connection string is:
connectionString="Data Source=RemoteComputerName;Initial Catalog=DatabaseName;Integrated Security=True; MultipleActiveResultSets=true"
I am not able to figure out exactly what is causing the error - Is it my code or Is it the Sql Server database settings - permissions.
Since the connection worked on my local machine, which means the code is correct
In order to check whether sql server permissions are working..I have created partial 'test connection application' in WINFORM and uploaded on the Server, this time the code works and read all the table data.
but when I try to connect in MVC project it shows the error..."Login failed for user...".
I'm totally confused what works in WINFORM fails in MVC.
Database permissions must be right because when tried to access it using WINFORM it worked.
please let me know if I have missed to provide any details in this post.
Any help is highly appreciated!!!
Thank You.
Please show your connection string. (you can block out any real passwords, actual server names, actual db names).
Since you mention "Integrated Security = true"..........then you have to be aware of which Identity is running the process (the website or the winforms.exe)
When running as winforms app, you are running as "you" (most likely). As in, the logged in user to the windows o/s.
When running under IIS, you are running under the Identity associated with the App Pool you are using..which most likely is NOT you, but rather a service account.
Your service-account does not have access to the sql-server.
You can read in depth here: https://support.microsoft.com/en-us/help/4466942/understanding-identities-in-iis#:~:text=ApplicationPoolIdentity%3A%20When%20a%20new%20application,also%20a%20least%2Dprivileged%20account.
You can show this......by catching an exception, and then something like this:
You can replace ArithmeticException with whatever, I'm just showing "adding info" to a caught exception and rethrowing.
try
{
// some sql server access code
}
catch(Exception ex)
{
throw new ArithmeticException("What is the real IIdentity: " + this.FindIIdentity(), ex);
}
private string FindIIdentity()
{
try
{
//'Dim user As WindowsPrincipal = CType(System.Threading.Thread.CurrentPrincipal, WindowsPrincipal)
//'Dim ident As IIdentity = user.Identity
string returnValue = string.Empty;
WindowsIdentity ident = WindowsIdentity.GetCurrent();
returnValue = ident.Name;
try
{
returnValue += " on " + System.Environment.MachineName;
} catch (Exception ex)
{}
return returnValue;
} catch (Exception ex)
{
return "Error Finding Identity";
}
}
IIS screenshots

Extremely slow mysql connection establishment only when called from code

I am currently trying to do something that should be simple and straight-forward - connect to a database server, run a query, see if I get anything back and if so send it back to the user. This is the code I'm using to do it:
MySqlDataReader reader = MySqlHeaper.ExecuteReader(connectionString, $"SELECT * FROM table WHERE insertDateTime > '{DateTime.Now.AddSeconds(-1800).ToString("yyyy-MM-ddTHH:mm:ss")}'";
I have also tried this with a MySqlCommand and MySqlConnection object pair, and either way the result is the same - it takes approximately 7100ms to connect to the MySql server. I know that sounds like a problem that should be on ServerFault, but my testing tells me otherwise. When I use the command line MySql client to connect to my database server using exactly the same credentials and run exactly the same query I get my connection established and my data back in nothing flat. I don't know at this stage if it's a server setting or not, but here's what I've tried so far:
Rebooting the server
Restarting the MySQL server
Setting the skip_name_resolve setting to 1 in order to prevent reverse name lookups on connect
Using alternative means of querying the server (mysql command line client and MySQL Workbench)
Opening all AWS IAM permissions on the RDS instance to allow everything from the server
Nothing seems to be making any difference, so I'm at a loss to explain this terrible performance. It's also only happening when I open the connection. Running queries, inserts, what have you is lightning fast. Any suggestions anyone might have would be most helpful.
I would not expect IAM permissions to have any impact on performance. I would expect them to be either successful or not successful.
I would execute some diagnostic protocols to get more information.
1) Try a subsequent query, to see if it is an issue with the stack being initialized. Are subsequent queries faster?
2) Try a query that is just an identity query. Something that doesn't require any sort of IO.
3) Try a query from a different platform (maybe a scripting language like ruby or php)
Once you answer those it should help you narrow it down.
This is most likely caused by Connector/NET executing a slow WMI query to query connection attributes when opening the connection; this is logged as MySQL bug 80030.
As far as I know, this isn't fixed in newer versions of the driver, but you can work around it by switching to MySqlConnector, an OSS MySQL ADO.NET library.

.NET SQL Server connection issue - Maybe connection pool related

I am having a very strange problem and am hoping someone out there has had a similar experience.
My companies application for one client is getting "banned" from the SQL Server at the beginning of our application. The behavior is strange. I'll write it out in point form.
SQL Connections are created, data is retrieved, the connections are closed, talk to another datasource and then denied access to SQL Server.
Here's the long winded version:
.NET application connects to database multiple times. Gets some data, does some work. It then goes to get some more data and then gets an error that the "SQL Server cannot be found or access is denied". If the process is started over again without re-starting the app then no more connections are able to be made to SQL Server. All new connections result in "SQL Server cannot be found or access is denied". If the application is restarted then it will repeat the above process.
This is the first in 5 years of my experience with the software to have this problem. The application does have code written in Delphi 7. The dephi 7 / VBA code has not issues. My .NET code that performs the actual query looks like:
protected abstract DbConnection GetConnection();
protected abstract DbDataAdapter GetDataAdapter(DbCommand cmd);
protected abstract DbCommand GetCommand(DbConnection conn, String sql);
protected abstract DbCommandBuilder GetCommandBuilder(DbDataAdapter adapter);
public virtual DataTable Query(string sql)
{
var dt = new DataTable();
using (var conn = GetConnection())
{
try
{
using (var cmd = GetCommand(conn, sql))
{
using (var adapter = GetDataAdapter(cmd))
{
adapter.Fill(dt);
}
}
}
catch (Exception ex)
{
throw new SqlStatementException(sql, ex);
}
}
return dt;
}
It is my own quite and dirty DAL. When it is used it is using an OleDbConnection.
Note: Due to legacy code the connection string is configured for OleDbConnection. After taking a moment to review my code I do have the ability to change the connection type to SqlConnection. I haven't tried that yet.
On the client's machine I have not been able to reproduce the issue outside of the main application. I tried creating a little app that would make 100 calls back to back using the format above with an OleDbConnection but it executed successfully.
The failure in the main app happens in the same spot. That should give me a clue except I cannot make sense of it since it is making duplicate query, getting the same data. But I will say that the application talks to two data sources and transfers data from one to the other. Before it does the transfer it does some validation on the sources. So it talks to another database (proprietary file based) via ODBC and comes back successfully and then fails when trying to talk to SQL Server through OleDbConnection.
My suspicion is something is happening in the connection pool. That is causing a failure which in turns causes a denial of access.
Other interesting points. All worked fine for about a year, client got a new machine a couple of months ago, all work fine and then suddenly stopped. I put the application on another machine at the client's site and all worked well for a week and then the same issue appeared. We turned everything off on the client's machine but the issue persisted. I thought firewall but no luck there.
Any assistance is greatly appreciated.
Was gonna put this in a comment, but it got too big :-)
I see your connection-creating methods are abstract. This of course means that derivatives can do all sorts of bad things when they create the connection. I'd look there first.
One thing I found in a similar situation...if you're doing something in the code that creates the connection that makes the connection string unique, you won't be reusing those pooled connections. So...doing something like adding an "App=MyApp" + an incrementing number, date/time, or guid, it will destroy your ability to use pooled connections. When this happened to me, it took me forever to figure it out.
If your application was "slow enough" in the past, such that "old" pooled connections fall out of the pool, you might never see a problem...but then, say a customer gets hot new hardware...and blam...weird errors from nowhere! This might not be what's happening to you, but maybe it will give you some ideas about where to look. Good luck!

How to insert data in SQL Server in an Android application

In order to insert data into an SQL Server database on an Android application do I simply need to execute a query ? I have the following code :
public int SaveUser(User user)
{
int r;
lock (locker)
{
connection = new SqlConnection("Data Source=" + path + ";Initial Catalog=DB;User ID=sa;Password=***********th");
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "INSERT INTO tblUsers (Username, UserEmail, FirstName, LastName, FacebookID) VALUES (#Username, #UserEmail, #FirstName, #LastName, #FacebookID)";
command.Parameters.AddWithValue("#UserEmail", user.Email);
command.Parameters.AddWithValue("#Username", user.UserName);
command.Parameters.AddWithValue("#FirstName", user.FName);
command.Parameters.AddWithValue("#LastName", user.LName);
command.Parameters.AddWithValue("#FacebookID", user.FacebookID);
r = command.ExecuteNonQuery();
}
connection.Close();
return r;
}
}
And I get the following information from the facebook-sdk login, so I simply need to execute that query in order to insert the data to the database? Is it right to use the sa account? Is inserting data into a database on an Android application done the same way it's done on a Windows application ? Until now I used the Microsoft Access and it was horribly simple and easy, but now as I moved on to SQL Server 2008 I'm kinda clueless.
Ok this is not really a proper answer, but I did not want to keep making comments.
It seems to me that what you really want is a DB on a server and not in your android app, because if users are added in massive amounts then those users cannot be coming from the android OS itself, they must be coming from an external source, ie. the internet.
So if they are coming from the internet you need a central storage location, which is your server. An ASP.NET server hosting a SQL Server instance.
You will need a domain name, and a hosting solution. Use either MVC controllers or WebAPI to set up your website and/or services that interact with your SQL Server instance. I would recommend you use Entity Framework as well it would make your life a lot easier.
You have many hosts, AZURE is one, but its expensive. But the least it will cost you is something like £8 a month to host databases.
You would design your MVC website+services, or WebAPI (just services) using Visual Studio and use the settings the server host gives you to upload it.
Once the services are up then its a simple matter of making HTTP get/post calls to your server to get and set data in your database, and your android APP will act like a client.
I did this whole thing a week ago for a very simple scenario and it works well.
You would have to follow best practices on how to secure your web service, using some sort of authentication mechanism so only authorised users can access your data.
I hope the above gives you a general idea of how it can be accomplished. Its very high level and you will have to google each stage, but its pretty simple if you know some basics.
That's all I can say...

SQL Server: Could not find prepared statement with handle x

Recently our QA team reported a very interesting bug in one of our applications. Our application is a C# .Net 3.5 SP1 based application interacting with a SQL Server 2005 Express Edition database.
By design the application is developed to detect database offline scenarios and if so to wait until the database is online (by retrying to connect in a timely manner) and once online, reconnect and resume functionality.
What our QA team did was, while the application is retrieving a bulk of data from the database, stop the database server, wait for a while and restart the database. Once the database restarts the application reconnects to the database without any issues but it started to continuously report the exception "Could not find prepared statement with handle x" (x is some number).
Our application is using prepared statements and it is already designed to call the Prepare() method again on all the SqlCommand objects when the application reconnects to the database. For example,
At application startup,
SqlCommand _commandA = connection.CreateCommand();
_commandA.CommandText = #"SELECT COMPANYNAME FROM TBCOMPANY WHERE ID = #ID";
_commandA.CommandType = CommandType.Text;
SqlParameter _paramA = _commandA.CreateParameter();
_paramA.ParameterName = "#ID";
_paramA.SqlDbType = SqlDbType.Int;
_paramA.Direction = ParameterDirection.Input;
_paramA.Size = 0;
_commandA.Parameters.Add(_paramA);
_commandA.Prepare();
After that we use ExceuteReader() on this _commandA with different #ID parameter values in each cycle of the application.
Once the application detects the database going offline and coming back online, upon reconnect to the database the application only executes,
_commandA.Prepare();
Two more strange things we noticed.
1. The above situation on happens with CommandType.Text type commands in the code. Our application also uses the same exact logic to invoke stored procedures but we never get this issue with stored procedures.
2. Up to now we were unable to reproduce this issue no matter how many different ways we try it in the Debug mode in Visual Studio.
Thanks in advance..
I think with almost 3 days of asking the question and close to 20 views of the question and 1 answer, I have to conclude that this is not a scenario that we can handle in the way we have tried with SQL server.
The best way to mitigate this issue in your application is to re-create the SqlCommand object instance again once the application detects that the database is online.
We did the change in our application and our QA team is happy about this modification since it provided the best (or maybe the only) fix for the issue they reported.
A final thanks to everyone who viewed and answered the question.
The server caches the query plan when you call 'command.Prepare'. The error indicates that it cannot find this cached query plan when you invoke 'Prepare' again. Try creating a new 'SqlCommand' instance and invoking the query on it. I've experienced this exception before and it fixes itself when the server refreshes the cache. I doubt there is anything that can be done programmatically on the client side, to fix this.
This is not necessarily related exactly to your problem but I'm posting this as I have spent a couple of days trying to fix the same error message in my application. We have a Java application using a C3P0 connection pool, JTDS driver, connecting to a SQL Server database.
We had disabled statement caching in our the C3P0 connection pool, but had not done this on the driver level. Adding maxStatements=0 to our connection URL stopped the driver caching statements, and fixed the error.

Categories