saved searches: fix exploit allowing flaggers to be determined.

Fix an exploit that let you determine the flagger of a post using
`flagger:<username>` saved searches. Saved searches were performed as
DanbooruBot, but since DanbooruBot is a moderator, it let unprivileged
users do `flagger:<username>` searches. Saved searches were done as a
moderator to avoid tag limits, but this is no longer necessary since the
last PostQueryBuilder refactor.

fred get out
This commit is contained in:
evazion
2021-08-31 22:14:11 -05:00
parent 88e379f9cc
commit c41e3f4590
3 changed files with 24 additions and 1 deletions

View File

@@ -1272,10 +1272,26 @@ class Post < ApplicationRecord
where("posts.tag_index @@ to_tsquery('danbooru', E?)", tag.to_escaped_for_tsquery)
end
# Perform a tag search as an anonymous user. No tag limit is enforced.
def anon_tag_match(query)
user_tag_match(query, User.anonymous, tag_limit: nil, safe_mode: false, hide_deleted_posts: false)
end
# Perform a tag search as the system user, DanbooruBot. The search will
# have moderator-level permissions. No tag limit is enforced.
def system_tag_match(query)
user_tag_match(query, User.system, tag_limit: nil, safe_mode: false, hide_deleted_posts: false)
end
# Perform a tag search as the current user, or as another user.
#
# @param query [String] the tag search to perform
# @param user [User] the user to perform the search as
# @param tag_limit [Integer] the maximum number of tags allowed per search.
# An exception will be raised if the search has too many tags.
# @param safe_mode [Boolean] if true, automatically add rating:s to the search
# @param hide_deleted_posts [Boolean] if true, automatically add -status:deleted to the search
# @return [ActiveRecord::Relation<Post>] the set of resulting posts
def user_tag_match(query, user = CurrentUser.user, tag_limit: user.tag_query_limit, safe_mode: CurrentUser.safe_mode?, hide_deleted_posts: user.hide_deleted_posts?)
post_query = PostQueryBuilder.new(query, user, tag_limit: tag_limit, safe_mode: safe_mode, hide_deleted_posts: hide_deleted_posts)
post_query.normalized_query.build

View File

@@ -130,7 +130,7 @@ class SavedSearch < ApplicationRecord
return if redis.exists?(redis_key)
post_ids = Post.with_timeout(timeout, [], query: query) do
Post.system_tag_match(query).limit(QUERY_LIMIT).pluck(:id)
Post.anon_tag_match(query).limit(QUERY_LIMIT).pluck(:id)
end
if post_ids.present?

View File

@@ -144,6 +144,13 @@ class SavedSearchTest < ActiveSupport::TestCase
SavedSearch.populate("does_not_exist")
assert_equal([], SavedSearch.post_ids_for(@user.id))
end
should "not allow users to perform privileged searches" do
@flag = create(:post_flag)
@saved_search = create(:saved_search, query: "flagger:#{@flag.creator.name}", user: @user)
SavedSearch.populate("flagger:#{@flag.creator.name}")
assert_equal([], SavedSearch.post_ids_for(@user.id))
end
end
context "Creating a saved search" do