Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: cichy, dodany: 27.11.2013 01:33, tagi: php

Full Path Disclosure (FPD)  w skrócie to podatność aplikacji i/lub konfiguracji serwera polegająca na upublicznieniu pełnej ścieżki dostępu do plików. Z pozoru niegroźna rzecz może być kluczowa dla przeprowadzenia bardziej szkodliwych ataków wymagających znajomości wspomnianej lokalizacji plików. W tym wpisie chciałbym pokazać tą podatność zarówno od strony atakującego jak i od strony osoby zajmującej się serwerem / aplikacją internetową podatną na FPD. Środowisko testowe zostało zbudowane z podatnej aplikacji napisanej w języku PHP na serwerze Apache 2.

1. FPD – jak wykryć podatność

Wśród technik wykorzystania tej podatności najprostszą jest po prostu próba przemycenia innego typu parametrów niż spodziewa się skrypt. Jako przykład może posłużyć nam adres:

http://example.com/index.php?page=Home

widząc taki adres możemy sobie zadać pytanie a co jeżeli skrypt otrzyma dane innego typu ? prowadzeni tą myślą wpisujemy w przeglądarce zmieniony URL:

http://example.com/index.php?page%5B%5D=Home

Jeżeli aplikacja nie sprawdza typu zmiennej $_GET['page'] oraz serwer jest błędnie skonfigurowany możemy zobaczyć coś takiego:

Notice: Array to string conversion in /var/users/janek/www/index.php on line 13

Jak widać niechciany komuniakt o błędzie zawiera pełną ścieżkę do pliku index.php.

Druga metoda, którą chciałbym przedstawić dotyczy zależności w plikach php wyobraźmy sobie sytuację w której mamy 3 pliki:

1.php o treści

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

Autor wpisu: matipl, dodany: 26.11.2013 09:55, tagi: php

Temat co jakiś czas wraca w dyskusjach i przez niektórych uznawany jest za trudny. Nic bardziej mylnego, sprawę można zamknąć w kilku linijkach kodu.

Ostatnio zetknąłem się z integrację aplikacji z API, które oferuje jeden z dostawców „chmur”. Dość specyficznie obsługują upload, oferując tak naprawdę tylko przesył danych (POST), bez zapewnienia dodatkowych możliwości.

Jeśli użyjemy do tego CURL-a, kilka funkcji możemy uzyskać sami. Jedną z takich funkcji jest chociażby stan postępu wgrywania pliku. CURL jest biblioteką napisaną w C, dzięki temu możemy skorzystać np. z wywołania zwrotnego, który wygląda w oryginale tak:

typedef int (*curl_progress_callback)(void *clientp,
                                      double dltotal,
                                      double dlnow,
                                      double ultotal,
                                      double ulnow);

W takim wypadku definiujemy na jego wzór własną funkcję zwrotną. W najprostszej postaci może wyglądać tak:

function progress($clientp, $dltotal, $dlnow, $ultotal, $ulnow) {
    if ($ulnow > 0) {
        echo round($ulnow / $ultotal * 100, 2) . PHP_EOL;
    }
}

Pozostaje już tylko użyć tej funkcji w naszym wywołaniu CURL-a:

$args = array();
$args['SourceFile_1'] = new CurlFile('plik.jpg', 'application/octet-stream', 'plik.jpg');

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progress');
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
$response = curl_exec($ch);

Oczywiście w prawdziwym przypadku musimy jeszcze zaiinicjować $ch, zalogować się lub ustawić odpowiednie nagłówki uwierzytelniające, oraz odpowiednio zdefiniować zwrotkę z funkcji progress, aby móc to odebrać jako np. JSON w przeglądarce. A resztą zajme się już człowiek od frontendu ;)

Autor wpisu: matipl, dodany: 18.11.2013 09:32, tagi: php, mysql, sql

MariaDB - MySQL

W ostatnim czasie kilkukrotnie już zdarzyło się, że osoba z którą rozmawiałem sądziła, że MariaDB to zupełnie nowy silnik bazodanowy niekompatybilny z MySQL.

Nic bardziej mylnego. Sytuacja wygląda bardzo podobnie do tej z OpenOffice sprzed kilku lat. Jak pamiętacie w 1999 roku firma Sun Microsystems przejęła produkty firmy StarDivision i udostępniła pod nazwą StarOffice. Pakiet był darmowy, ale zamknięty ze silnym wsparcie od firmy Sun. W 2002 roku pojawiła się pierwsza wersja OpenOffice, na której bazował StarOffice 6.0. Był to bardzo popularny zabieg w tamtym czasie (patrz OpenSUSE, CentOS). Firma wydawała otwartą, darmową wersję community rozwijaną przez społeczność, następnie markowała swoją marką i rozprowadzała za odpowiednie benefity (często w formie płatnego supportu).

Nie wszystko układało się jednak najlepiej, ale w takim zawieszeniu środowisko współtwórców OO trwało przez wiele lat. W 2010 roku firma Oracle przejęła Sun i wszelkie projekty, w tym OpenOffice/StarOffice. Środowisko open-source było zaniepokojone poczynaniami Oracle (np. pozwy w sprawie korzystania z Javy w Androidzie) i postanowiono zupełnie oddzielić się od korporacyjnych wpływów – powstał LibreOffice.

To tak w sporym skrócie. Co wspólnego ma z tym MySQL? MySQL tworzony był przez szwedzką firmę MySQL AB, która została wykupiona przez Sun w 2008 roku, a ta została przejęta… Zgadza się, przez Oracle w 2010 roku. Ale już w 2004 roku środowisko wolnego oprogramowania zaczęło mieć „problemy” z MySQL, a dokładniej programiści chociażby PHP. Wszystko z powodu zmian w licencji MySQL od wersji 4.1, ponieważ od tego momentu MySQL na darmowej licencji można było używać wyłącznie do zastosowań niekomercyjnych. W momencie przejęcia przez Sun, jeden z twórców MySQL (Monty Widenius) stworzył forka MySQL pod nazwą MariaDB.

MariaDB

MariaDB jest oparta na tym samym kodzie co MySQL, ale rozpowszechniana tylko na licencji GPL. Twórcy starają się utrzymywać ciągłą kompatybilność do pierwowzoru – MySQL. Produkt ma być dostępny zawsze na licencji GPL, czego nie można powiedzieć o przyszłości MySQL od Oracle.

Do wersji 5.5 (aktualna stabilna) MariaDB jest numerowana identycznie do MySQL i kompatybilna w pełni. Natomiast następcą MariaDB 5.5 będzie MariaDB 10 (obecnie w fazie rozwoju, będzie częściowo kompatybilna z MySQL 5.6).

Percona Server

Firma Percona natomiast stworzyła fork MySQL zastępując jej silnik innoDB (względy licencyjne) silnikiem pisanym przez zespół XtraDB. Głównym powodem wprowadzenia własnych zmian była słaba skalowalność bazy MySQL w oryginale.

Percona Server jest w stanie skalować się aż na 48 rdzeni procesora. Podobnie jak MariaDB, również Percona Server od wersji 5.6 nie będzie w pełni kompatybilna z MySQL 5.6. Percona Server wykorzystuje natomiast dobre smaczki z MariaDB, oraz pewne udostępnione fragmenty kodu przez Google (np. SHOW USER/TABLE/INDEX).

Percona Server 5.5 udostępniona jest na wersji CC BY-SA 2.0.

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

Autor wpisu: Jacek Skirzyński, dodany: 11.11.2013 23:22, tagi: php

Pracując przy projekcie programistycznym, oprócz pisania kodu trzeba też m.in. zarządzać projektem – może to być uruchomienie testów, skonfigurowanie projektu czy wdrożenie projektu etc. Z reguły każde z takich zadań wymaga wykonania jakichś operacji, często wielu i w określonej kolejności – w tym miejscu „zapala się lampka”. Takie operacje można, a nawet trzeba, zautomatyzować! Dzięki temu uniknie się błędów wynikających z rutyny, znudzenia wykonywaniem ciągle tych samych operacji, bo czas można poświęcić na ciekawsze sprawy.

Dla programistów Javy znajomo brzmi nazwa Ant. Dla programistów PHP istnieje podobne narzędzie o nazwie Phing. W obu przypadkach, w skrócie, chodzi o możliwość „oprogramowania” różnych zadań związanych z projektem i późniejsze tylko uruchamianie odpowiednich procedur, które aplikacja zrobi za użytkownika.

Tym wpisem chciałbym rozpocząć cały cykl wpisów na temat narzędzia Phing, a ponieważ to pierwszy wpis zacznijmy od podstaw.

Instalacja

Instalacja narzędzia jest możliwa na kilka sposobów, wszystkie opisane są na tej stronie: http://www.phing.info/trac/wiki/Users/Installation. Poprawność instalacji, można zweryfikować poleceniem w konsoli:

root@cim-k52:~# phing -version
Phing 2.6.1

Użycie

Użycie Phinga do zarządzania projektem opiera się na utworzeniu i wypełnieniu pliku build.xml. Jak wskazuje rozszerzenie jest to plik XML. Dzięki temu nie trzeba się uczyć nowej składni (wystarczy znajomość podstaw XML). Dodatkowo działanie Phinga jest niezależne od systemu operacyjnego (włącznie ze ścieżkami do plików). Oprócz build.xml bardzo przydatne są pliki właściwości (*.properties), które są źródłem danych dla skryptu1.

Na początek kilka „słów kluczowych” odnośnie projektu z perspektywy Phing:

  • project (projekt) – <project> to główny element w pliku build.xml, tzw. root node; definuje projekt, jego nazwę, opis, domyślny cel; dokumentacja
  • target (cel) – <target> definiowane cele, które będzie można później wywoływać, np. konfiguracja projektu, wdrożenie na środowisko, uruchomienie testów; cele składają się z wywołań zadań; dokumentacja
  • properties (właściwość) – <property> pozwala definiować właściwości, które w grunie rzeczy oznaczają zmienne skryptu; dokumentacja
  • task (zadanie) – to konkretne zadania, których wykonanie składa się na osiągnięcie celu, np. skopiowanie/przeniesienie pliku, wgranie na serwer; w dokumentacji można znaleść listę dostępnych zadań

Na koniec pierwszego wpisu testowe uruchomienie, poniżej treść pliku build.xml:

<?xml version="1.0" encoding="UTF-8"?>

<project name="HelloWorld" default="hello">

    <property name="who"  value="World" />

    <target name="hello">
	<echo>Hello ${who}</echo>
    </target>

</project>

Plik build.xml najlepiej umieścić w głównym katalogu projektu. Podstawowym sposobem użycia jest wywołanie w katalogu zawierającym plik skryptu z poziomu konsoli:

cim@cim-k52:~/public_html/Phing$ phing hello
Buildfile: /home/cim/public_html/Phing/build.xml

HelloWorld > hello:

     [echo] Hello World

BUILD FINISHED

Total time: 0.0559 seconds

W powyższym przypadku wywołanie phing i phing hello daje ten sam efekt, ponieważ cel hello jest domyślnym celem projektu.

Komunikaty na konsoli pozwalają śledzić operacje (cele i zadania) wykonywane przez Phing (co jest szczególnie przydatne przy wywoływaniu celów, które zależą od osiągnięcia innych celów). Na koniec pojawia się komunikat o „BUILD FINISHED” informujący o poprawnym zakończeniu pracy, w innym wypadku pojawi się „BUILD FAILED” ze szczegółowym komunikatem błędu.

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

Autor wpisu: Łukasz Socha, dodany: 11.11.2013 13:38, tagi: php

Wczytywanie różnego rodzaju plików (zdjęć, dokumentów PDF itp) jest podstawową funkcją niemal każdego serwisu (niezależnie czy chodzi o backend, czy frontend). Jeszcze niedawno operacja ta była dostępna tylko za pomocą znacznika <input type=”file” /> (pomijam wykorzystanie Flasha i Javy), ale taki sposób nie był nigdy ani wygodny, ani estetyczny. Na szczęście, wraz z nadejściem HTML5 mamy takie zdarzenia JS jak drop i dragover.

Dzięki tym zdarzeniom oraz obiektowi XMLHttpRequest możemy przeciągać i wysyłać pliki tak łatwo jak w aplikacjach deskopowych. Spójrzmy na kod.

<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
        <style>
            body{
                font-size: 12px;
                font-family: Arial;
                color: #000000;
            }
            #drop_zone{
                padding: 20px;
                width:150px;
                border: 1px dashed #000000;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <form method="post" action="upload.php" enctype="multipart/form-data">
            <div id="drop_zone">Przeciągnij tutaj plik</div>
            <output id="list"><ul></ul></output>
        </form>
        <script type="text/javascript">
            function handleFileSelect(evt) {
                xhr = new XMLHttpRequest();
                evt.stopPropagation();
                evt.preventDefault();

                var files = evt.dataTransfer.files; // FileList object.

                // files is a FileList of File objects. List some properties.
                var output = '';
                f = files[0];
                output += '<li><strong>' + escape(f.name) + '</strong> (' + f.type + ') - ';
                output += f.size + ' bytes, last modified: ';
                output += '<span class="info"></span></li>';
                $("#list ul").append(output);
                xhr.open("post", "upload.php", true);
                xhr.upload.onprogress = function(e) {
                    if (e.lengthComputable) {
                        var percentComplete = (e.loaded / e.total) * 100;
                        console.log(percentComplete + '% uploaded');
                        $("#list li:last .info").html("Wgrywanie..." + parseInt(percentComplete) + " %");
                        $("#drop_zone").html("Proszę czekać...");
                    }
                };
                xhr.onload = function() {
                    // do something to response
                    console.log(this.responseText);
                    $("#list li:last").css("color", "#008416");
                    $("#list li:last .info").html("Wczytano plik!");

                    $("#drop_zone").html("Przeciągnij tutaj plik");
                };
                var formData = new FormData();
                formData.append('file', f);
                xhr.send(formData);
            }

            function handleDragOver(evt) {
                evt.stopPropagation();
                evt.preventDefault();
                evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
            }

            // Setup the dnd listeners.
            var dropZone = document.getElementById('drop_zone');
            dropZone.addEventListener('dragover', handleDragOver, false);
            dropZone.addEventListener('drop', handleFileSelect, false);
        </script>
    </body>
</html>

W funkcji handleFileSelect() za pomocą evt.dataTransfer.files pobieramy tablicę przeciągniętych plików. Następnie, za pomocą XMLHttpRequest przesyłamy plik na serwer. Dodatkowo dodałem komunikaty dla użytkownika informujące o „postępach” wysyłania plików.

Działanie skryptu możecie zobaczyć na tej stronie. Zachęcam do podejrzenia konsoli w Fireburgu :) .

Autor wpisu: matipl, dodany: 10.11.2013 10:45, tagi: php

speed up

W 2010 roku polecałem Wam korzystanie z APC, który miał w tamtym czasie bardzo dobre wsparcie, a na zaczął wtedy dominować PHP 5.3. APC z którego przede wszystkim wykorzystywano mechanizm cache opcode sprawiał się wyśmienicie, a w kodzie aplikacji nie trzeba było nic dostosowywać.

Niestety, dla nas wszystkich, w marcu 2012 roku ukazał się udoskonalony PHP (5.4), a do dzisiaj nie ukazała się stabilna wersja obsługująca tę wersję języka. Oczywiście APC działa pod PHP 5.4, ale w pewnych sytuacjach nie bardzo dogaduje się z PHP sypiąc segfault, lub po prostu kończąc wątek.

Całe szczęście na rynku pojawił się PHP 5.5, który oferuje nam możliwość skorzystania z wbudowanego akceleratora PHP – opcache szybszego o około 10-15% od APC. W początkowej wersji (5.5.0) posiadał jeszcze sporo niedociągnięć, ale obecnie można opcache (7.0.2) polecić. Jeśli mamy już PHP 5.5 wystarczy  w php.ini wprowadzić następującą modyfikacje:

opcache.enable=On

zend_extension=opcache.so

Opcache posiada zbliżone możliwości konfiguracji jak APC. Zalecane przełączniki dla opcache przez twórców:

opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

Niestety, tak jak pisałem na Twitterze, opcache nie spełnia specyficznych wymagań. Jeśli na serwerze posiadacie serwisy chrootowane, które mają zbliżoną strukturę ścieżek to opcache zgłupieje. Nie bierze pod uwagę użytkownika jako który jest uruchamiany, ani ścieżki nadrzędnej, tylko te w chroot które są identyczne. W tym momencie jedynym pomysłem jest użycie unikalnych nazw katalogów zamiast docroot/.

Użytkownicy PHP 5.2, 5.3 i 5.4 nie muszą jednak ronić łez, opcache dostępny jest dla nich w PECL.

Jeśli potrzebujecie podejrzeć jak sprawuje się opcache, podobnie jak dla APC istnieje jedno plikowy opcache-status. Wystarczy umieścić go na serwerze i wywołać przez http.

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