Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu sql Kanał ATOM (tag: sql)

Autor wpisu: Tomasz Kowalczyk, dodany: 02.08.2011 23:09, tagi: sql

Dzisiejszy wpis ponownie będzie krótki i prosty, ponownie też podejmę temat zapytań SQL przydatnych w codziennej pracy programisty. Czym w takim razie się zajmiemy? Otóż, w związku z tym, że "czasem" musimy wykonać pewne instrukcje w zależności od istnienia bądź nieistnienia rekordów dodanych w konkretnym przedziale czasu (np. wczoraj, w ostatnim tygodniu), w tym wpisie [...]

Autor wpisu: Tomasz Kowalczyk, dodany: 29.07.2011 22:55, tagi: sql

Pracowałem ostatnio nad skryptem galerii w jednym z projektów i w pewnym momencie natrafiłem na problem polegający na wyświetlaniu w widoku pojedynczego zdjęcia linków kierujących do następnego i poprzedniego elementu. Nie jest to pierwszy raz, kiedy zostałem zmuszony do "poradzenia sobie" z tego typu sytuacją, dlatego uznałem, że warto opisać wykorzystane rozwiązanie na blogu. Standardowo [...]

Autor wpisu: Tomasz Kowalczyk, dodany: 01.07.2011 00:22, tagi: sql, mysql

Oprogramowanie komputera zawiera w sobie wiele pułapek, o których trzeba wiedzieć, żeby w nie nie wpaść. Szczęśliwym trafem jeszcze nie miałem okazji cierpieć przez opisywany dzisiaj problem - przeczytałem o nim podczas poszukiwania informacji na temat innego, który już opisałem na niniejszym blogu. Serwer SQL, a dokładnie MySQL, to jedno z najpopularniejszych rozwiązań tej klasy, [...]

Autor wpisu: Diabl0, dodany: 29.06.2011 15:37, tagi: mysql, php, sql, zend_framework

Od jakiegoś czasu borykałem się z problemem dlaczego czasami zapisywane do bazy danych zserializowane dane są „obcinane. Poszukiwania, googlanie niewiele pomagało aż a końcu trafiłem gdzieś na informację że problemem może być znak NULL (0×00) w którym PHPowe serialize się lubuje :) . A koro tak, to postanowiłem napisać swoją wersję serialize.

Kod tutaj:

<?php
/**
 * Serializowanie i deserializowanie treści zawierających 0x00
 *
 * @category    Mao
 * @package     Mao_Serializer
 * @author      Krzysztof 'Diabl0' Szatanik
 * @copyright   Copyright (c) 2011, MAO Group
 * @version     $Id: Form.php 1164 2009-11-10 13:01:53Z diabl0 $
 */

/**
 * Własna nakładka na serializację
 *
 */
class Mao_Serializer {

	const CHAR_0x00 = '\\$0x00$/';

	/**
	 * Serializuje obiekt jak serialize() z tym że zastępuje znak 0x00
	 * aby nie sprawiał problemu przy zapisie do bazy danych
	 *
	 *
	 * @param mixed $obj
	 *
	 * @return string
	 */
	static function serialize( $obj ) {
		return str_replace( chr(0x00), self::CHAR_0x00, serialize( $obj ) );
	}

	/**
	 *
	 * Deserializuje obiekt jak unserialize() z tym że przywraca
	 * zastąpiony znak 0x00
	 *
	 * @param string $string
	 *
	 * @return mixed
	 */
	static function unserialize( $string ) {
		return unserialize( str_replace( self::CHAR_0x00, chr(0x00), $string ) );
	}

}

Użycie jest banalne:

<?php
$text = 'to jest test znaku [' . chr(0) . '] - czy sie dobrze zapisuje do bazy';
$serialized = Mao_Serializer::serialize($text);
$unserialized = Mao_Serializer::unserialize($serialized);
?>

Wiem że nie jest to idealne rozwiązanie ale na razie nie mam czasu aby przysiąść i dorobić jakąś konwersję w locie na poziomie Zend_Db_Adapter

Autor wpisu: Tomasz Kowalczyk, dodany: 24.06.2011 11:46, tagi: php, doctrine, framework, sql, symfony

Od kiedy programiści stron internetowych [i nie tylko] dostali w swoje ręce pierwsze biblioteki wspomagające technikę ORM - mapowania obiektowo-relacyjnego, stało się jasne, że w bardzo wielu przypadkach oszczędzą nam one samodzielnego pisania zapytań SQL i związanych z tym problemów i błędów. Za bardzo przyjemną abstrakcją tychże bibliotek kryje się jednak jeden problem - ze [...]

Autor wpisu: Athlan, dodany: 28.05.2011 14:40, tagi: sql, php, internet

Dziś bardzo krótko, bez zbędnych dywagacji, czyli tylko i wyłącznie o tablicy $_SERVER. Dbając o bezpieczeństwo aplikacji webowych zwraca się uwagę na wiele czynników, jakimi są SQL injections, przechwytywanie nieprawidłowych parametrów, uogólniające zapytania przepuszczające maskę % w LIKE zapytaniu do baz, XSS‘y w $_POST, $_GET.

I finalnie… wiele osób zapomina (a jeszcze więcej nie jest tego świadom) o możliwości wstrzyknięcia szkodliwych danych w $_SERVER['HTTP_X_FORWARDED_FOR'];. Konsekwencje są oczywiście katastrofalne.

O ile sama walidacja jest rzeczą wtórną, diabeł tkwi w trzech szczegółach:

  1. Rzecz trywialna, ale pamiętajmy, że w naturalnym procesie użytkowania przeglądarki, w nagłówku może zostać zwrócony nie tylko jeden adres IP, a kilka oddzielonych przecinkiem, w tym localhost‘y (standard nagłówka X-Forwarded-For).
  2. Wstrzyknięcie Javascriptów jest możliwe, ale notabene najmniej szkodliwe, bo do spreparowania nagłówka potrzebny jest bardziej zaawansowany proces (dajmy na to Data Tamping, który przedstawię poniżej), np. niż wklejenie syfu w linku/obrazku i przesłanie go komuś przez komunikator, żeby wykraść jego ciasteczka sesyjne document.cookie i przesłać je sobie na serwer w dowolny sposób, zatem atakowi nie ulegną osoby trzecie.
  3. Niepoprawność danych, które można zmanipulować, jest chyba rzeczą oczywistą: nieprzepuszczenie takich danych przez filtry może skutkować złymi wartościami zwracanymi np. przez ip2long() i zapis w zupełności nieprzydatnych nam później danych do bazy.
  4. ale największe nieprzyjemności możemy mieć przez spreparowanie lewych zapytań do baz danych, o ile nie używamy sprawdzonych ORM lub czegokolwiek, co pomaga nam filtrować wartości do niej przekazywane i używane w warunkach zapytań (data binding).

Przykład tampingu danych, żeby spreparować niepożądane efekty.

Mamy bardzo prosty, niebezpieczny kod funkcji, która pobiera pierwszy adres na liście adresów oddzielonych przecinkami z $_SERVER['HTTP_X_FORWARDED_FOR'] o ile istnieje, natomiast w przeciwnym wypadku $_SERVER['REMOTE_ADDR']:

< ?php
 
function getUserIp()
{
  if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    return trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
 
  return $_SERVER['REMOTE_ADDR'];
}
 
$sUserIP = getUserIp();
 
echo 'Hi "' . $sUserIP . '"!'; // first bug while display.
var_dump(ip2long($sUserIP)); // second bug while transforming data.
 
?>

Pora na przykład manipulacji takich danych.

  • Będziemy używać Tamper Data dla Firefox’a.Dość popularny wśród developerów addon do Firefox’a, pozwala zmodyfikować dane $_POST, $_GET, $_COOKIE, nagłówki, “w locie żądania” etc.
  • Po instalacji w menu Narzędzia pojawi się pozycja Dane Tamper, która uruchamia okienko do podsłuchiwania żądań. Po kliknięciu Rozpocznij podsłuchujemy wszystkie wychodzące żądania z naszej przeglądarki. Każde żądanie nie zostanie przepuszczone, dopóki go nie zmanipulujemy klikając Tamper, lub przepuścimy dalej klikając Wyślij.
  • Jeżeli zdecydujemy się Tamper’ować żądanie, naszym oczom ukaże się okno z parametrami. Klikamy prawym przyciskiem myszy na listę parametrów, wybieramy Dodaj i wpisujemy nasz przykładowy, brzydki dla aplikacji nagłówek: X_FORWARDED_FOR=<script>alert('Test.')</script>

Naszym oczom ukazują się co najmniej dwa błędy. Pierwszy to błąd prezentacji danych, który wykorzystuje <script>. O ile nie musimy się tym przejmować, bo naturalnie takie żądania nie są tak łatwo wysyłane, użytkownik nie może paść ofiarą ataku przez kliknięcie w link, który np. ukradnie mu ciasteczka. Dane nagłówkowe nie są w stanie być zmodyfikowane poprzez kliknięcie w link, podobnie jak z danymi $_POST (oczywiście mówimy o przypadkach trywialnych, bez javascript’owych wymuszanych submitów targetowanych do np. ramek).

Znacznie poważniejszym błędem jest konsekwencja wadliwego formatu danych, które nasza funkcja bagatelizuje. Po pierwsze mamy fałszywe dane zwracane przez ip2long(), po drugie kto powiedział, że właśnie z tej funkcji korzystamy, a nie zapisujemy danych plain’em i nie bindujemy pofiltrowanych danych lub instrukcji warunkowych zapytania przez np. sprawdzony ORM.

Rozwiązanie problemu.

Edit: Jak słusznie zauważył Zyx, zapomniałem o tym wspomnieć, że skoro mogą znaleźć się tam dowolne dane przesłane od użytkownika, nie należy tego pola traktować jako wyznacznik, że jest to numer jego IP, jest ono bezużyteczne i powoduje potencjalną lukę. Poza zabezpieczeniami to podstawowy argument, żeby o polu zapomnieć i używać $_SERVER['REMOTE_ADDR'].

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: cojack, dodany: 06.03.2011 15:37, tagi: php, sql

PHP Wczoraj pracowałem nad swoim Frameworkiem, miałem kłopot jakby sobie tu poradzić z parametrami przesyłanymi do procedur w funkcjach SQL, gdyż w każdym engine pl/sql mogą one różnie wyglądać, więc poszedłem po rozum do głowy użyłem pseudo Dekoratora działającego na małej fabryce, tylko zaś ten dekorator nie jest typową implementacją książkową. No ale dobra, do rzeczy. Problem był z utworzeniem tablicy PostgreSQL z tablicy PHP, i do jasnej cholery nie udało mi się rozwikłać tego problemu bez użycia rekurencji. Z tego powodu jestem bardzo niezadowolony, gdyż tak bardzo chciałem nie używać rekurencji w swoim kodzie, dobra stało się, może teraz słów kilka o tym typie tablicy w PostgreSQL?

Array Postgresql

Jak wiemy w php mamy tablice asocjacyjne, takich w postgresql nie ma, to jak sobie poradzić z danymi przesyłanymi do funkcji, by wiedzieć która wartość odpowiada któremu rekordowi w bazie? Trzeba przyjąć sobie jakiś schemat i się jego trzymać, nauczyłem się tego pracując wcześniejszej firmie, z czego jestem bardzo zadowolony i cenie sobie tą wiedzę do której doszedłem sam. Ale się nią z Wami podzielę.

Przykład tablicy w PostgreSQL: ‘{1234,325,513,1332}’, jest to zwykła tablica jednowymiarowa, w php zapisalibyśmy ją tak: $someArray = array(1234,325,513,1332);

Więcej tutaj: link

Przykład z życia

Proste oczywiste, nie stwarzającego żadnego problemu do odczytania. Z tym że takie tablice są rzadkością. Przeważnie operujemy na rekordach z tabeli, które posiadają unikatowy identyfikator w bazie, i właśnie on jest nam potrzebny. Jeżeli mamy pola wielokrotnego wyboru, np checkboxy, teoria, relacja jeden do wielu, jeden produkt może należeć do wielu kategorii w sklepie. No to przykład kawałka kodu html:

<label>Jakaś kategoria</label>
<input type="checkbox" name="categories[$incramentValue][id_category]" value="$jakies_id_kategorii" />
<label>Rabat dla kategorii tego produktu</label>
<input type="text" name="categories[$incramentValue][discount]" value="$jakas_wartosc_rabatu" />

To akurat jest trochę bardziej rozbudowany przykład niż ten o który mi chodziło ;d Gdyż gdybyśmy mieli tylko zwykłe przypisanie produktu do kategorii, to wystarczyło by naszej funkcji w sql 2 parametry, jeden to id produktu, a drugi to tablica z idkami kategorii, które wybraliśmy. No ale dobra, jeżeli chcemy operować czasami na paru tabelach w jednym widoku, to takie rozwiązanie jest jak najbardziej zrozumiałe, i teraz w naszej tablicy po przesłaniu do php będziemy mieli coś takiego:

array(
  $incramentValue = array(
    'id_category' => $jakies_id_kategorii,
    'discount' => $jakas_wartosc_rabatu
  )
  ... itd
)

Jak to ugryźć?

No i dobra, teraz tak mamy identyfikator kategorii i rabat jaki chcemy nadać temu produktowi w tej kategorii, można by tam jeszcze dorzucić id klienta, taki pełny system b2b (business-to-business). Mamy to co mamy, teraz tak jak pisałem już wyżej, musimy sobie przyjąć jakiś standard w sql którym w danej funkcji będziemy operować na tych tablicach, widząc po kolejności argumentów w tablicy wiemy jak byśmy chcieli by wyglądała nasza tablica w SQL, o tak: ‘{{$jakies_id_kategorii,$jakas_wartosc_rabatu},{$jakies_id_kategorii2,$jakas_wartosc_rabatu2},{…}}’ czyli np: ‘{{2,34.2},{5,12}}’. Po przesłaniu takiej tablicy do procedury w SQL musimy ją jeszcze tylko „przelecieć” i wstawić odpowiednie rekordy, a jak utworzyć taką tablicę?

Utworzenie tablicy PostgreSQL z tablicy PHP

Napisałem do tego funkcję:

   function phpArrayToPg( array $phpArray, $inner_glue = ',' ) {
      foreach( $phpArray as $key => $value ) {
         if( is_array( $value ) ) {
            $output[$key] = "{".phpArrayToPg($value, $inner_glue)."}";
         }
         else {
            if( !(int)$value )
               $output[$key] = '"'.$value.'"';
            else
               $output[$key] = (int)$value;
         }
      }
 
      return implode( $inner_glue, $output );
   }

Która się nie podoba depeszowi ;d Dlaczego? Pytał się mnie co z wartościami które będą posiadały w sobie jakieś nietypowe wartości, czyli np: ‘, \, / itp znaki escape, szczerze to mało mnie interesują takie wartości, dlaczego? Używam PDO do bindowania takich wartości, to że w stringu będzie ‘ czy \ czy ¬ a nawet ¿ jest mi to totalnie obojętne, znaki te nie wyescepują zapytania i to jest najważniejsze, a jak strzelę gafę przy validacji podczas wprowadzania wartości przez użytkowników to jest już tylko i wyłącznie mój błąd a nie że funkcji która ma na celu tylko utworzenie tablic z tablicy.

Wywołanie:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.