Seite 1 von 1

addslashes() in python?

Verfasst: Montag 29. August 2005, 10:07
von Daveron
Gibt es eine Funktion, die mir in einem String die Sonderzeichen so auskommentiert, das ich diesen sauber in eine SQL DB schreiben kann?

Verfasst: Montag 29. August 2005, 10:45
von jens

Verfasst: Montag 29. August 2005, 10:55
von Daveron
ich escape bereits mit %s:

sql_query = "INSERT INTO test (text) VALUES ('%s') " % inhalt

ansicht klappt das ganz gut, doch leider machen mir hochkommas probleme.

Verfasst: Montag 29. August 2005, 10:58
von jens
Damit nutzt du nicht die SQL-Escape Funktion der API! Was du machst, ist eine normale String-Operation, ohne irgendweine Escape Funtkion! Es muß beim .execute() gemacht werden!

Schau dir den anderen Thread an.

Verfasst: Montag 29. August 2005, 11:55
von Daveron
hab mir jetzt ne Funktion mit reg exp gebaut, die mir alle Sonderzeichen mit einem '\' für das SQL Statement auskommentiert.

Ich kann leider nicht einfach so die klasse für den zugriff auf die Datenbank verändern, da noch andere damit arbeiten ;P

Verfasst: Montag 29. August 2005, 12:01
von jens
Das ist allerdings keine gute Idee! SQL-Injections sind damit nicht ausgeschlossen, glaub ich...

Es gibt, zumindest bei der mySQLdb auch eine spezielle Funktion die das erledigen kann... Ich weiß jetzt nur nicht, wie die heißt... Da hilft bestimmt ein help() weiter ;)

Verfasst: Montag 29. August 2005, 13:56
von ProgChild
Daveron hat geschrieben:hab mir jetzt ne Funktion mit reg exp gebaut, die mir alle Sonderzeichen mit einem '\' für das SQL Statement auskommentiert.

Ich kann leider nicht einfach so die klasse für den zugriff auf die Datenbank verändern, da noch andere damit arbeiten ;P
Warum schreibst du dir ne Funktion, wenn dir Jens schon ne komplette Lösung anbietet? *kopfschüttel* Du solltest unter allen Umständen die Escape Sequenzen von SQL einfügen lassen :!:

Ein kleines Beispiel:

Code: Alles auswählen

query = "DELETE FROM address WHERE ID=%s"
data = ( id, )

cursor.execute( query, data )

Verfasst: Montag 29. August 2005, 16:33
von henning
Ich habe den Thread hier nur angelesen, daher keine Ahnung, ob das Problem nicht schon an sich gelöst wurde, aber ich hab mich vor kurzem auch ein bisschen damit befasst und mal eine Funktion geschrieben die potentiell bösartige strings je nachdem ob sie ein Wert oder ein "Key" (also Spalte oder Tabellenname) sein sollen, quotet.

Code: Alles auswählen

#!/usr/bin/python

"""
  save_sql.py

  Author: Henning Hasemann

  A little module ensuring that userdata wont
  hurt sql-strings, quoting tablenames, column names and
  values correctly.
  
  Note 1: You are allowed to just provide one dictionary instead
  of two. In this case, it will be used for both, keys and values.

  Note 2: Always use %(Kname)s / %(Vname)s, (pronouncing the last s),
  because all values are internally converted into strings.
  (i.e. it makes no sense to use %(Vname)d, as this simply wont work)
  
  Example:
  
  import MySQLdb
  from save_sql import mksql

  conn = MySQLdb.connect(db="MyDatabase", user="MyUser", paswd="MyPW", host="localhost")
  curs = conn.cursor()

  query = mksql("INSERT INTO %(Ktab)s (`name`, `surname`, %(Kcol3)s, `count`) VALUES (%(Vname)s, %(Vsur)s, 'X', %(Vcnt)s)",
      {"tab": "MyTable", "col3": "Some` really; unsafe stuff\\"},
      {"name": "'; DELETE", "sur": "even' unsafer`blorg", "cnt": 500})

  curs.execute(query)
  
  curs.close()
  conn.close()
  
"""

escape_keys = ("\\", "`", ";")
escape_values = ("\\", "'", ";")

def mksql(string, keys = False, values = False, **kwars):
  """Fills string. %(Ksome_name)s will be subsituted
    with the key-like (think of columns and table names) quoted
    value of keys["some_name"], while
    %(Vsomething)s will be substituted by the value-like quoted
    value of values["something"] or keys["something"] if values
    is not defined.

    Note that this function raises the usual KeyError when
    a value requested is not found in the dict."""

  if not keys:
    keys = kwars
  if not values:
    values = keys
  d = {}
  for k, v in keys.items():
    d["k" + k] = to_key(str(v))
    d["K" + k] = "`" + to_key(str(v)) + "`"
    # R is for "raw". Please use this with extreme
    # caution, since raw data is not preprocessed at all.
    # Whatever you take as raw data should
    # - not depend on user accesiable input
    # or
    # - be checked very very carefully!
    d["R" + k] = str(v)

  for k, v in values.items():
    d["v" + k] = to_value(str(v))
    d["V" + k] = "'" + to_value(str(v)) + "'"
  
  return string % d

def to_key(v):
  """Converts an unstrusted sql-key into a save one.
    Note that this DOES NOT add the ` - signs on the left
    and the right, but please dont provide them in the paramter,
    because there they will be quoted.
    You'll have to add them yourself later!
    This function will be called by mksql."""
  for r in escape_keys:
    v = v.replace(r, "\\" + r)
  return v

def to_value(v):
  """Converts an unstrusted sql-value into a save one.
    Note that this DOES NOT add the ' - signs on the left
    and the right, but please dont provide them in the paramter,
    because there they will be quoted.
    You'll have to add them yourself later!
    This function will be called by mksql."""
  for r in escape_values:
    v = v.replace(r, "\\" + r)
  return v

if __name__ == "__main__":
  # short mixed form:
  # sql-string values and keys via keywords
  print mksql("SELECT * FROM %(Ktab)s WHERE %(Kkey)s=%(Vval)s",
      tab="tabelle", key="schlüssel", val="Wert")

  # long mixed form:
  # sql-string, values and keys in one dict
  print mksql("SELECT * FROM %(Ktab)s WHERE %(Kkey)s=%(Vval)s",
      {
        "tab": "tabelle",
        "key": "schlüssel",
        "val": "Wert"
      })

  # long splitted form:
  # sql-string, dict of keys, dict of values
  print mksql("SELECT * FROM %(Ktab)s WHERE %(Kkey)s=%(Vval)s",
      {
        "tab": "tabelle",
        "key": "schlüssel",
      },
      {
        "val": "Wert"
      })
Sorry, falls das zu lang sein sollte, oder als OT empfunden wird!

Henning

Verfasst: Montag 29. August 2005, 16:41
von henning
Ich kann natürlich nicht garantieren, dass das Quoting korrekt ist, aber alle meine Versuche, da eine SQL-Injection durchzukriegen sind bis jetzt gescheitert :-)

Verfasst: Montag 29. August 2005, 16:43
von jens
henning hat geschrieben:Sorry, falls das zu lang sein sollte, oder als OT empfunden wird!
Zu lang für das Forum ist es nicht, aber zulang für das Problem ;)

Also wenn die SQL-Anbindung schon ein Escaping besitzt, warum das nicht einfach benutzten???

Schau mal mit "help(MySQLdb)" nach dem Stichwort "escape": Mir scheint das MySQLdb.escape_string() genau das macht, was ihr wollt...

Aber wie ProgChild schon geschrieben hat: Du solltest unter allen Umständen die Escape Sequenzen von SQL einfügen lassen

Verfasst: Montag 29. August 2005, 17:00
von henning
jens hat geschrieben: Also wenn die SQL-Anbindung schon ein Escaping besitzt, warum das nicht einfach benutzten???
Ganz einfach deswegen, weil ich auch Spalten- und Tabellennamen über unsichere Kanäle gechickt/empfangen habe und die dementsprechend auch gequotet haben wollte.

In der Doku zu MySQLdb wurde explizit erwähnt, dass man das Quoting, dass die bieten NUR für Werte verwenden soll.
Und dann teilweise was eigenes und teilweise das von MySQLdb zu nutzen war mir zu unübersichtlich, da fand ichs schöner, eine Funktion zu haben, die das alles erledigt.

Aber wenn man nur Werte quoten will geb ich dir natürlich Recht, reicht das Ding von der MySQLdb auch.
Aber vielleicht passt der Post ja in die Codesnippets-Ecke.

Verfasst: Dienstag 30. August 2005, 13:20
von Daveron
jo genau danach hatte ich gesucht. läuft wunderbar ;P