In vb.net, I need to split a string multiple ways to create a list of commands - vb.net

Lets say I have a string that contains stored procedure names, their parameters, and values, like this:
Dim sprocs As String = "Procedure: NameOfProcedure, Parameters: #Param1(int), #Param2(varchar) Values: Something, SomethingElse ; Procedure: NameOfProcedure, Parameters: #Param1(int), #Param2(varchar) Values: Something, Something Else"
My point of the above is I need to be able to take a user defined string that can store multiple procedures separated by... something. In this case I used a ; semicolon.
What I need to be able to do is a FOR EACH on these in vb.net.
I know how to used stored procedures and set parameters... I'm just not sure of the best way to go about this as far as how to split up that string to match parameters and values, etc.
So a bad example:
Dim ConnectionString As String = "String...removed"
Dim conn As New System.Data.SqlClient.SqlConnection(ConnectionString)
' So I need a for each here
Dim cmd As New System.Data.SqlClient.SqlCommand(ProcedureName)
With cmd
.Connection = conn
.CommandType = CommandType.StoredProcedure
' and a for each here on the parameters, datatypes, and their values
.Parameters.Add(ParamName, DataType).Value = TheValue
.Connection.Open()
.BeginExecuteReader()
.Connection.Close()
End With
So the splitting and parsing out the string is my biggest roadblock on this. I'm not sure how to separate it out at this level, match parameters, datatypes and their values all together. If there's a better way to have the end-user organize the string to make parsing and splitting easier, please share.
Any suggestions or examples are greatly appreciated.
Thank you very much.

There's a temptation here to use String.Split() or a regular expression. Neither solution is actually very good for this. To understand what I mean, take a quick moment to search Google for the many thousands of posts of programmers working with CSV running into edge cases where their regex didn't quite cut it. For this purpose, your semi-colon delimiter is not significantly different than a fancy comma.
Depending on the regex engine, it may actually be possible to build an expression that does this, especially if you can put certain constraints on the data. However, such expressions tend to be very tough to build and maintain, and they tend to require backtracking, which hurts performance.
The next alternative to examine is a dedicated parser. For CSV data, this is the panacea. There a number of good ones available for most any platform that you can just plug in, and they're typically pretty easy to work with. However, what you have, while similar, goes a bit beyond the level of what these parsers are written to handle.
One related solution is write your own csv-like parser. This may be your best option, and if you choose this route all I can do is recommend that you build a state machine to go character by character through the input string.
The next rung up the ladder is to use a generic parser/interpretter that relies on something like ANTLR. I'm haven't personally dug very deep into that well, but I know the tools are out there.
One related option, that I think is probably your best option here overall, is a Domain Specific Language (DSL). This is something that may be a little easier to get started with than a tool like ANTLR, especially because it's already built into Visual Studio. However, this option requires that you be able to control your input format.
If all this sounds like more work than it should be, you're right. The good news is that is possible to skip all this. The trick is that you must first impose artificial constraints on your data. For example, a constraint that parameter values are not allowed to contain ; characters means you can get back to a String.Split() solution to divide out each separate procedure call. Now your function is no longer generally applicable, but then maybe is doesn't need to be. When you create these constraints, make sure they are documented, so that when something violates them and code explodes you'll have clear definitions for why.

Related

Can SQL be injected when the input is hashed?

The passwords and my SQL database are hashed. If the input is hashed, can the field be injected?
The hash is SHA256. My command is to be:
SELECT true FROM accounts WHERE password = '[hex digits]';
I suggest that you not ask this question, because maybe there is a way that you can be in danger, but probably there isn't. Instead, use SQL placeholders and bind variables because that's why they exist.
Any time you are building a SQL statement using data that you are not directly controlling, you are running a risk.
Prepared SQL statements with placeholders also have the benefit of being less work for the database.
Do you have a reason that you can't do it this way?
Strictly speaking, the example you give is safe. Similarly, if you have an application variable that can only be an integer, it is safe. Or even if it's a string, if your code is in control of the string, and you can be sure the string doesn't contain characters that would cause SQL injection (e.g. quote characters like ' or "), then it's safe.
But I agree with Andy Lester's answer — just use query parameters, and then you don't have to think about it. You don't have to wonder if there's an edge case where the input string may be out of your control. You don't have to ask if a string of hex digits is safe or not.
And even more importantly, you don't have to worry that not every developer on your team has the same understanding of how to tell if an input is safe or not. Many developers don't know how to tell safe inputs from non-safe inputs, so it's safest to just establish a policy that all inputs must be parameterized into an SQL query after it is parsed, instead of concatenated into the SQL query before it is parsed.
Imagine you are an electrician. You don't want to touch a live circuit, but if you're well trained you know if you touch it with the right kind of insulated protection, or if you're not grounded, or other conditions are true, then you're probably safe. Probably.
But what is safest is to just make sure the circuit has been disconnected from the power source. That's just a smart habit. It always works, and even if you work with other people who are not as smart as you, it still works.
I agree with the previous answers from Bill and Andy - it's safe, but you should still bind variables / parameterized query parameters. Doing so will:
Improve performance in many databases - the query string will only need to be parsed and cached once
Reduce false positives for human code reviewers and static code analysis
Reinforce the correct coding techniques for anyone reading the code
Future proof it against changes (for example if someone changes the hash output to include quotes)

Custom, user-definable "wildcard" constants in SQL database search -- possible?

My client is making database searches using a django webapp that I've written. The query sends a regex search to the database and outputs the results.
Because the regex searches can be pretty long and unintuitive, the client has asked for certain custom "wildcards" to be created for the regex searches. For example.
Ω := [^aeiou] (all non-vowels)
etc.
This could be achieved with a simple permanent string substitution in the query, something like
query = query.replace("Ω", "[^aeiou]")
for all the elements in the substitution list. This seems like it should be safe, but I'm not really sure.
He has also asked that it be possible for the user to define custom wildcards for their searches on the fly. So that there would be some other input box where a user could define
∫ := some other regex
And to store them you might create a model
class RegexWildcard(models.Model):
symbol = ...
replacement = ...
I'm personally a bit wary of this, because it does not seem to add a whole lot of functionality, but does seem to add a lot of complexity and potential problems to the code. Clients can now write their queries to a db. Can they overwrite each other's symbols?
That I haven't seen this done anywhere before also makes me kind of wary of the idea.
Is this possible? Desirable? A great idea? A terrible idea? Resources and any guidance appreciated.
Well, you're getting paid by the hour....
I don't see how involving the Greek alphabet is to anyone's advantage. If the queries are stored anywhere, everyone approaching the system would have to learn the new syntax to understand them. Plus, there's the problem of how to type the special symbols.
If the client creates complex regular expressions they'd like to be able to reuse, that's understandable. Your application could maintain a list of such expressions that the user could add to and choose from. Notionally, the user would "click on" an expression, and it would be inserted into the query.
The saved expressions could have user-defined names, to make them easier to remember and refer to. And you could define a syntax that referenced them, something otherwise invalid in SQL, such as ::name. Before submitting the query to the DBMS, you substitute the regex for the name.
You still have the problem of choosing good names, and training.
To prevent malformed SQL, I imagine you'll want to ensure the regex is valid. You wouldn't want your system to store a ; drop table CUSTOMERS; as a "regular expression"! You'll either have to validate the expression or, if you can, treat the regex as data in a parameterized query.
The real question to me, though, is why you're in the vicinity of standardized regex queries. That need suggests a database design issue: it suggests the column being queried is composed of composite data, and should be represented as multiple columns that can be queried directly, without using regular expressions.

Does Laminas Framework DB Adapter automatically strip tags etc. like mysqli_real_escape_string?

I'm using Laminas framework (formerly ZEND Framework) and would like to know if the DB Adapter automatically strip tags etc. at Insert and Select Statements / Execution ($statement->prepare() / $statement->execute()->current()) to avoid SQL injection?
If not what is the best method to implement it while working with LAMINAS DB Adapter? A Wrapper function to get a clean SQL statement?
Before, I was using a wrapper function that cleaned the input with mysqli_real_escape_string
You'd need to provide some sample code in order to get a more accurate answer to this question, however the topic you're talking of here is parameterisation. If you use laminas-db properly, you won't have to call mysqli_real_escape_string or similar to protect against SQL injection. However, you should still be very wary of any potential cross site scripting (XSS) issues if any data written to your database eventually gets echoed back to the browser. See the section below on that.
How to NOT do it
If you do anything like this, laminas-db won't parameterise your query for you, and you'll be susceptible to SQL injection:
// DO NOT DO THIS
$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = $idToSelect";
$statement->prepare($myQuery);
$results = $statement->execute();
How to do it properly
Personally, I make use of the Laminas TableGatewayInterface abstraction, because it generally makes life a lot easier. If you want to operate at the lower level, something like this is a much safer way of doing it; it'll ensure that you don't accidentally add a whole heap of SQL injection vulnerabilities to your code
Named Parameters
$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = :id";
$statement->prepare($myQuery);
$results = $statement->execute(['id' => $idToSelect]);
Anonymous Parameters
$idToSelect = $_POST['id'];
$myQuery = "select * from myTable where id = ?";
$statement->prepare($myQuery);
$results = $statement->execute([$idToSelect]);
If you do it in a way similar to this, you won't need any additional wrapper functions or anything, the underlying components will take care of it for you. You can use either the named or anonymous parameter version, however I personally prefer the named parameters, as I find it aids code readability and generally makes for easier debugging.
Sanitising Input/Escaping Output
Be very careful with sanitising input. Not only can it lead to a false sense of security, it can also introduce subtle and very frustrating behaviour that the end user will perceive as a bug.
Take this example: Someone tries to sign up to a site under the name "Bob & Jane Smith", however the input sanitisation routine spots the ampersand character and strips it out. All of a sudden, Bob has gained a middle name they never knew they had.
One of the biggest problems with input sanitisation is context. Some characters can be unsafe in one given context, but entirely benign in another. Furthermore, if you need to support the entire unicode character set (as we generally should be unless we have a very good reason to not), trying to sanitise out control characters in data that will potentially pass through several different systems (html, javascript, html, php, sql, etc) becomes a very hard problem due to the way multibyte characters are handled.
When it comes to MySQL, parameterisation pretty much takes care of all of these issues, so we don't need to worry about the "Little Bobby Tables" scenario.
It's much easier to flip all of this on its head and escape output. In theory, the code that's rendering the output data knows in which context it's destined for, so can therefore escape the output for said context, replacing control characters with safe alternatives.
For example, let's say someone's put the following in their bio on a fictional social networking site:
My name is Bob, I like to write javascript
<script>window.postStatusUpdate("Bob is my hero ♥️");</script>
This would need to be escaped in different ways, depending upon the context in which this data is to be displayed. If it's to be displayed in a browser, the escaper needs to replace the angle brackets with an escaped version. If it's going out as JSON output, the double quotes need to be backslash escaped, etc.
I appreciate this is a rather windy answer to a seemingly simple question, however these things should certainly be considered earlier on in the application design; It can save you heaps of time and frustration further on down the line.

Parse a comma delimited field into seperate fields (MS ACCESS VBA 2003)

I inherited a database where user input fields are stored as a comma delimited string. I know. Lame. I want a way to parse these fields in a SELECT query where there are three segments of varying number of characters. Counter to all the recommendations that I insert fields into a new table or create a stored procedure to do this, this is what I came up with. I'm wondering if anyone sees any flaw in doing this as a select query (where I can easily convert from string to parsed and back again as need be).
Field_A
5,25,89
So to get the left segment, which is the most straightforward:
Field_1: Left$([Field_A],InStr([Field_A],",")-1)
To get the right-most segment:
Field_3: Right$([Field_A],Len([Field_A])-InStrRev([Field_A],","))
Middle segment was the trickiest:
Field_2: Mid([Field_A],InStr([Field_A],",")+1,InStrRev([Field_A],",")-InStr([Field_A],",")-1)
So the result is:
Field_1 Field_2 Field_3
5 25 89
Any consenting opinions?
Well, if you insist on going down this road......
This might be easier and more adaptable. Create a function in a module:
Public Function GetValueFromDelimString(sPackedValue As String, nPos As Long,
Optional sDelim As String = ",")
Dim sElements() As String
sElements() = Split(sPackedValue, sDelim)
If UBound(sElements) < nPos Then
GetValueFromDelimString = ""
Else
GetValueFromDelimString = sElements(nPos)
End If
End Function
Now in your query you can get any field in the string like this:
GetValueFromDelimString([MultiValueField],0) AS FirstElement, GetValueFromDelimString([MultiValueField],1) AS SecondElement, etc.
I feel like I am buying beer for a minor, encouraging this type of behavior :)
It sounds like you're not asking for information on how to parse a comma-delimited field into different fields, but rather looking for people to support you in your decision to do so, yes?
The fact, as you've already discovered, is that you can indeed do this with skillful application of functions in your SQL field definitions. But that doesn't mean that you should.
In the short run, it's an easy way to achieve your goals as data manager, I'll grant you that. But as a long-term solution it's just adding another layer of complexity to what seems like a poorly-designed database (I know that the latter is not your fault -- I too have inherited my share of "lame" databases).
So I applaud you on "getting the job done" for now, but would advise you to listen to "all the recommendations that you insert fields into a new table" -- they're good recommendations. It'll take more planning and effort, but in the long run you'll have a better database. And that will make everything you do with it easier, faster, and more reliable.
This is an old thread, but someone might search it. You can also do the same strategy as an update query. That way you can keep the original CSV and have 3 new destination fields that can be calculate and recalculated depending on your application purposes.

Is there some way to inject SQL even if the ' character is deleted?

If I remove all the ' characters from a SQL query, is there some other way to do a SQL injection attack on the database?
How can it be done? Can anyone give me examples?
Yes, there is. An excerpt from Wikipedia
"SELECT * FROM data WHERE id = " + a_variable + ";"
It is clear from this statement that the author intended a_variable to be a number correlating to the "id" field. However, if it is in fact a string then the end user may manipulate the statement as they choose, thereby bypassing the need for escape characters. For example, setting a_variable to
1;DROP TABLE users
will drop (delete) the "users" table from the database, since the SQL would be rendered as follows:
SELECT * FROM DATA WHERE id=1;DROP TABLE users;
SQL injection is not a simple attack to fight. I would do very careful research if I were you.
Yes, depending on the statement you are using. You are better off protecting yourself either by using Stored Procedures, or at least parameterised queries.
See Wikipedia for prevention samples.
I suggest you pass the variables as parameters, and not build your own SQL. Otherwise there will allways be a way to do a SQL injection, in manners that we currently are unaware off.
The code you create is then something like:
' Not Tested
var sql = "SELECT * FROM data WHERE id = #id";
var cmd = new SqlCommand(sql, myConnection);
cmd.Parameters.AddWithValue("#id", request.getParameter("id"));
If you have a name like mine with an ' in it. It is very annoying that all '-characters are removed or marked as invalid.
You also might want to look at this Stackoverflow question about SQL Injections.
Yes, it is definitely possible.
If you have a form where you expect an integer to make your next SELECT statement, then you can enter anything similar:
SELECT * FROM thingy WHERE attributeID=
5 (good answer, no problem)
5; DROP table users; (bad, bad, bad...)
The following website details further classical SQL injection technics: SQL Injection cheat sheet.
Using parametrized queries or stored procedures is not any better. These are just pre-made queries using the passed parameters, which can be source of injection just as well. It is also described on this page: Attacking Stored Procedures in SQL.
Now, if you supress the simple quote, you prevent only a given set of attack. But not all of them.
As always, do not trust data coming from the outside. Filter them at these 3 levels:
Interface level for obvious stuff (a drop down select list is better than a free text field)
Logical level for checks related to data nature (int, string, length), permissions (can this type of data be used by this user at this page)...
Database access level (escape simple quote...).
Have fun and don't forget to check Wikipedia for answers.
Parameterized inline SQL or parameterized stored procedures is the best way to protect yourself. As others have pointed out, simply stripping/escaping the single quote character is not enough.
You will notice that I specifically talk about "parameterized" stored procedures. Simply using a stored procedure is not enough either if you revert to concatenating the procedure's passed parameters together. In other words, wrapping the exact same vulnerable SQL statement in a stored procedure does not make it any safer. You need to use parameters in your stored procedure just like you would with inline SQL.
Also- even if you do just look for the apostrophe, you don't want to remove it. You want to escape it. You do that by replacing every apostrophe with two apostrophes.
But parameterized queries/stored procedures are so much better.
Since this a relatively older question, I wont bother writing up a complete and comprehensive answer, since most aspects of that answer have been mentioned here by one poster or another.
I do find it necessary, however, to bring up another issue that was not touched on by anyone here - SQL Smuggling. In certain situations, it is possible to "smuggle" the quote character ' into your query even if you tried to remove it. In fact, this may be possible even if you used proper commands, parameters, Stored Procedures, etc.
Check out the full research paper at http://www.comsecglobal.com/FrameWork/Upload/SQL_Smuggling.pdf (disclosure, I was the primary researcher on this) or just google "SQL Smuggling".
. . . uh about 50000000 other ways
maybe somthing like 5; drop table employees; --
resulting sql may be something like:
select * from somewhere where number = 5; drop table employees; -- and sadfsf
(-- starts a comment)
Yes, absolutely: depending on your SQL dialect and such, there are many ways to achieve injection that do not use the apostrophe.
The only reliable defense against SQL injection attacks is using the parameterized SQL statement support offered by your database interface.
Rather that trying to figure out which characters to filter out, I'd stick to parametrized queries instead, and remove the problem entirely.
It depends on how you put together the query, but in essence yes.
For example, in Java if you were to do this (deliberately egregious example):
String query = "SELECT name_ from Customer WHERE ID = " + request.getParameter("id");
then there's a good chance you are opening yourself up to an injection attack.
Java has some useful tools to protect against these, such as PreparedStatements (where you pass in a string like "SELECT name_ from Customer WHERE ID = ?" and the JDBC layer handles escapes while replacing the ? tokens for you), but some other languages are not so helpful for this.
Thing is apostrophe's maybe genuine input and you have to escape them by doubling them up when you are using inline SQL in your code. What you are looking for is a regex pattern like:
\;.*--\
A semi colon used to prematurely end the genuine statement, some injected SQL followed by a double hyphen to comment out the trailing SQL from the original genuine statement. The hyphens may be omitted in the attack.
Therefore the answer is: No, simply removing apostrophes does not gaurantee you safety from SQL Injection.
I can only repeat what others have said. Parametrized SQL is the way to go. Sure, it is a bit of a pain in the butt coding it - but once you have done it once, then it isn't difficult to cut and paste that code, and making the modifications you need. We have a lot of .Net applications that allow web site visitors specify a whole range of search criteria, and the code builds the SQL Select statement on the fly - but everything that could have been entered by a user goes into a parameter.
When you are expecting a numeric parameter, you should always be validating the input to make sure it's numeric. Beyond helping to protect against injection, the validation step will make the app more user friendly.
If you ever receive id = "hello" when you expected id = 1044, it's always better to return a useful error to the user instead of letting the database return an error.