Opublikowano 5 Grudnia 20245 Gru Programista Ta odpowiedź cieszy się zainteresowaniem. Nie będę się zbyt dużo rozpisywał. Przykładowy skrypt, który może wywalić nam całą bazę danych: 🔐 Ukryta Treść 🔐 Zaloguj się lub Zarejestruj się Opcje na zabezpieczenie przed tego typu atakiem są co najmniej 3, przedstawię Wam każdą którą znam. Sposób pierwszy - modyfikacja zapytania przed jego wykonaniem: Otwieramy plik: /game/src/db.cpp Wykonujemy następujące kroki: 🔐 Ukryta Treść 🔐 Zaloguj się lub Zarejestruj się Sposób drugi - wyłączenie opcji "multi zapytań" w libsql: Otwieramy plik: /libsql/AsyncSQL.cpp Wykonujemy następującą modyfikację: 🔐 Ukryta Treść 🔐 Zaloguj się lub Zarejestruj się Sposób trzeci - blokada uprawnień "mt2" w bazie danych: Aby to zrobić wykonujemy bardzo proste zapytanie na naszej bazie danych: 🔐 Ukryta Treść 🔐 Zaloguj się lub Zarejestruj się Jeśli macie jeszcze jakieś propozycje jak można zabezpieczyć się przed tego typu atakiem to piszcie śmiało w temacie. Chętnie poznam Wasze pomysły. Edytowane 5 Grudnia 20245 Gru przez KoYGeR
Opublikowano 5 Grudnia 20245 Gru Ten dopisek "nawet na plikach martysamy" jest zabawny, bo to przecież tyczy się dosłownie wszystkiego związanego z serwisami online i bazami danych. Jeżeli chodzi o fixa, ja bym to bardziej nazwał takim safety checkiem bo to niczego realnie nie fixuje. Dalej nie można zapominać o escape stringu przy przyjmowaniu inputu.
Opublikowano 5 Grudnia 20245 Gru Autor Programista Godzinę temu, MysteriousDev napisał(a): Ten dopisek "nawet na plikach martysamy" jest zabawny, bo to przecież tyczy się dosłownie wszystkiego związanego z serwisami online i bazami danych. Jeżeli chodzi o fixa, ja bym to bardziej nazwał takim safety checkiem bo to niczego realnie nie fixuje. Dalej nie można zapominać o escape stringu przy przyjmowaniu inputu. Dlatego najlepiej jest zadbać o odpowiednie uprawnienia użytkowników bazy danych i zwykłe zapytania zastąpić procedurami : )
Opublikowano 5 Grudnia 20245 Gru 26 minut temu, KoYGeR napisał(a): Dlatego najlepiej jest zadbać o odpowiednie uprawnienia użytkowników bazy danych i zwykłe zapytania zastąpić procedurami : ) Gratulacje koyger. Wygyrwasz złotą łopatę za odkrycie buga na którego jest alternatywny fix na mpcforum od prawia 10lat.
Opublikowano 5 Grudnia 20245 Gru 21 minut temu, KizioRCK napisał(a): Gratulacje koyger. Wygyrwasz złotą łopatę za odkrycie buga na którego jest alternatywny fix na mpcforum od prawia 10lat. Nawet jeśli to co z tego? Ktoś kto sobie z tym zaczyna na świeżo szuka aktywnego forum, nie siedzi na martwym, wiec nie znając sie zbytnio na większości rzeczach dostaje taka osoba całkiem przydatną rzecz. Nikt nie szuka na siłę na starcie konkretnych błędów. Więc takie ironie zostaw dla siebie... Na początku tego forum była kulturka, a zaczyna za dużo ludzi przychodzić, którzy zamiast pomóc to tylko komentują, wyśmiewają, a sami ch... sie znają.
Opublikowano 5 Grudnia 20245 Gru Autor Programista 23 minuty temu, KizioRCK napisał(a): Gratulacje koyger. Wygyrwasz złotą łopatę za odkrycie buga na którego jest alternatywny fix na mpcforum od prawia 10lat. To prawda. Na epvp również jest ten "fix". W mojej wersji masz przedstawione dobre praktyki w postaci "clean code".
Opublikowano 6 Grudnia 20246 Gru Najlepszym rozwiązaniem jest użycie: prepared statements przy uzyciu MySQL Connector/C++ / MariaDB Connector/C++ przy budowanniu zapytania SQL Edytowane 6 Grudnia 20246 Gru przez Eclipse Shade
Opublikowano 6 Grudnia 20246 Gru 10 minut temu, Eclipse Shade napisał(a): Najlepszym rozwiązaniem jest użycie: prepared statements przy uzyciu MySQL Connector/C++ przy budowanniu zapytania SQL To podrzuć nam rozwiązanie 😄
Opublikowano 7 Grudnia 20247 Gru Autor Programista 12 godzin temu, Eclipse Shade napisał(a): Najlepszym rozwiązaniem jest użycie: prepared statements przy uzyciu MySQL Connector/C++ / MariaDB Connector/C++ przy budowanniu zapytania SQL Specjalnie dla Ciebie (pisane na kolanie) prepared statements: Otwieramy plik: /game/src/db.h // class DBManager // Add: CAsyncSQL* GetDatabaseConnection() { return &m_sql_direct; } Przykład użycia w pliku: /game/src/messenger_manager.cpp // Add: #include "../../libsql/Statement.h" // Search for: DBManager::instance().Query("DELETE FROM messenger_list%s WHERE account='%s' AND companion = '%s'", get_table_postfix(), __account, __companion); // Replace with: std::unique_ptr<CStmt> pstmt = std::make_unique<CStmt>(); pstmt->Prepare(DBManager::instance().GetDatabaseConnection(), "DELETE FROM `messenger_list` WHERE `account` = ? AND `companion` = ?"); pstmt->BindParam(MYSQL_TYPE_STRING, &__account, sizeof(__account)); pstmt->BindParam(MYSQL_TYPE_STRING, &__companion, sizeof(__companion)); pstmt->Execute(); Wiadomo, można to dużo ładniej napisać, ale jak za darmo to i ocet słodki. Pozdrawiam cieplutko. Edytowane 7 Grudnia 20247 Gru przez KoYGeR
Opublikowano 3 Stycznia3 Sty '; EXEC xp_cmdshell 'ping -t 192.168.1.1'; -- tak chyba wszyscy zapominają to tylko tak wspomnę w tym temacie że atakiem sql injection, mozna równiez wykonać w tym samym atak DDo'S, czy skryptami w http masowo uruchamianymi. bądź drugi przykład; x' AND BENCHMARK(999999,BENCHMARK(999999,BENCHMARK(999999,MD5(NOW()))))=0 OR '1'='1 dlatego lepiej aby sobie każdy zabezpieczył, różnymi metodami 😜
Opublikowano 4 Stycznia4 Sty Programista Zamiast substr możemy użyć prostego erase: void FixQuery(std::string& query) { auto const result = query.find(';'); if (result == std::string::npos) return; query.erase(result); } W każdym razie temat dobry, warto mieć takie rzeczy na uwadze, pozdrawiam Edytowane 4 Stycznia4 Sty przez Thorek
Opublikowano 5 Stycznia5 Sty bool IsPotentialInjection(const std::string& query) { const std::vector<std::string> dangerous_patterns = { "'", "--", ";", "/*", "*/", "xp_", "BENCHMARK", "SLEEP", "DROP", "EXEC", "UNION", "OR 1=1", "AND 1=1", "CHAR(", "LOAD_FILE" }; std::string normalized_query = query; std::transform(normalized_query.begin(), normalized_query.end(), normalized_query.begin(), ::toupper); for (const auto& pattern : dangerous_patterns) { if (normalized_query.find(pattern) != std::string::npos) { return true; } } return false; } void DBManager::Query(const char* c_pszFormat, ...) { char szQuery[4096]; va_list args; va_start(args, c_pszFormat); vsnprintf(szQuery, sizeof(szQuery), c_pszFormat, args); va_end(args); if (IsPotentialInjection(szQuery)) { sys_log(0, "Potential SQL Injection detected in Query: %s", szQuery); return; } m_sql.AsyncQuery(szQuery); } std::unique_ptr<SQLMsg> DBManager::DirectQuery(const char* c_pszFormat, ...) { char szQuery[4096]; va_list args; va_start(args, c_pszFormat); vsnprintf(szQuery, sizeof(szQuery), c_pszFormat, args); va_end(args); if (IsPotentialInjection(szQuery)) { sys_log(0, "Potential SQL Injection detected in DirectQuery: %s", szQuery); return nullptr; } return m_sql_direct.DirectQuery(szQuery); }
Opublikowano 5 Stycznia5 Sty Programista 53 minuty temu, Think napisał(a): bool IsPotentialInjection(const std::string& query) { const std::vector<std::string> dangerous_patterns = { "'", "--", ";", "/*", "*/", "xp_", "BENCHMARK", "SLEEP", "DROP", "EXEC", "UNION", "OR 1=1", "AND 1=1", "CHAR(", "LOAD_FILE" }; std::string normalized_query = query; std::transform(normalized_query.begin(), normalized_query.end(), normalized_query.begin(), ::toupper); for (const auto& pattern : dangerous_patterns) { if (normalized_query.find(pattern) != std::string::npos) { return true; } } return false; } void DBManager::Query(const char* c_pszFormat, ...) { char szQuery[4096]; va_list args; va_start(args, c_pszFormat); vsnprintf(szQuery, sizeof(szQuery), c_pszFormat, args); va_end(args); if (IsPotentialInjection(szQuery)) { sys_log(0, "Potential SQL Injection detected in Query: %s", szQuery); return; } m_sql.AsyncQuery(szQuery); } std::unique_ptr<SQLMsg> DBManager::DirectQuery(const char* c_pszFormat, ...) { char szQuery[4096]; va_list args; va_start(args, c_pszFormat); vsnprintf(szQuery, sizeof(szQuery), c_pszFormat, args); va_end(args); if (IsPotentialInjection(szQuery)) { sys_log(0, "Potential SQL Injection detected in DirectQuery: %s", szQuery); return nullptr; } return m_sql_direct.DirectQuery(szQuery); } Dzięki temu czemuś zwykłe zapytanie może zostać zablokowane xD Edytowane 5 Stycznia5 Sty przez Thorek
Opublikowano 5 Stycznia5 Sty Godzinę temu, Thorek napisał(a): Dzięki temu czemuś zwykłe zapytanie może zostać zablokowane xD nope
Opublikowano 5 Stycznia5 Sty Programista 2 godziny temu, Think napisał(a): nope SELECT x FROM y WHERE z = 'wartość' mówi to panu coś?
Nie będę się zbyt dużo rozpisywał.
Przykładowy skrypt, który może wywalić nam całą bazę danych:
Opcje na zabezpieczenie przed tego typu atakiem są co najmniej 3, przedstawię Wam każdą którą znam.
Sposób pierwszy - modyfikacja zapytania przed jego wykonaniem:
Otwieramy plik: /game/src/db.cpp
Wykonujemy następujące kroki:
Sposób drugi - wyłączenie opcji "multi zapytań" w libsql:
Otwieramy plik: /libsql/AsyncSQL.cpp
Wykonujemy następującą modyfikację:
Sposób trzeci - blokada uprawnień "mt2" w bazie danych:
Aby to zrobić wykonujemy bardzo proste zapytanie na naszej bazie danych:
Jeśli macie jeszcze jakieś propozycje jak można zabezpieczyć się przed tego typu atakiem to piszcie śmiało w temacie. Chętnie poznam Wasze pomysły.
Edytowane przez KoYGeR