What is the use of order by in sql injection - mysql

I am learning SQL injection and I can't quite seem to understand the order by statement.
The definition here in wwwschools is that this sorts the given table in ascending or descending. What happens when I use a integer?
For example.
Order by 1
http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_orderby
When I use order by 1 in this example, I get Customer ID arranged from 1to 91.
When I use order by 2 in this example, I get customer ID arranged in a zig zag manner.
What is the reason for this behaviour? And how is order by used in sql injection to obtain the number of columns?

It may be useful as part of a blind SQL injection attack. You keep increasing the number (which indicates which column in the SELECT clause should be used to determine the sort order) until the server suddenly reports an error. You now know the number of columns in the SELECT clause of the query (it's one less than the number you just tried)

The order by 1 means sort by values of the first column from the result set.
The order by 2 means sort by values of the second column from the result set.
The order by clause in SQL has no direct relation to SQL injection AFAIK.

You asked two questions
Answer 1: Order By is used to order the result to the given SQL Query according to the Column Number given in SQL query.
For Example: Order by 1 means order the result based on the first column in ascending order by default.
Answer 2: We use Order By for SQL Injection to check whether a given website is prone to SQL injection or not.
For Example
If I write order by 1 in my SQL injection payload then it will give me some result
On the other hand if I write order by 100000 then it most probably will give an error because it is very unlikely that my Table has these many columns. So Order by is used to check whether a website is vulnerable to SQL Injection or not. And the error confirms that the database was trying to understand my SQL Query but couldn't do it.
It's second use is to find the number of columns in our Table which we are exploiting. If you want more information on this then feel free to reply me in the comments

Related

What does it mean to include a string in an SQL SELECT query

I apologize if the question asked is simple and far too stretched out
I've been studying the fundamentals of SQL Injection attacks and at a point, I've read that a potential method of verifying the data type of a particular field in a UNION SQL Injection attack is by making certain changes to the request that we make to the target server.
The software being used is BurpSuite, and the target is a practice lab on the website https://portswigger.net. It is told that the category field is vulnerable, and that the query for the category returns two fields, so the following "code" is appended to the category part of the HTTPS GET message that we send to the server in an attempt to know the data type of the first field
...?category=Gift'+UNION+SELECT+'abc',NULL+FROM+table_that_contains_target_information--
According to the manuals for the lab, what we're doing with the 'abc',NULL part is that we're verifying that the first field in the "table_that_contains_target_information", is of the type string/varchar. This seems to work and aids one in determining the data type of that particular field, as I checked in the lab, since if the first field's datatype is not a string/varchar, I would get an internal server error.
However, later on, when performing a query on a general database to check what the 'abc',NULL part does in a general SELECT query, the results that come are somewhat different.
The general database question is one that is available to use for learning SQL at https://www.w3schools.com/mysql. It has a table named Customers with several fields. I know for a fact that the first field is an integer (via verification with information_schema.columns), and the rest are varchars. For context, in the Customers table, CustomerID is an integer field, and CustomerName is a varchar field. I ran the following query on the server
|-------This part is the original query-------||This is our inserted code to find out information about the database|
SELECT CustomerID, CustomerName FROM Customers UNION SELECT 'abc',NULL FROM Customers
Disclaimer: My intentions were not to cause any harm to the database, only to learn some SQL
According to what I've learnt from the Lab manuals, I should be getting an error of sorts right?, since I'm checking the datatype of a field in a method that and unethical hacker could potentially take. However, all I get are the results of the original query and an extra record with values 'abc' and the second field is NULL.
I've tried to read up on documentation regarding the SELECT query in SQL, but as far as I was able to find, most of them tell about the general SELECT * FROM table_name or SELECT column_name, other_column_name FROM table_name. I wasn't able to find anything about the SELECT 'abc' FROM table_name.
Could anyone please explain what is going on here? Does the SELECT 'abc' FROM table_name just give me an extra record with 'abc'? If so, then why is this same query used to verify the datatypes in the lab at https://portswigger.net, and it seems to work its purpose there.
Thank you for answering in advance!

(Routed) SQL injection on shared parameter

I am in charge of the security of several websites. Recently we bought the Acunetix WVS and performed several tests that gave positive on SQL injection. Not only am I trying to replicate these tests but I also trying to find out if it is possible to extract relevant information, given that we have a WAF/IPS deployed that mitigates the more critical SQL injections.
I am obviously not allowed to disclose the website I am currently testing on, for that I will refer to it as http://example.com.
I was able to find out that on the page http://example.com/show_results.php?group=1&query=members there are 2 queries being used to display the results. So maybe, this is related to Routed SQL Injection. I have applied several SQL injection techniques, and through the error messages I have identified that they take the form of:
SELECT 1 FROM ... WHERE group='1' LIMIT 0,1
SELECT 1,2,3,4 FROM ... WHERE group='1' AND `user_type` NOT LIKE 'colaborators' ORDER BY 'name'
Both queries are displayed on individual <div>. user_type represents the members on the URL. The first query is obviously very easy to inject. I can get the database name by simply changing the URL to:
http://example.com/show_results.php?group=1' union select database() -- - &query=
The obvious question here is: How to get the table names for instance. Something like:
GROUP_CONCAT(table_name) FROM information_schema.tables WHERE TABLE_SCHEMA=database()
This is tricky because both queries use the same group parameter, so it is not entirely Routed SQL Injection in its simplest form. Something like this:
http://example.com/show_results.php?group=1' union select database() -- -&query=members
Note the difference brom above on the query parameter. This shows me the error of The used SELECT statements have a different number of columns (obviously because both queries have a different number of columns).

Extremely basic SQL Misunderstanding

I'm preparing for an exam in databases and SQL and I'm solving an exercise:
We have a database of 4 tables that represent a human resources company. The tables are:
applicant(a-id,a-name,a-city,years-of-study),
job(job-name,job-id),
qualified(a-id,job-id)
wish(a-id,job-id).
the table applicant represents the table of applicants obviously. And jobs is the table of available jobs. the table qualified shows what jobs a person is qualified for, and the table wish shows what jobs a person is interested in.
The question was to write a query that displays for each job-id, the number of applicants that are both qualified and interested to work in.
Here is the solution the teacher wrote:
Select q1.job_id
, count(q1.a_id)
from qualified as q1
, wish as w1
Where q1.a_id = w1.a_id
and q1.job_id = w1.job_id
Group by job_id;
That's all well and good, I'm not sure why we needed that "as q1" and "as w1", but i can see why it works.
And here is the solution I wrote:
SELECT job-id,COUNT(a-id) FROM job,qualified,wish WHERE (qualified.a-id=wish.a-id)
GROUP BY job-id
Why is my solution wrong? And also - From which table will it select the information? Suppose I write SELECT job-id FROM job,qualified,wish. From which table will it take the information? because job-id exists in all 3 of these tables.
You can only refer to tables mentioned in the FROM clause. If it's ambiguous (because more than one has a column of the same name) then you need to be explicit by qualifying the name. Usually the qualifier is an alias but it could also be the table name itself if an alias wasn't specified.
There's a concept of a "natural join" which joins tables on common column(s) between two tables. Not all systems support that notation but I think MySQL does. I believe these systems usually collapse the joined pairs into a single column.
select q1.job_id, count(q1.a_id) from qualified as q1, wish as w1
where q1.a_id = w1.a_id and q1.job_id = w1.job_id
group by job_id;
I don't think I've worked on any systems that would have accepted the query above because the grouping column would have been strictly unclear even though the intention really is not. So if it truly does work correctly on MySQL then my guess is that it recognizes the equivalence of the columns and cuts you some slack on the syntax.
By the way, your query appears to be incorrect because you only included a single column in a join that requires two columns. You also included a third table which means that your result will effectively do a cross join of every row in that table. The grouping is going to still going to reduce it to one row per job_id but the count is going to be multiplied by the number of rows in the job table. Perhaps you added that table thinking it would hurt to add it just in case you need it but that is not what it means at all.
Your query will list non-existing jobs in case the database has orphan records in applicant and qualified, and might also omit jobs that have no qualified and willing candidates.
I'm not exactly sure, because I have no idea if there's any database that will accept COUNT(a-id) when there's no information about the table from which to take this value.
edit: Interestingly it looks like both of these problems are shared by both of the solutions, but shawnt00 has a point: your solution makes a huge pointless cartesian of three tables: see it without the group by.
My current best guess for a working answer would therefore be http://sqlfiddle.com/#!9/09d0c/6

Confused with selecting data from db in mysql [duplicate]

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 8 years ago.
I have 2 tables: PLAYER and GROUP.
When I call:
SELECT * FROM PLAYER
Everything is OK but when I call:
SELECT * FROM GROUP
There is error:
#1064 - 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 'GROUP' at line 1`
I don't understand why there is such error.
GROUP is a reserved word and it must be escaped with back ticks.
SELECT * FROM `GROUP`
It's also better practice to avoid using table names or columns that are reserved words. Also, specify a column list and not use *.
GROUP is a reserved keyword . You have to escape it, like so
SELECT * FROM `GROUP`
Things to note:
It is highly recommended not to name the table group, it is better to use the plural Groups.
Also, try to avoid *.
Just as you use the reserved keywords SELECT and FROM for constructing your query, there are other reserved keywords like the ones in the following list that you may want to avoid when naming all your tables, views, constraints and columns.
List of (some) reserved keywords: WHERE, ORDER, GROUP, UPDATE, DELETE, CHECK, CHANGE, LIKE etc...
Therefore, in your case the DB Engine is complaining because a query
needs 1 mandatory clause SELECT and optional clauses FROM, WHERE,
ORDER BY, GROUP BY, HAVING, LIMIT etc... read more here
We might be tempted to use these keywords; especially if they've been modeled in our problem domain (or in the diagrams). For example, a client placing an order yields 2 Entities CLIENT and ORDER etc. or a mechanic performing a check giving MECHANIC and CHECK. or even a FACEBOOK_USER expressing a LIKE. or in your case there might be a GROUP of PEOPLE for example.
As a general rule, you can transform your entities like so to avoid problems:-
a) The Entity is always modeled (on paper) as singular as it represents a concept/asset/person in the real world or problem domain. eg. ORDER, LIKE, CHECK, STUDENT, CAR
b) the corresponding DB Table it is transformed into is always named using plural. The logic is that the table will contain lots of instances of that Entity. Therefore ORDERS, LIKES, CHECKS, STUDENTS, CARS
In the end, you decide because you really can use GROUP if you really
want or need to make your table name like a reserved word. Just
remember to give them a special treatment by putting them in quotes
using the backtick (“`”) when querying. At the moment of creation the DB engine
won't complain, trusting that you know what you're doing.

MySQL Query eliminate duplicates but only adjacent to each other

I have the following query..
SELECT Flights.flightno,
Flights.timestamp,
Flights.route
FROM Flights
WHERE Flights.adshex = '400662'
ORDER BY Flights.timestamp DESC
Which returns the following screenshot.
However I cannot use a simple group by as for example BCS6515 will appear a lot later in the list and I only want to "condense" the rows that are the same next to each other in this list.
An example of the output (note BCS6515 twice in this list as they were not adjacent in the first query)
Which is why a GROUP BY flightno will not work.
I don't think there's a good way to do so in SQL without a column to help you. At best, I'm thinking it would require a subquery that would be ugly and inefficient. You have two options that would probably end up with better performance.
One would be to code the logic yourself to prune the results. (Added:) This can be done with a procedure clause of a select statement, if you want to handle it on the database server side.
Another would be to either use other information in the table or add new information to the table for this purpose. Do you currently have something in your table that is a different value for each instance of a number of BCS6515 rows?
If not, and if I'm making correct assumptions about the data in your table, there will be only one flight with the same number per day, though the flight number is reused to denote a flight with the same start/end and times on other days. (e.g. the 10a.m. from NRT to DTW is the same flight number every day). If the timestamps were always the same day, then you could use DAY(timestamp) in the GROUP BY. However, that doesn't allow for overnight flights. Thus, you'll probably need something such as a departure date to group by to identify all the rows as belonging to the same physical flight.
GROUP BY does not work because 'timestamp' value is different for 2 BCS6515 records.
it will work only if:
SELECT Flights.flightno,
Flights.route
FROM Flights
WHERE Flights.adshex = '400662'
GROUP BY (Flights.flightno)