vb.net handling many table name using string - sql

Am storing a table name in a String
ugad = "INSERT INTO tb(Ugname,Ugdob,Uggender)"
this is the ordinary query which functions well.
But i need to store a Tablename in a string called "dept"
and this string will have diff table name at diff times. How should i run it, Wat query should I Give.
ugad = "INSERT INTO dept(Ugname,Ugdob,Uggender)"
I know this query is not vaild. May i know the correct query

Use:
ugad = "INSERT INTO " & dept & "(Ugname,Ugdob,Uggender)"
N.B. There are arguably safer, better ways to compose SQL (if you are worried about malicious or accidental interference with your underlying data through SQL injection) than the above but hopefully that gets you started.

Or
ugad = String.Format("INSERT INTO {0}(Ugname,Ugdob,Uggender)", dept)
Which I think is easier to read and easier to maintain.

If I understand you correctly you neet to try something like
ugad = "INSERT INTO " + dept + "(Ugname,Ugdob,Uggender)"
Have a llok at Operators in VB.NET
Just remember that string concatenation can be very slow once you start concatenating in loops, so always have in the back of your mind that the StringBuilder Class exists, and is a lot faster than normal concatenation...

Related

Best way of sanitize unparametrizable sql

I have to make a SQL string to be injected in a database for a third party to read it, execute it, and making a report with the results. Since the user can choose the columns wanted for the report, as well as renaming the columns, I've ended with a code like this:
string sql = "SELECT ";
foreach(KeyValuePair<string, string> field in report.fields)
{
sql += "[" + field.Key + "] as [" + field.Value + "];
}
sql += " WHERE idrpt=#id";
The only part of this query I can parametrize is the WHERE clause, but if my research on the web has'nt been misguided, there's no way to parametrize the column names and aliases in the SELECT clause. Now, given that I can't change the way the program works (I have to produce a valid SQL query to a third party to execute it), what would be the best way of sanitize the input string?
I've solved the part about column names by checking them against a list of valid columns, but I can't do that for the aliases, which can be whatever string of less than 80 characters the user is willing to give.
Right, so you have a SQL layout you can't change that necessitates you to do this. That is unfortunate, but lets make the best of it.
As you stated in your comments, you probably need some special character support, so specifically escape these special characters.
Other then that, you should reduce the allowed names to alphanumeric characters and possibly whitespace. Validate these against your validation mechanism of choice, for instance regex, and allow only those characters. That will probably keep you mostly safe from SQL injection.
This isn't optimal, but it seems to be the best you can do in this situation.
As you noted there is no way to parametrize the column names and aliases. Therefore, you are opened to SQL injection. To minimize the issue you can use quotename, which is similar to the approach you are using currently.
string sql = "SELECT ";
foreach(KeyValuePair<string, string> field in report.fields)
{
sql += "quotename(" + field.Key + ") as quotename(" + field.Value + ")";
}
sql += " WHERE idrpt=#id";

Convert SQL statement to Hibernate Criteria or Projections

I'd like to convert this SQL Statement into either Criteria or Projections. I'm sorry I don't know which one to use since I'm new to Hibernate. I've done some research, and it looks like both are needed to achieve what I wanted.
Before I always use SQL Statements in my programs but when I saw a sample code which allows you to create queries without writing SQL Statements by using Criteria, I wanted to use it since it gives me cleaner code.
Thanks in advance.
String query = "SELECT MAX(employeeNo) "
+ "FROM Profile "
+ "WHERE SUBSTRING(employeeNo,1,2)='" + yy + "'";
empNo = session.createQuery(query).list().get(0).toString();
This query gets the highest employee number in the database for a given year yy.
Sample result would be 14-229
This is assuming that you've already defined a mapping for Profile entity.
Session session = sessionFactory.getCurrentSession();
String empNo = (String) session
.createCriteria(Profile.class)
.add(Restrictions.sqlRestriction("substring(employeeNo,1,2) = ?", yy, StringType.INSTANCE)
.setProjection(Projections.max("employeeNo"))
.uniqueResult();
Now, this I don't know if I'd agree with your statement that this is cleaner. The nice thing about using Criteria is the allow you to build a criteria dynamically, but it's very verbose, and it isn't clear exactly what you are trying to do at first glance. Plus, because of the substring function, forces you to mix in a sqlRestriction. Instead, you could use HQL:
Session session = sessionFactory.getCurrentSession();
String empNo = (String) session.createQuery("SELECT MAX(employeeNo) FROM Profile WHERE substring(employeeNo,1,2) = :year")
.setString("year", yy)
.uniqueResult();
Personally, I think the HQL or even SQL approach is a little cleaner, and expresses intent better.

SQL Injection: Why is the following code dangerous?

An intern has written the following vb.net code:
Public Sub PopulateUsersByName (name As String)
'Here, the parameter 'name' is unsantized, coming straight from the form
Dim query As String = ""
query += vbNewLine + " SELECT Id, FirstName, LastName FROM dbo.[Users]"
query += vbNewLine + " WHERE FirstName LIKE '" + REPLACE(name, "'", "''") + "'"
query += vbNewLine + " OR LastName LIKE '" + REPLACE(name, "'", "''") + "'"
'Execute SQLCommand with above query and no parameters
'Then do some other stuff
END Sub
I have explained that in general, one should never use string concatenation when trying to do something like the above. The best practice is to use either an SP, or an SQLClient.SQLCommand with parameters.
His logic is: any sql varchar(xxx) gets sanitized by replacing all single quotes with two single quotes (and adding additional single quotes at the start and end of the string).
I am unable to provide an example of something the user could type that would get around this - I'm hoping I can find something more convincing than "But, as a general principal, one should avoid this - you know... coz... well, don't argue with me - I'M THE BOSS AND MY WISH IS YOUR COMMAND.".
Note: The code will always connect to our Microsoft SQL Server. But I can imagine it failing to sanitize the input on some other SQL Implementation.
UPDATE:
Just to make it a little clearer, what I'm looking for is a possible value of the parameter name which will allow someone to inject SQL into the query.
Try this with his code using '%_%' (with and without the single quotes) as the input....same as this in SQL....
select SELECT Id, FirstName, LastName FROM dbo.[Users] from TBL_EMPLOYEES where FirstName like '%_%' or LastName like '%_%'
irrespective if it failing or not, his is very poor code... fair enough this one is only a one liner, but anything more than that, including complicated SQL statements would be difficult to maintain and debug.. in any case, using Sps gets him used to using them AND allows him to take advantage of the flexibility and power of T-SQL... LOL, i'd dread to think how some of the SQL I have written would look like in code.....
You know, I come across code like this (and a lot worse) all the time... just because it might work for a while DOESN'T mean it's the right way to do it.... If your intern that does NOT listen to experience he will NEVER make a good developer and that is sadly a fact
I once reduced a junior developers attempt at importing a CSV file (50 million rows) in the same way your intern has done, from her 300 lines of code (which was never going to work) to just one line of LINQ to convert it to XML (we couldn't use Bulk Insert or bcp) and a fancy SP... Was bullet proof, job done....
I can get a list of all your users. If name = %%
Now I know the full name of everyone in your database.
I would consider that a security hole.
Sanitizing is not the answer. You can by pass quotes and use "smuggling". A good example is http://danuxx.blogspot.com.br/2011/08/sql-injection-bypassing-single-quotes.html
Also a good practice (to use dynamic queries) is to use parametric dynamic queries. Also SPs can do the trick (if you don't use dynamic queries inside it off course).

Is it ok to use dynamic SQL in this case?

Let me start by saying I am biased; I hate dynamic SQL under all circumstances. That being said, is this scenario considered good practice for dynamic SQL?
sqlDataSourceObject.SelectCommand = String.Concat(
"select top ", maxRows,
" col1, ",
" col2 as myData, ",
" '' as blah, ",
" col3 as Fromperson ",
" 'Corporate' as toPerson, ",
" Convert(char(11), orderDate) as orderDate, ",
" carrier, ",
sqlString1,
sqlString2,
sqlString3 + " AND areaCode = '" + currArea + "'"
);
This query may run once, then change the value for sqlString1,2,3, or currArea and run it again against a different SqlDataSource.
This code makes me angry to read. Its hard to read, it can change with the sqlString variables, I cant run it without copy/pasting into SSMS and I have to go track down several variables to make a single change.
But, like I said I am biased so I am asking you. Is this code, written in 2001 before LINQ, as good as a stored proc or some other technology, generally OK from a good practice perspective?
If not, how would you have improved it (remember no LINQ, this is 2001).
A point of clarification:
Dynamic SQL is normally taken to mean that the semantics of the statement change based on some external factor. In other words, the column names or even the base table(s) might be altered. This was common to do for pivot queries in the old days.
It's kind of hard to tell because I don't know what's going into those awfully-named sqlStringX parameters, but I think that what I'm seeing here is really just inline SQL which happens to be riddled with SQL injection vulnerabilities. It is trivially easy to parameterize. Fix this ASAP, please. Inline SQL is fine but there is no reason to be using raw strings instead of parameters.
Stored procedures would be one idea of how to better handle these types of queries. Granted the stored proc may just execute what the parameters pass but that would be my suggestion for one way to improve that code so that the DBA can know what indexes may be useful to help optimize the query. SQL injection attacks as #Jarrod Roberson points out are also quite likely with this kind of code.
PS: I wrote this kind of code back in 1998 where I had ~20 possible parameters in writing a "Find Customer" routine that was one of my first assignments out of university so I do understand where this kind of code can originate.
I'd use a stored procedure myself. But in any case, no matter what, use parameters. They way you' have it there is not secure at all, and as you say, makes me angry to look at. :-)
Here's one reference that might help (not stored procs per se, but still uses parms)
http://www.asp.net/data-access/tutorials/using-parameterized-queries-with-the-sqldatasource-vb

How to search for matches with optional special characters in SQL?

I have a problem with a search query I am using my data contains names and information that has apostrophes in various forms (HTML encoded and actual).
So for example I would like an alternative to this:
SELECT * FROM Customers WHERE REPLACE(LastName,'''','')
LIKE Replace('O''Brien,'''','')
This is just an example, what I want is a way where if someone types OBrien or O'Brien this will still work, I need to replace three versions of the character and the data is feed sourced and cannot be changed - what can be done to a query to allow for this kind of search to work.
I have Items with names which work this way which currently have many nested REPLACE functions and cannot seem to find something that will work this way, which is more efficient.
I am using MS SQL 2000 with ASP if that helps.
Edit
Here is the query that needs to match O'Brien or OBrien, this query does this but is too inefficient - it is joined by another for Item Names and FirstName (optional) for matching.
SELECT * FROM Customers
WHERE
REPLACE(REPLACE(REPLACE(LastName,'&apos;',''),''',''),'''','')
LIKE
REPLACE(REPLACE(REPLACE('%O'Brien%','&apos;',''),''',''),'''','')
If you want to stay correct and do this in SQL this is probably the best you can do
SELECT * FROM Customers WHERE
LastName LIKE 'O%Brien' AND
REPLACE(LastName,'''','') LIKE 'O''Brien'
You will still get table scans sometimes, due to poor selectivity.
The reason for the first where is to try to use an existing index.
The reason for the second match is to ensure that last names like ObbBrien do not match.
Of course the best thing to do would be not to need the ugly replace. This could be achieved in the app by storing an additional clean lastname column. Or in a trigger. Or in an indexed view.
You could try this:
SELECT *
FROM Customers
WHERE LastName LIKE Replace('O''Brien,'''','%')
This should allow it to use an index as you are not modifying the original column.
For pure SQL, the escaping is entirely unnecessary.
SELECT * FROM Customers WHERE LastName = 'O''Brien'
Use parameters instead of building the queries in code.
If you are using ADO you can use a syntax like this:
Dim cmd, rs, connect, intNumber
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = "your connectionstring"
cmd.CommandText = "SELECT * FROM Customers WHERE LastName LIKE #LastName"
cmd.Parameters.Append cmd.CreateParameter("#LastName",,,,"O'Brien")
Set rs = cmd.Execute
This should perform the query and insert the string O'Brien properly formatted for your database.
Using parameters ensures that all values are properly formatted and it also protects you against sql injection attacks.