Suppose the website is written in PHP which disables multiple statements. If the query looks like this:
Select id From TableX Where num = >userInput<
Is it impossible to Update or Delete record by SQL Injection? Is it possible to get the content from another table, like tableB, which may not be union-compatible?
Thanks in advance.
userInput = -1 union select GetCharCode(SomeStringField, CharPosition) from SomeTable where SomeCondition, where GetCharCode returns the code of character in CharPosition of SomeStringField (you need to write some DB-specific code there) will help you to get the value of SomeStringField by looping through possible CharPositions, and thus bypass the problem of tableB not being "union-compatible".
I am curious about questions like "How to inject", "How to break in", "How to steal some info", implying getting step by step instructions - are such questions welcome on this site or not?
Related
What is the simplest way of putting another mysql query inside a where clause in php.
For example I have tried:
$sql = "SELECT app, description FROM all-apps WHERE app!='(SELECT user, app FROM users-apps WHERE user="$user_name")'";
I need to bring up all the apps entries in the database. and then check if the user has the same app name in his list. if so it will not show up.
Basically there are 2 databases one has all apps and the other one has apps which the users have used and I need the query to find all the apps the user has not used.
Please comment bellow if this question is up to standard. Please have an opinion so I can fix on my mistakes in the future.
A few changes needed
"SELECT app, description FROM all-apps WHERE app NOT IN (SELECT app FROM users-apps WHERE user='{$user_name}')";
Note that this and your original query may leave you vulnerable to sql injection. Please use PDO prepared statements.
Thanks, with all of your help I was able to get this query to work:
$sql = "SELECT * FROM all_apps WHERE app NOT IN (SELECT app FROM users_apps WHERE user='{$user_name}') ";
This works by first selecting one table. Then choosing what column you want the WHERE to be. Then put IN if you want it to be in or NOT IN. Then in brackets your second query. Make sure to have it only select the one column. The IN clause also works if there are multiple results.
I am trying to inject into a dummy website I have made, its a simple form which uses the text input to send data to my php file and then outputs the data gathered. The following is my code for the SQL.
$id = $_GET['id'];
$id = $_GET['id'];
$data = $conn->query('SELECT * FROM users WHERE username = ' . $conn->quote($id));
foreach($data as $row) {
echo $row['id'].' '.$row['username'];
}
When I try to use things such as unions I get no data back and if I put an apostrophe at the end of the URL I don't get a MySQL error. Could someone please explain why the site is secure from SQL injections?
As there are some confusions as to what I asked my final goal is to be able to get into the information schema so I have been trying to use statements like to get into the schema but without success:
' and 1=1 union select table_name,table_schema from information_schema.tables where table_schema='users' #
Other apparently may have missed what you were asking...
You are INTENTIONALLY trying to sql-inject your own site, such as for personal learning on how NOT to, but also see what impacts sql-injection CAN do. If so, take a look at your statement and see "what would I need to add to fake it out".
"SELECT * from users WHERE username = '$id'"
If the user puts a value such as "Bill" for the $id, it would become
"SELECT * from users WHERE username = 'Bill'"
and run no problem. Now, you want to inject and see ALL users, a common way is to close the quote and then add something else that will always return true... such as a user puts a value of
' OR 1=1 ;--
The above would result in
"SELECT * from users WHERE username = '' OR 1=1;-- '"
The semi-colon and dashes are important to "finish" the original query, and then indicate that anything after the dashes are comments so it won't try to execute anything AFTER the otherwise dangling close quote from your original query build construct.
Hopefully that helps answer why you may be failing while TRYING to inject into your own site.
COMMENT FEEDBACK
I don't know why my version would not work, I am not trying to union anything, just force an all records returned.
With respect to your UNION clause, that looks ok, but if your users table has 3 columns and your UNION is only 2 columns, that should fail as the union should be the same number of columns as in the original query. THAT would cause a failure on execution, but not enough specific information to confirm.
Most likely, you have magic quotes enabled, which is saving your otherwise-vulnerable code.
Don't rely on it.
As it can be clearly seen from either question and answers, most people don't understand what injection is. For some strange reason everyone takes injection consequences for injection itself. While injection is just a query creation. No more, no less.
So, the result of injection is not whatever data returned, but mere SQL query string. Thus, what the OP have to check is the resulting SQL query. It is extremely simple a task, as primitive as just echoing the query string out. This will reveal injection possibility immediately, without toilsome guesswork and sophisticated query building.
Simple output like this
SELECT * from users WHERE username = 'Bill\''
will tell you that magic quotes are on and whole question is a thousand-times-duplicate and not-a-real-one at once.
UPDATE
For some strange reason the code in the question mysteriously has been changed to invulnerable PDO based code. Which leads me to believe that whole performance were just a mere trolling.
Your injected SQL String should look like this
-1'/**/UNION/**/SELECT/**/1,##VERSION/**/FROM/**/users/**/WHERE/**/1='1
as you need to close the last ' in the final sql query
Update:
like Your Common Sense pointed out
For some strange reason the code in the question mysteriously has been changed to invulnerable PDO based code. Which leads me to believe that whole performance were just a mere trolling.
This question already has answers here:
Why is SELECT * considered harmful?
(16 answers)
Closed 9 years ago.
I am developing an application and I was reading about how queries work. I read somewhere that you should avoid SELECT * FROM... where blah = blah
Why is that? And what's the workaround if you're trying to select pretty much everything?
Initially need to know what data you will need. Although, you can select all at once, if such requests will not be much. The difference in performance, you'll see only in heavy projects.
This is not really a direct answer to your question "Why is that?" (so downvote the answer if you need to.) It's an answer to the "what's a workaround if you need to" question.
The only workaround to avoid SELECT *, when I need all of the columns in the table, is to get a list of all the columns. And that's just extra busy I work I don't need when I'm already busy.
To put a backwards twist on a line from Office Space charaacter Peter Gibbons: "The thing is, Bob, it's not that I don't care, it's just that I'm lazy."
With MySQL I make for less busy work by using the SQLyog right click menu option to generate a skeleton SELECT statement that contains all the columns.
For a SQL statement that references multiple tables, I want every column reference to be qualified with a table alias, so I'll just use a SQL statement to retrieve a ready-to-use list of columns for me:
SELECT GROUP_CONCAT(CONCAT('t.',c.column_name)
ORDER BY c.ordinal_position
) AS col_list
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase'
AND c.table_name = 'mytable'
if I only need a few out a long list, it's easier for me to get them out of a vertical list
SELECT CONCAT(',s.`',c.column_name,'`') AS col_names
FROM information_schema.columns c
WHERE c.table_schema = 'mydatabase'
AND c.table_name = 'mytable'
ORDER BY c.ordinal_position
When the column references are qualified, the backticks are only needed for "special" characters in column names (or maybe some weird case sensitive setting.)
I can start with that list, and whittle out the columns I know I don't need.
Again, I apologize that this doesn't answer the question "Why?" There's several good reasons, given in answers to similar questions. For me, a big reason is that a future reader of the statement isn't going to have to go look somewhere else to find out what columns are being returned. Sure they can copy the statement, and go run it in a different environment, to see the list. But if the statement has variable substitutions, bind variables, and the dots and double quotes and calls to mysql_real_escape_string (in the case of mysql_ interface), that's a bigger hassle than it needs to be. Sure, the code can be modified to echo out the SQL text before its executed, and the reader may need to do that. But someone just reviewing the code shouldn't have to do that. And having the list of columns and expressions being returned by the statement, in an order more appropriate than the ordinal position of the columns in the table, I think that just makes for more readable code. (If it's important for the column to be returned by the statement, then I think it's reasonable that the column name is shown in the query.)
(This was in terms of application code, statements that are going to be included in an application. For ad hoc queries and development and such, I use the SELECT c.* freely. But when a statement is going into an application, that * gets replaced.
I have browser game. There is message send form.
I didn't make real escape string function to the "message_content" variable.
There is any option, that the user could make after the insert of the message, any update ?
I mean that the user could write a sql code in the message_content that can UPDATE values in the sql? Like update users set gold = '9999' where username = 'my_username'
THANKS ALOT....
And that it only a question. Don't worry i already made mysql_real_escape_string...
Please learn about using parametrized queries, preferably with the PDO module, to protect your web app. http://bobby-tables.com/php has examples to get you started.
The mysql_query function doesn't allow the execution of multiple statements at once. So the often mentioned example of Robert'; DROP TABLE Students; -- won’t work.
This also means that the exploitation is restricted to the statement type. So if the injection point is in an INSERT statement, the vulnerability can only be exploited to insert arbitrary values into that specific table.
However, one can still inject arbitrary data from the database into that table. And if the attacker addresses the message to himself, he will be able to read arbitrary data from the database and may also be able to read and write arbitrary files on the server.
If you don't escape the user input the following can happen:
Imagine this query:
SELECT * FROM user WHERE login='$login'
where $loginis the user's input.
Now the user insers the following content in the variable: '; DROP TABLE user; --
The following query will be executed:
SELECT * FROM user WHERE login=''; DROP TABLE user; --'
It's a very generic example, but I hope you get the idea
I'm using a PHP webservice where I have performed a simple SELECT query, and stored it
$result = run_query($get_query);
I now need to perform further querying on the data based on different parameters, which I know is possible via MySQL in the form:
SELECT *
FROM (SELECT *
FROM customers
WHERE CompanyName > 'g')
WHERE ContactName < 'g'
I do know that this performs two Select queries on the table. However, what I would like to know is if I can simply use my previously saved query in the FROM section of the second section, such as this, and if my belief that it helps performance by not querying the entire database again is true:
SELECT *
FROM ($result)
WHERE ContactName < 'g'
You can make a temp table to put the initial results and then use it to select the data and in the second query. This will work faster only if your 1-st query is slow.
PHP and SQL are different languages and very different platforms. They often don't even run in the same computer. Your PHP variables won't interact at all with the MySQL server. You use PHP to create a string that happens to contain SQL code but that's all. In the end, the only thing that counts is the SQL code you sent to the server—how you manage to generate it is irrelevant.
Additionally, you can't really say how MySQL will run a query unless you obtain an explain plan:
EXPLAIN EXTENDED
SELECT *
FROM (SELECT *
FROM customers
WHERE CompanyName > 'g')
WHERE ContactName < 'g'
... but I doubt it'll read the table twice for your query. Memory is much faster than disk.
Thanks for the responses, everyone. Turns out what I was looking for was a "query of query", which isn't supported directly by PHP but I found a function over here which provides the functionality: http://www.tom-muck.com/blog/index.cfm?newsid=37
That was found from this other SO question: Can php query the results from a previous query?
I still need to do comparisons to determine whether it improves speed.
If I understand your question correctly you want to know whether saving the "from" part of your SQL query in a php variable improves the performance of you querying your SQL server, then the answer is NO. Simply because the variable keeping the value is inserted into the query.
Whether performance is gained in PHP, the answer is most probable yes; but depends on the length of the variable value (and how often you repeat using the variable instead of building a new complete query) whether the performance will be notable.
Why not just get this data in a single query like this?
SELECT *
FROM customers
WHERE CompanyName > 'g'
AND ContactName < 'g'