Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przełączanie na gotowe zestawienia

Byłem w takiej samej sytuacji. Ja też korzystałem z połączonych wyciągów, a potem przestawiłem aplikację na gotowe wyciągi.

zła wiadomość czy zamierzasz zmienić każdą instrukcję SQL zbudowaną przez połączenie danych klienta z instrukcją SQL, która będzie prawie każdą instrukcją SQL, którą masz w swoich 50 plikach źródłowych.

dobra wiadomość czy zysk z przejścia na wyciągi gotowe jest bezcenny, na przykład:

1-nigdy nie będziesz się martwić o coś, co nazywa się „atakiem wstrzyknięcia SQL”

php podręcznik mówi

Dla mnie ten powód - spokój ducha - wystarczy, aby pokryć koszty zmiany mojego kodu źródłowego. , teraz Twoi klienci mogą wpisać w polu nazwy formularza robert; DROP table students; -- ;) i czujesz się bezpiecznie, że nic się nie stanie

2- nie musisz już zmieniać parametrów klienta. możesz ich użyć bezpośrednio w instrukcji SQL, na przykład :

$query = "SELECT FROM user WHERE id = ?";
$vars[] = $_POST['id'];

zamiast

$id = $mysqli->real_escape_string($_POST['id']);
$query = "SELECT FROM user WHERE id = $id";

co musisz zrobić przed użyciem przygotowanych stwierdzeń, co narażało cię na niebezpieczeństwo zapomnienia o ucieczce od jednego parametru jako normalnego człowieka. a wszystko, czego potrzeba, aby atakujący uszkodził Twój system, to tylko 1 nieunikniony parametr.

Zmiana kodu

zazwyczaj zmiana plików źródłowych jest zawsze ryzykowna i bolesna, zwłaszcza jeśli projekt oprogramowania jest zły i jeśli nie masz oczywistego planu testowania. ale powiem ci, co zrobiłem, aby było to jak najłatwiejsze.

Stworzyłem funkcję, z której będzie korzystał każdy kod interakcji z bazą danych, dzięki czemu możesz zmienić to, co chcesz później w jednym miejscu - ta funkcja - możesz zrobić coś takiego

class SystemModel
{
    /**
     * @param string $query
     * @param string $types
     * @param array $vars
     * @param \mysqli $conn
     * @return boolean|$stmt
     */
    public function preparedQuery($query,$types, array $vars, $conn)
    {
        if (count($vars) > 0) {
            $hasVars = true;
        }
        array_unshift($vars, $types);
        $stmt = $conn->prepare($query);
        if (! $stmt) {
            return false;
        }
        if (isset($hasVars)) {
            if (! call_user_func_array(array( $stmt, 'bind_param'), $this->refValues($vars))) {
                return false;
            }
        }
        $stmt->execute();
        return $stmt;
    }

    /* used only inside preparedQuery */
    /* code taken from: https://stackoverflow.com/a/13572647/5407848 */
    protected function refValues($arr)
    {
        if (strnatcmp(phpversion(), '5.3') >= 0) {
            $refs = array();
            foreach ($arr as $key => $value)
                $refs[$key] = &$arr[$key];
                return $refs;
        }
        return $arr;
    }
}

Teraz możesz używać tego interfejsu w dowolnym miejscu w plikach źródłowych, na przykład zmieńmy bieżące instrukcje SQL, które podałeś w pytaniu. Zmieńmy to

$mysqli = new mysqli('localhost', "root", "", "testdb");
$addresult = "
                SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined 
                FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id 
                WHERE b.id = '".$inputvalues['schoolid']."'";

if( $result = $mysqli->query($addresult) ) {
    while($row = $result->fetch_all())
    {
        $returnResult = $row;
    }
}

W to

$mysqli = new mysqli('localhost', "root", "", "testdb");
$sysModel = new SystemModel();
$addresult = "
                SELECT a.firstnames, a.surname, a.schoolrole, a.datejoined
                FROM teachers a LEFT JOIN schools b ON a.schoolid = b.id
                WHERE b.id = ?";
$types = "i"; // for more information on paramters types, please check :
//https://php.net/manual/en/mysqli-stmt.bind-param.php
$vars = [];
$vars[] = $inputvalues['schoolid'];

$stmt = $sysModel->preparedQuery($addresult, $types, $vars, $mysqli);
if (!$stmt || $stmt->errno) {
   die('error'); // TODO: change later for a better illustrative output
}
$result = $stmt->get_result();
$returnResult = [];
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
    $returnResult[] = $row;
}

Tak, atak Sql Injection jest stosowany przez połączenie złego ciągu z instrukcją SQL. gdzie jest INSERT , SELECT , DELETE , UPDATE . na przykład

$query = "SELECT * FROM user WHERE name = '{$_GET['name']}' AND password = '{$_GET['pass']}'"

coś takiego mogłoby zostać wykorzystane przez

// exmaple.com?name=me&pass=1' OR 1=1; -- 

co da w wyniku instrukcję SQL

$query = "SELECT * FROM user WHERE name = 'me' AND password = '1' OR 1=1; -- '"
//executing the SQL statement and getting the result
if($result->num_rows){
    //user is authentic
}else{
    //wrong password
}
// that SQL will always get results from the table which will be considered a correct password

Powodzenia w przełączeniu oprogramowania na gotowe zestawienia i pamiętaj, że spokój ducha, jaki uzyskasz wiedząc, że cokolwiek się stanie, jesteś bezpieczny przed atakami typu SQL injection, jest wart kosztów zmiany plików źródłowych




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP/MySQL - Przechowywanie danych tablicowych w formacie JSON, złe praktyki?

  2. MySQL Używanie kolumny ciągu z tekstem daty jako polem daty

  3. Pula połączeń Perla

  4. Łączenie tabel z różnych baz danych

  5. Jaka jest właściwa konwencja nazewnictwa dla pakietów MySQL FK?