Ha!

Co zrobić, żeby móc sprawdzić bezpieczeństwo kodu pisanego przez niezliczoną ilość studentów, praktykantów i różnych wynajętych programistów? Oczywiście powinno być to do zrobienia automatycznie. Grep, regexpy, nieduży skrypcik w pythonie i powinienem móc w dowolnej chwili być w stanie sprawdzić, czy nie ma jakiś luk. Ale do tego potrzebny jest jakiś spójny styl kodowania. No przecież, notacja węgierska!

  1. 1. Jajcus

    Łojej... Windows API mi przypominasz (grzechy młodości)... fe!

  2. 2. mmazur

    To nie chodzi o taką notację węgierską, przeczytaj tekst :)

  3. 3. Jajcus

    O, to tej oryginalnej węgierskiej notacji nie znałem. Takie coś czasem stosuję, zresztą nie tylko ja, wystarczy spojrzeć na nazwy funkcji w curses. Jednak ja raczej używam suffiksów i podkreśleń, bo nie lubię FunkcjiPisanychDużymiLiterami i podobnieNazywanychZmiennych.

  4. 4. mmazur

    Też nie lubię TakichFunkcji i TakichZmiennych, jedynie Takieklasy robię w pythonie.

    Poza tym fajny komentarz odnośnie samej notacji: http://mimas.ceti.pl/tarpit/wpis/1116915727

  5. 5. Patrys

    Ja głównie dłubię w PHP, więc nie problem odróżnić takąFunkcję() od $takiejZmiennej ;)

  6. 6. mmazur

    Ale to właśnie w pehapie przydaje się możliwość automatycznego sprawdzania, czy sql jest wyeskejpowany, czy pobrane z browsera dane nie są jakoś głupio używane, etc.

  7. 7. Patrys

    Ja używam edytora z podświetlaniem składni (Quanta+) i każda próba wstawienia przez innych do zapytania gołej zmiennej (bez apostrofów) świeci mi po oczach. Pod tym względem jestem wyćwiczony ;]

  8. 8. mmazur

    Apostrofów? Chodzi mi o eskejpowanie wartości przy pomocy mysql_real_escape_string (i analogicznie z postgresem). No i jeszcze pilnowanie wartości liczbowych (imho najlepiej konstruować zapytania sprintfem).

  9. 9. Patrys

    U nas quotowanie wszystkich niebezpiecznych znaków odbywa się na początku każdego skryptu, potem odwołanie zwyczajowo wygląda tak:

    $engine->sql->query("
    SELECT a, b, c, d
    FROM x
    JOIN y
    ON x.w = y.w
    LEFT JOIN z
    ON x.v = z.v
    WHERE e = '$asd'
    AND f = '{$fgh->lang}'
    ");

    A wyświetlane są gołe dane z bazy (budujemy CMSy i klient musi mieć w razie czego możliwość wpisania dowolnego kodu HTML np. w treść artykułu).

  10. 10. Jajcus

    Najlepiej używać sensownego API. Takiego, w którym podajesz zapytanie wraz z parametrami, a API samo cytuje co trzeba. Np. Pythonowe DB-API 2.0 i templaty takie jak ZPT, czy te Nevow.
    Używanie sprintów, $zmienna w zapytaniach SQL czy generowanym kodzie HTML, to zawsze proszenie się o kłopoty. A ręczne używanie różnych quote() i escape() jest po prostu niewygodne, nieeleganckie i łatwo tego zapomnieć. W tym przypadku HN to tylko łata do zalepiania słabosci API.

  11. 11. Jajcus

    A nie lepiej byłoby coś w rodzaju:

    $engine->sql->query("
    SELECT a, b, c, d
    FROM x
    JOIN y
    ON x.w = y.w
    LEFT JOIN z
    ON x.v = z.v
    WHERE e = %1
    AND f = %2
    ", $asd, $fgh->lang );

    Gdzie API robiłoby quotowanie? Przy okazji różne NULL/nil, czy co tam w tym PHP macie działało by od kopa tam gdzie trzeba.

  12. 12. Patrys

    Tak kiedyś było, ale kiedy robi się inserta na 20+ wartości, to przy liście parametrów robi się niezły burdel. Tak mamy kompromis - czytelnie i bezpiecznie.

    IMHO samo wcinanie kodu SQL tak jak zwykłego kodu już znacznie poprawia czytelność i pozwala wygodnie znaleźć potencjalne problemy.

  13. 13. Jajcus

    Patrys: w pythonowym DB-API można podać (i ja zawsze podaje) słownik (tablicę asocjacyjną/hashującą, czy jak to się u was nazywa) — wtedy w zapytaniu (jasne, że wciętym jak należy) pojawiają się nazwy zmiennych, ale zawartości zmiennych nie muszę nigdzie specjalnie przygotowywać. Mogą nawet zawierać wartości boolean, czy DateTime i zostaną w odpowiedniej postaci umieszczone w zapytaniu.

  14. 14. Jajcus

    oj, rozpędziłem się... dane są wprowadzane w formacie użytym w wyrażeniu formatującym w zapytaniu (coś jak sprintf), a nie zależnym od typu zmiennej... ale i tak działa to nieźle :-)

  15. 15. mmazur

    Najlepszym kompromisem byłoby chyba coś w deseń pythonowej notacji słownikowej:
    "%(nazwa)s" % slownikzezmiennymi

    A co do tego, co pokazałeś, Jajcuś, to niegłupim pomysłem byłoby chyba jawne castowanie argumentów niestringowych. Tzn:
    "SELECT teskt FROM kloczektable WHERE miesiac = %1", (int)$miesiac

  16. 16. Patrys

    Jajcuś: wiem, znam Pythona :)

    Problem w tym, żeby nie poświęcać więcej czasu na pisanie zapytań SQL niż na resztę kodu, a w moim przypadku samo przekonanie części zespołu, że programowanie na klasach i mikrofunkcjach jest lepsze niż jedna wielka funkcja, graniczyło z cudem. Nie mówię o zmuszeniu ich do wdrożenia tego...

  17. 17. mmazur

    Ja mam studentów, praktykantów i innych takich. Generalnie z przekonaniem to nie problem, tylko ani ja nie mam nad nimi władzy decyzyjnej, ani nie mam z nimi kontaktu, bo nie ja nimi zarządzam :)

  18. 18. Jajcus

    Patrys: rozumiem. Piszę jak jest najlepiej robić, a nie co jest najlepsze w konkretnym, praktycznym przypadku. To, niestety, zupełnie odrębne sprawy.

    mmazur: poczytaj o tym DB-API, naprawdę. Żebyś jakiś głupot nie robił, jak będziesz chciał coś w Pythonie bazodanowego pisał. Używając operatora % tracisz najważniejsze z tego co piszę. A reszta wygląda właśnie tak samo (co jest IMHO problemem, bo aż się prosi o użycie "%" zamiast ",", co od razu z ładnego kodu robi dziurę).

Adde commentarium: (textile lite)