LINUX.ORG.RU

PHP7, Python3 и SQL-инъекции

 , ,


1

1

Подскажите, пожалуйста, как в седьмом пыхе и третьем питоне перегнать строку в безопасный вид, который можно было бы вставлять напрямую в sql-код, а также как потом такую строку, выращенную из бд, перегнать в прежний вид.

1) Использовать prepared statements!
2) В крайнем случае в драйвере БД должна быть функция экранирования
3) Также, в SQL стандарте есть HEX литералы строк X'value'

surefire ★★★ ()

А зачем в прежний то перегонять?) Чтобы инъекция сработала?) Из sql возвращают обычно строку как она была послана на сервак, но при выводе в HTML ее уже экранируют.

menangen ★★★★★ ()
Ответ на: комментарий от goingUp

на самом деле все это программно можно сделать: для этого нужно проescapить ' " \ \0 (удвоение, добавления слеша - в зависимости от бд). в пхп prepared statements не имели смысла, потому как жили в пределах одного запроса. в питоновских либах мне неизвестно они эмилируются или честно используются. скорее второе.

tz4678 ★★ ()
Ответ на: комментарий от tz4678

проescapить

Ещё, например, ; - с её помощью прекрасно инъекции делаются. А что ещё? Мне интересует готовый, проверенный веками, механизм.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

не делается. только перечисленные мною символы нужно экранировать.

ты не написал базу, которую будешь использовать. если без ORM, то что-то типа этого

cur = con.cursor()
cur.execute('insert into users values(NULL,%s,%s)', ('user@example.org','qweasd'))
# ...
cur.execute('select * from users limit 1;')
row = cur.fetchone()
print(row)
tz4678 ★★ ()
Ответ на: комментарий от MetalBeaver

у orm главный недостаток - это потеря гибкости, а преимущество работа с базой в объектном стиле, забывая про sql

tz4678 ★★ ()
Ответ на: комментарий от demrnd

Ну да там ООП. Оно везде в python'е. Там закос под Entity Framework из мира C#. В C# есть LINQ, которые позволяет в код эротично делать вставки чего-то похожего на SQL. Отдаленно напоминает. В пистоне нет альтернатив sqlalchemy, ну разве peewee. Самое лучшее это Django ORM, но для нее нужны тонны кала в виде Django (в эпоху микросервисов ему места в этом жестоком мире нету). Для Mongodb есть Djano-подобная ORM называется mongoengine. Ты так и не написал что там делаешь, какая тебе бпаза нужна, хотя у тебя там выбор небольшой MariaDB (aka MySQL) и Postgresql. Помследняя предпочтителнее, но смотря для каких целей. Ты можешь вообще ORM не использовать, а наплодить DAO как принято это в Java. А еще на питоне можно писать в асинхронном стиле. Когда заходит речь о преимуществах асинхронщины приводят в сравнении Nginx, однопоточный (условно-, потому как треды он все-таки использует для воркеров) сервер и жопач, который в основном работает на тредах.

tz4678 ★★ ()
Ответ на: комментарий от ggrn

если с чем-то несогласен приведи примеры, доказывающие обратное. на питоне существует три с половиной ормки (django orm,sqlalchemy,peewee,ponyorm,mongoengine), остальное внимания даже не заслуживает.

tz4678 ★★ ()
Ответ на: комментарий от tz4678

Да куда уж нам.

django orm,sqlalchemy,peewee,ponyorm,mongoengine

Жду примеров mongoengine для postgresql. И я полностью согласен что без ORM для ELK python беден. Куда там ему до C# с его LINQ. А подумать, что LINQ совсем не всем удобен (и часто вообще неудобен) не судьба. Мы ведь не видели Z SQL Methods...

demrnd ()
Ответ на: комментарий от demrnd

это джангоподобная ормка для монги. нету?! - напиши сам. я писал на сисярпе. это скорее сисярп не удобен, гибкости не хватает.

tz4678 ★★ ()
Ответ на: комментарий от tz4678

Да как бы из того что есть мне все хватает.Можно и чистый SQL использовать. Причем это не мешает мне в одном проекте сменить БД без проблем. Благо в Python нормальный db-api где sql injection сделать только если быть идиотом и постараться. https://www.python.org/dev/peps/pep-0249/#paramstyle

demrnd ()
Ответ на: комментарий от tz4678

Я написал вот такой код. Можно ли им пользоваться?

class Tools:
    @staticmethod
    def escape(text: str) -> str:
        # remove useless and dangerous zero symbol from string
        while "\0" in text:
            index = text.index("\0")
            text = text[:index] + text[index + 1:]

        # encode dangerous symbols to hex and frame them to zero symbols
        # encode ampersand also for special use
        for symbol in ["'", '"', "\\", "&"]:
            while symbol in text:
                index = text.index(symbol)
                text = text[:index] + "\0" + codecs.encode(text[index:index+1]).hex() + "\0" + text[index+1:]

        # change dangerous zero symbols to ampersands
        while "\0" in text:
            index = text.index("\0")
            text = text[:index] + "&" + text[index+1:]

        return text

    @staticmethod
    def unescape(text: str) -> str:
        # change ampersands to zero symbols back
        while "&" in text:
            index = text.index("&")
            text = text[:index] + "\0" + text[index + 1:]

        # find and decode hex fragments
        while "\0" in text:
            index = text.index("\0")
            part0 = text[:index]
            part1 = text[index+1:]
            index = part1.index("\0")
            part2 = part1[index+1:]
            part1 = part1[:index]
            text = part0 + bytes.fromhex(part1).decode() + part2

        # no need to restore zero symbols
        return text

MetalBeaver ()
Ответ на: комментарий от sekreti-gollivuda

php bin2hex(), hex2bin()

Перегонять прям всё в hex/bin - не то, что надо. Надо что-то сделать с опасными символами. А потом вернуть, как было.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

амперсанд зачем? в питоне как в яваскрипт строки иммутабельны, ты каждый раз строку копируешь в цикле это как бы иррационально. у строки есть метод translate для множественной замены, но и это тебе не нужно, потому как все коннекторы к базам поддерживают плейсхолдеры/prepared statements.

tz4678 ★★ ()
Ответ на: комментарий от tz4678

амперсанд зачем?

Он у меня обрамляет закодированные фрагменты, т.е. является служебным символом, потому в исходном тексте все амперсанды тоже перегоняются в hex.

в питоне как в яваскрипт строки иммутабельны, ты каждый раз строку копируешь в цикле это как бы иррационально.

Не в этом сейчас вообще вопрос. Я понимаю, что код очень далёк от идеала. Мне важно, чтобы он корректно и безотказно функционировал.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver
#!/usr/bin/env python
import sqlite3
con = sqlite3.connect('test.db')
con.execute("""
  create table if not exists data (
    id integer primary key autoincrement,
    content text
  );
""")
cur = con.cursor()
cur.execute('insert into data (content) values (?);', ('\0"\'', ))
cur.execute('select * from data limit 1;')
row = cur.fetchone()
print(row)
print('\0' in row[1])

Output:

(dev)  sergey@sergey-pc  ~/Development/tests  ./sql.py
(1, '\x00"\'')
True

В базе у тебя и так оригинальные символы хранятся. Нет смысла в твоих телодвижениях.

tz4678 ★★ ()
Ответ на: комментарий от tz4678

В пистоне нет альтернатив sqlalchemy

Самое лучшее это Django ORM

ggrn ★★★★★ ()
Ответ на: комментарий от sekreti-gollivuda

Это в мануале пэхэпэ описано. Оказывается у тебя простая проблемка.

Проблема пэхэпэ в том, что там далеко не одна функция для обезопасевания. Там есть и htmlspecialchars, add*slashes, *_real_escape_string, и прочие. Если ты такой шарящий, то вместо того, чтобы слать меня на... читать мануал, лучше бы написал всего два слова: функция, позволяющая перегнать текст в безопасный вид для прямой вставки в SQL-запрос, и функция, которая восстановит из этого вида в исходный. А если ещё и для питона две такие функции назовёшь - вообще красава будешь. Но ты этого не сделаешь, пока все тут только языком трепят, по существу никто ничего не сказал. Мне не нужны ваши обходные решения и нравоучения на тему, как правильно делать. Я чётко поставил задачу. Можете помочь - буду очень благодарен. Не можете - проходите, пожалуйста, мимо, ну нужно засерать тему и расписываться в своём дилетантсве.

MetalBeaver ()
Ответ на: комментарий от tz4678

В базе у тебя и так оригинальные символы хранятся. Нет смысла в твоих телодвижениях.

Спасибо, милый человек, что рассказал, как правильно делать. Но вопрос в нулевом посте поставлен именно так, как поставлен. Мне не нужно «правильное» решение, мне нужны две функции для php и две для питона.

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

тебе все написали как делать. давно бы нагуглил.

>>> tr=str.maketrans({'\0': '\\0', '"': '""', "'": "''"})                       

>>> 'This is "bad" string\0'.translate(tr)                                      
'This is ""bad"" string\\0'

tz4678 ★★ ()
Ответ на: комментарий от tz4678

Мне казалось главный недостаток десятитысячекратное падение производительности, гибкости там хватает на удовлетворение всех требований (помимо самых сумасшедших и экспериментальных).

anonymous ()
Ответ на: комментарий от tz4678

Ты сам то понял, что за бред написал?

>>> a = '\0'
>>> len(a)
1
>>> tr = str.maketrans({'\0': '\\0'})
>>> a.translate(tr)
'\\0'
>>> b = a.translate(tr)
>>> len(b)
2
>>> b[1]
'0'
>>> b[0]
'\\'

MetalBeaver ()
Ответ на: комментарий от MetalBeaver

функция, позволяющая перегнать текст в безопасный вид для прямой вставки в SQL-запрос, и функция, которая восстановит из этого вида в исходный

Фейспалм. addslashes и stripslashes устроит?

goingUp ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.