search: fix info leak when searching nested associations.

Fix an exploit in #4553. It was possible to use nested searches to infer
the contents of private forum posts.

For example:

* https://danbooru.donmai.us/users?search[forum_posts][id]=121683&search[forum_posts][body_matches]=h*
* https://danbooru.donmai.us/users?search[forum_posts][id]=121683&search[forum_posts][body_matches]=he*
* https://danbooru.donmai.us/users?search[forum_posts][id]=121683&search[forum_posts][body_matches]=hel*
* https://danbooru.donmai.us/users?search[forum_posts][id]=121683&search[forum_posts][body_matches]=hell*
* https://danbooru.donmai.us/users?search[forum_posts][id]=121683&search[forum_posts][body_matches]=hello*

The above searches returned the user 'albert', indicating that the
private forum post with id 121683 starts with the word 'hello'.

By guessing the id of a private forum post (which can be done by
searching for gaps in the id sequence), and by guessing text within the
post (which can be done by sequentially guessing characters with
wildcard searches), one could eventually infer the full text of a
private forum post.

The fix is to make nested searches only return records that are visible
to the current user.
This commit is contained in:
evazion
2020-08-18 12:49:38 -05:00
parent 86c376e90d
commit 70b82010a7
2 changed files with 32 additions and 18 deletions

View File

@@ -82,6 +82,19 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
should respond_to_search(posts_tags_match: "touhou").with { @uploader }
should respond_to_search(posts: {rating: "e"}).with { @other_user }
should respond_to_search(inviter: {name: "yukari"}).with { @other_user }
context "a user with private forum posts" do
setup do
as(@user) do
@private_post = create(:forum_post, body: "private", creator: @user, topic: create(:mod_up_forum_topic))
@public_post = create(:forum_post, body: "public", creator: @user)
end
end
# should ignore the existence of private forum posts the current user doesn't have access to.
should respond_to_search(forum_posts: { body: "private" }).with { [] }
should respond_to_search(forum_posts: { body: "public" }).with { [@user] }
end
end
end