Когда приложение PHP устанавливает соединение с базой данных, оно, конечно, обычно должно передать логин и пароль. Если я использую для своего приложения один логин с минимальным разрешением, то PHP должен где-то знать этот логин и пароль. Как лучше всего защитить этот пароль? Похоже, просто писать это в PHP-коде - не лучшая идея.
Пароль базы данных, используемый в строке подключения. Спасибо!
Для полной безопасности вам необходимо настроить ssl-соединение, иначе любой в вашей сети все равно сможет прослушать вводимый вами пароль.






Храните их в файле вне корневого веб-сайта.
А также, как упоминалось в другом месте, вне системы контроля версий.
мы могли бы это включить? например в PHP можем ли мы тогда сделать include('../otherDirectory/configfile.conf')?
Вы все предлагаете хранить учетные данные вне wwwroot. Хорошо, я понимаю, что такое безопасность. Но как тогда его хранить в системе контроля версий (пример конфигурации)? Обычно wwwroot является корнем репозитория git, поэтому, если есть что-то снаружи - это будет за пределами VC. Представьте, что новый разработчик пытается создать локальный экземпляр для разработки - откуда ему знать магию вроде «взять этот файл, скопировать его и заполнить»?
@TheGodfather Идея состоит в том, что новый разработчик должен иметь свои собственные учетные данные для своей собственной среды разработки. Хотя рекомендуется иметь файл readme с инструкциями или комментариями в коде, указывающими, как вы должны его настроить (но не с фактическими данными).
Некоторые люди неверно истолковали это как вопрос о том, как использовать пароли хранить в базе данных. Это не правильно. Речь идет о том, как сохранить пароль, который позволяет вам получить к в базе данных.
Обычное решение - переместить пароль из исходного кода в файл конфигурации. Затем оставьте администрирование и защиту этого файла конфигурации вашим системным администраторам. Таким образом, разработчикам не нужно ничего знать о производственных паролях, и в вашем исходном элементе нет записи о пароле.
Спасибо. Если я правильно это понимаю, тогда файл php будет включен в файл конфигурации, что позволит ему использовать пароль. например Я создаю файл с именем app1_db_cfg.php, в котором хранятся логин, пароль и имя базы данных. Затем моя страница application.php включает «app1_db_cfg.php», и я в деле!
да, я обычно использую DEFINE ("DB_NAME", "mydb"); и т. д. также удобно определить все, что вы будете использовать на более чем странице, что вы, возможно, захотите изменить позже
Простое сохранение пароля в файле конфигурации ненамного безопаснее. Он должен быть должным образом защищен, используя надежные списки контроля доступа и надежное шифрование с должным образом защищенными ключами ... См. Мой пост ниже.
Я согласен с тем, что конфиг необходимо должным образом защитить. Однако знание того, как это сделать, - дело системных администраторов, а не разработчиков. Я не согласен с ценностью надежного шифрования в этом случае. Если вы не можете защитить свой файл конфигурации, почему вы думаете, что можете защитить свои ключи?
Я предпочитаю использовать учетную запись базы данных, которой разрешен доступ к базе данных только с веб-сервера. И тогда я не утруждаюсь шифрованием конфигурации, я просто сохраняю ее вне корневого веб-каталога.
@bentilly, вот где приходит сильное управление ключами, и это определенно должно быть ответственностью разработчика, а не администратора - хотя у администраторов также есть некоторые задачи здесь.
@bentilly, значит, когда вы не раскрываете конфиденциальные данные, нет необходимости в шифровании? Отсутствие шифрования, потому что вы не думаете, что кто-то непривилегированный получит доступ, звучит для меня странно - это делает PIN-код на моей VISA бесполезным, поскольку никто не должен получать к нему доступ. изменить: извините, кто-то откопал старую ветку
@gnut: «Я просто храню его вне корня сети». Как это поможет сделать это за пределами webroot? Я спрашиваю об этом, поскольку даже в современных сценариях с открытым исходным кодом я видел, что файл конфигурации, содержащий пароль db, находится в корне. Я не предпочитаю это, и я хочу знать, стоит ли мне беспокоиться.
@MatthewRapati ... Я фактически решаю проблему с паролем в константах, потому что другие разработчики могут просто сделать get_defined_constants().
Я использую переменную среды apache, чтобы установить путь, чтобы даже путь к файлу был неизвестен в исходном коде. Это также позволяет иметь другой пароль для разработки и производства в зависимости от настроек Apache на сервере.
Имейте в виду, что даже файлы, хранящиеся вне каталога, доступного в Интернете, должны быть прочитаны сценарием, который их использует. Если кто-то включает этот файл, а затем выгружает данные из файла, они увидят пароль.
Для всех людей, которые спрашивают, как защититься от всех, кроме меня, ответ - либо управлять всей компанией самостоятельно, либо вы должны доверять хотя бы кому-то.
@henk Для этого нет решения. Вы должны доверять или быть осторожными с содержимым всех сценариев, которые отправляются на рабочий сервер.
@RickMacGillis If someone includes that file, then dumps the data from the file, they will see the password, как вы с этим справляетесь?
@tonix Проблема больше связана с программным обеспечением с открытым исходным кодом, поскольку вы будете знать переменные или структуру этого файла. По этой причине define - плохая идея для установки этих переменных. (Например, WordPress использует этот небезопасный метод, и он находится внутри каталога, доступного в Интернете.) Проблема, на которую я указал, заключается в том, что если кто-то может загрузить файл, он может обнаружить пароли в этом файле. Однако, несмотря на то, что кто-то может легко сбросить пароль, созданный с помощью define, файлы конфигурации Laravel .env или на основе массивов только слегка лучше. Каждый файл уязвим для атаки.
Чтобы избежать этой проблемы, в первую очередь используйте сервер паролей и запросите у него необходимую информацию. AWS KMS можно использовать для дополнительной защиты ваших паролей, храня их в зашифрованном виде в файловой системе и расшифровывая их только в памяти с помощью Redis. aws.amazon.com/kms
Опять же, если кто-то может разместить файл на вашем сайте и запустить его, у вас будут большие проблемы, чем просто потеря паролей. Этот файл может делать что угодно.
За исключением того, что администраторы почти никогда не защищают их, потому что обычно даже не подозревают об их наличии. ржунимагу.
Поместите пароль базы данных в файл, сделайте его доступным только для чтения для пользователя, обслуживающего файлы.
Если у вас нет средств, позволяющих только процессу php-сервера обращаться к базе данных, это почти все, что вы можете сделать.
Если вы говорите о пароле базы данных, а не о пароле, исходящем от браузера, стандартной практикой кажется размещение пароля базы данных в конфигурационном файле PHP на сервере.
Вам просто нужно убедиться, что php-файл, содержащий пароль, имеет соответствующие разрешения. Т.е. он должен быть доступен для чтения только веб-серверу и вашей учетной записи.
К сожалению, файл конфигурации PHP может быть прочитан с помощью phpinfo (), и если кто-то оставит какой-то тестовый скрипт, удачливый злоумышленник сможет прочитать пароль. Вероятно, лучше оставить пароль для подключения в файле за пределами корневого каталога веб-сервера. Тогда единственный способ получить к нему доступ - либо с помощью оболочки, либо путем выполнения произвольного кода, но в этом сценарии вся безопасность все равно теряется.
@MarioVilas "файл конфигурации PHP может быть прочитан с помощью phpinfo ()" - я думаю, что ответ относится к произвольному сценарию PHP, который содержит информацию о конфигурации, а не к файлу php.ini (config) (который, как я полагаю, это то, что вы имеете в виду к). Это не будет "читаться phpinfo ()".
@MrWhite, конечно, ты абсолютно прав. Я неправильно понял ответ, означающий хранение учетных данных базы данных в самом php.ini.
Обычно это делается просто путем помещения его в конфигурационный файл. Просто убедитесь, что вы:
Ваш выбор ограничен, поскольку вы говорите, что вам нужен пароль для доступа к базе данных. Один из общих подходов - хранить имя пользователя и пароль в отдельном файле конфигурации, а не в основном скрипте. Затем обязательно сохраните это за пределами основного веб-дерева. Это было, если возникла проблема с веб-конфигурацией, из-за которой ваши php-файлы просто отображались как текст, а не выполнялись, вы не раскрыли пароль.
В остальном вы находитесь на правильных линиях с минимальным доступом к используемой учетной записи. Добавьте к этому
Питер
Если вы используете PostgreSQL, он автоматически ищет пароли в ~/.pgpass. См. руководство для получения дополнительной информации.
Дополнительный трюк - использовать отдельный файл конфигурации PHP, который выглядит так:
<?php exit() ?>
[...]
Plain text data including password
Это не мешает вам правильно установить правила доступа. Но в случае взлома вашего веб-сайта команда «require» или «include» просто выйдет из сценария в первой строке, так что получить данные будет еще сложнее.
Тем не менее, никогда не помещайте файлы конфигурации в каталог, доступный через Интернет. У вас должна быть папка «Web», содержащая код вашего контроллера, CSS, изображения и js. Вот и все. Все остальное находится в автономных папках.
но как тогда скрипт php читает учетные данные, хранящиеся в файле?
Вы используете fopen (), как и для обычного текстового файла.
@ e-satis хорошо, это помешает хакеру выполнить require / include, но как предотвратить выполнение fopen?
"это не мешает вам правильно устанавливать правила доступа"
@ e-satis, это довольно умно. интересно, почему никто об этом не подумал. тем не мение, все еще уязвимый для проблемы копирования редактора. feross.org/cmsploit
Для чрезвычайно безопасных систем мы шифруем пароль базы данных в файле конфигурации (который сам защищен системным администратором). При запуске приложения / сервера приложение запрашивает у системного администратора ключ дешифрования. Затем пароль базы данных считывается из файла конфигурации, расшифровывается и сохраняется в памяти для использования в будущем. Все еще не на 100% безопасный, поскольку он хранится в дешифрованной памяти, но в какой-то момент вы должны назвать его «достаточно безопасным»!
@RaduMurzea, это смешно. Когда вы слышали о смерти системных администраторов? Они как McDonalds, просто появляются / исчезают из ниоткуда!
@Radu Murzea Просто имейте 2 или более админов, тогда у вас будет паритет, как у рейдового массива. Вероятность одновременного отказа более чем одного диска намного ниже.
как насчет перезапуска серверов? Как насчет времени, необходимого для того, чтобы разбудить администратора и заставить его ввести пароль в… и т. д.? ржунимагу
Я на 100% согласен, что веб-логика Oracle была сделана с помощью boot.properties
Не уверен, что вы имеете в виду под словом «хранится в памяти». Веб-приложения PHP обычно ничего не хранят в памяти дольше, чем время, необходимое для ответа на отдельный запрос на просмотр страницы.
@bdsl Redis или Memcache
@ element11 Только убедитесь, что они никогда не едут в McDonald's на обед вместе в одной машине!
если возможно создать соединение с базой данных в том же файле, где хранятся учетные данные. Вставьте учетные данные в оператор подключения.
mysql_connect("localhost", "me", "mypass");
В противном случае лучше всего отключить учетные данные после оператора подключения, потому что учетные данные, которых нет в памяти, не могут быть читать из памяти;)
include("/outside-webroot/db_settings.php");
mysql_connect("localhost", $db_user, $db_pass);
unset ($db_user, $db_pass);
Если у кого-то есть доступ к памяти, вы все равно облажались. Это бессмысленная подделка безопасности. Вне корневого веб-сайта (или, по крайней мере, защищенный .htaccess, если у вас нет доступа выше вашего веб-корневого каталога) - единственный безопасный вариант.
@uliwitness - это все равно что сказать, что просто потому, что кто-то может прорезать замок вашего центра управления сетью с помощью ацетиленовой горелки, означает, что дверь также является поддельной защитой. Всегда имеет смысл держать конфиденциальную информацию в максимально возможном объеме.
Как насчет echo $ db_user или печати $ db_pass? Даже разработчики в одной команде не должны иметь возможности вычислить производственные учетные данные. Код не должен содержать ничего печатаемого об информации для входа в систему.
@ LukeA.Leber При надлежащей защите замок не должен прибавлять никакой дополнительной защиты. Блокировка предназначена только для уменьшения вероятности кражи оборудования, но на случай кражи оборудования оно не должно содержать конфиденциальных и / или незашифрованных данных.
Лучший способ - вообще не хранить пароль!
Например, если вы работаете в системе Windows и подключаетесь к SQL Server, вы можете использовать встроенную проверку подлинности для подключения к базе данных без пароля, используя идентификатор текущего процесса.
Если вам действительно нужно подключиться с паролем, сначала зашифровать его, используя надежное шифрование (например, используя AES-256, а затем защищая ключ шифрования, или используя асимметричное шифрование и пусть ОС защищает сертификат), а затем сохраните его файл конфигурации (вне веб-каталога) с сильные ACL.
Нет смысла шифровать пароль опять таки. Тот, кто может получить незашифрованный пароль, также может получить любую парольную фразу, необходимую для расшифровки пароля. Однако использование ACL и .htaccess - хорошая идея.
@uliwitness Думаю, вы неправильно поняли - что вы имеете в виду под "зашифровать опять таки"? Это всего лишь одно шифрование. И вы не хотите использовать парольные фразы (предназначенные для использования людьми) для его шифрования, достаточно надежное управление ключами, например защищен ОС таким образом, что простой доступ к файловой системе не предоставит доступ к ключу.
Шифрование - это не волшебство - вместо защиты ключа AES с помощью списков контроля доступа вы можете просто сохранить там пароль. Нет никакой разницы между доступом к ключу AES или дешифрованному паролю, шифрование в этом контексте - это просто змеиная нефть.
@MarioVilas, что? Если пароль зашифрован, а ключ шифрования защищен ОС, как там нет разницы? Шифрование - это не волшебство - оно просто сжимает всю секретность в меньшем ключе шифрования. Вряд ли snakeoil, в этом контексте это просто движущийся, вся эта секретность в ОС.
@AviD, почему ОС может защитить ключ, но не сами данные? Ответ: он может защитить и то, и другое, поэтому шифрование не помогает. Было бы иначе, если бы хранились только данные, а ключ шифрования был получен, например, из пароля, который должен был быть напечатанный пользователем.
Если вы размещаете на чужом сервере и не имеете доступа за пределами вашего корневого веб-сайта, вы всегда можете поместить свой пароль и / или соединение с базой данных в файл, а затем заблокировать файл с помощью .htaccess:
<files mypasswdfile>
order allow,deny
deny from all
</files>
Спасибо, это именно то, что я искал.
Полезно, если это действительно безопасно, хотя кажется, что вход в оболочку все равно будет иметь доступ.
Определенно, но если у кого-то есть доступ к оболочке, вся ваша учетная запись все равно была скомпрометирована.
Для этого нет реального решения. Любой желающий может использовать функции дампа в файле, загрузить файл на рабочий сервер и выполнить его. Ура, у вас есть все секреты производственного сервера!
Это плохая практика, потому что вы можете случайно зафиксировать свои учетные данные в репозитории.
@Ankit: если недружественный пользователь может загрузить файл на сервер и выполнить его, значит, сервер настроен неправильно.
@Porlune: разработчики должны заставить свою систему контроля версий игнорировать файл паролей, то есть использовать .gitignore. Но да, следует проявлять осторожность с файлами, которые содержат конфиденциальные данные.
@Porlune Хорошо, но вы также можете случайно ввести пароль в поле пользователя и сохранить его в файле журнала с открытым текстом. В какой-то момент нужно ожидать, что люди будут правильно выполнять свою работу. Вы не можете исключить все риски. Это заблуждение, что вы можете полностью обезопасить любую систему от ошибок.
@RobertTalada Если говорить об этом конкретном решении, важно, чтобы те, у кого ограниченный опыт в области безопасности, были предупреждены о потенциальных ловушках. Пользовательские поля в браузере выходят за рамки, но фиксации репозитория - нет.
Самый безопасный способ - вообще не указывать информацию в вашем PHP-коде.
Если вы используете Apache, это означает, что необходимо указать детали подключения в файле httpd.conf или файле виртуальных хостов. Если вы это сделаете, вы можете вызвать mysql_connect () без параметров, что означает, что PHP никогда не будет выводить вашу информацию.
Вот как вы указываете эти значения в этих файлах:
php_value mysql.default.user myusername
php_value mysql.default.password mypassword
php_value mysql.default.host server
Затем вы открываете свое соединение mysql следующим образом:
<?php
$db = mysqli_connect();
Или вот так:
<?php
$db = mysqli_connect(ini_get("mysql.default.user"),
ini_get("mysql.default.password"),
ini_get("mysql.default.host"));
Пожалуйста, проверьте правильность значений ini_get ('значения по умолчанию') php.net/manual/en/class.mysqli.php
Можно ли использовать это в своем файле .htaccess?
да, но любой пользователь (или хакер, злоупотребляющий плохо написанным php-скриптом) может прочитать пароль через ini_get().
@ Marki555 but any user (or a hacker abusing badly written php script) can read the password via ini_get() Как вы с этим справляетесь?
Marki555 говорит, что злоумышленник, который может запускать код PHP, также может вызывать функции PHP, что, очевидно, верно и с этим невозможно что-то сделать. Я также хотел бы добавить, что я больше не следую советам, которые даю в этом ответе, а вместо этого использую переменные среды. Однако концепция схожа: не храните свои учетные данные в коде, а как-то их вставляйте. На самом деле не имеет значения, используете ли вы ini_get() или getenv().
@tonix, как уже было написано, если «хороший» скрипт имеет доступ к паролю db, то также «плохой» скрипт имеет доступ. Таким образом, ваш единственный вариант - обнаруживать такие сценарии и не разрешать им запускаться, например, с помощью модуля mod_security apache, хотя правильно настроить правила нетривиально.
@ Marki555 Я могу подумать об использовании одной точки входа для подключения к базе данных, где я читаю пароль и имя пользователя базы данных и передаю их механизму подключения, чтобы получить подключение к базе данных, а затем сбросить эти переменные. На этом этапе мне нужно остерегаться того, что все будут нажимать на базу кода, и убедиться, что в этом файле точки входа нет изменений и никто не пытается каким-то образом сбросить пароль базы данных. Этого может быть достаточно?
Наличие прохода в файле конфигурации вне корня безопаснее, чем его использование ini_get () или getenv (), которые могут быть введены и выполнены из любого места на веб-сайте.
@DeepBlue Если вы можете внедрить ini_get (), вы также можете ввести file_get_contents (anypath). Если у php есть способ получить пароль, то будет и любой вредоносный код.
Я думаю, что это очень плохая идея, если на сервере есть phpinfo (), плавающая вокруг, это приведет к утечке вашего пароля.
Это решение является общим, поскольку оно полезно как для приложений с открытым, так и для закрытых исходных кодов.
Преимущества:
Этот метод предложен Heroku, которые очень успешны.
Мы решили это так:
Раньше мы сохраняли пользователя / проход БД в файле конфигурации, но с тех пор перешли в параноидальный режим - приняв политику Глубокая оборона.
Если ваше приложение скомпрометировано, пользователь получит доступ для чтения к вашему файлу конфигурации, и, следовательно, взломщик может прочитать эту информацию. Файлы конфигурации также могут попадать в систему контроля версий или копироваться с серверов.
Мы перешли на хранение user / pass в переменных среды, установленных в Apache VirtualHost. Эта конфигурация доступна для чтения только root - надеюсь, ваш пользователь Apache не работает как root.
Минус в том, что теперь пароль находится в глобальной переменной PHP.
Чтобы снизить этот риск, мы принимаем следующие меры предосторожности:
phpinfo() отключен. PHPInfo - простая цель для получения общего обзора всего, включая переменные среды.«Эта конфигурация доступна для чтения только пользователю root» - хотя установленные переменные среды предположительно доступны для чтения каждый?
@MrWhite, переменная env будет установлена только для пользователя, от имени которого запускается Apache. Так что это определенно не читается для каждый.
На самом деле, лучше всего хранить учетные данные вашей базы данных в переменных среды, потому что:
Как их использовать?
$_ENV['MYVAR'] = $myvarecho $_ENV["MYVAR"]putenv("MYVAR=$myvar");getenv('MYVAR');Вы можете легко удалить файл, такой как envvars.php, со всеми переменными среды внутри, запустить его (php envvars.php) и удалить. Это немного старая школа, но она все еще работает, и у вас нет файла с вашими учетными данными на сервере, и нет учетных данных в вашем коде. Поскольку это немного трудоемко, фреймворки справляются с этим лучше.
Пример с Symfony (хорошо, это не только PHP) Современные фреймворки, такие как Symfony, рекомендуют использовать переменные среды и хранить их в незафиксированном файле .env или непосредственно в командных строках, что означает, что вы можете:
symfony var:set FOO=bar --env-levelДокументация :
Вы имеете в виду пароли пользователей или пароль базы данных, используемый в строке подключения?