Como sobrescrever a memória do php por razões de segurança?

9

Na verdade, estou trabalhando em um script de segurança e parece que encontro um problema com o PHP e a maneira como o PHP usa a memória.

my.php:

<?php
// Display current PID
echo 'pid= ', posix_getpid(), PHP_EOL;

// The user type a very secret key
echo 'Fill secret: ';
$my_secret_key = trim(fgets(STDIN));

// 'Destroty' the secret key
unset($my_secret_key);

// Wait for something
echo 'waiting...';
sleep(60);

E agora eu corro o script:

php my.php
pid= 1402
Fill secret: AZERTY             <= User input
waiting...

Antes do final do script (enquanto dorme), eu gero um arquivo principal enviando sinal SIGSEV para o script

kill -11 1402

Eu inspeciono o corefile:

 strings core | less

Aqui está um extrato do resultado:

...
fjssdd
sleep    
STDIN
AZERTY            <==== this is the secret key
zergdf
...

Eu entendo que a memória é liberada com o não definido e não 'destruído'. Os dados não são realmente removidos (uma chamada para a função free ())

Então, se alguém descartar a memória do processo, mesmo após a execução do script, ele poderá ler $ my_secret_key (até que o espaço de memória seja sobrescrito por outro processo)

Existe uma maneira de sobrescrever este segmento de memória do espaço de memória total após a execução do script PHP?

Obrigado a todos por seus comentários.

Eu já sei como a memória é gerenciada pelo sistema.

Mesmo se o PHP não usar malloc e free (mas algumas versões editadas como emalloc ou efree), parece (e eu entendo por que) é simplesmente impossível para o PHP 'limpar' depois de liberar a memória não permitida.

A pergunta foi mais por curiosidade, e todos os comentários parecem confirmar o que eu pretendo fazer anteriormente: escrever um pequeno pedaço de código em uma linguagem consciente de memória (c) para lidar com essa parte especial alocando uma string simples com malloc , sobrescrevendo com XXXXXX depois de usar THEN liberando.

Obrigado a todos

J

    
por nemenems 30.08.2011 в 15:57
fonte

4 respostas

4

Parece que você não tem muita compreensão sobre como o gerenciamento de memória funciona em geral, e especificamente no PHP.

Uma discussão dos vários pontos salientes é redundante quando você considera qual é o risco de segurança aqui:

  

Então, se alguém despeja a memória do processo, mesmo após a execução do script

Se alguém pode acessar a memória de um programa rodando sob um uid diferente, então eles têm acesso root e podem comprometer o alvo de muitas outras maneiras - e não importa se é script PHP, ssh, um Oracle DBMS. ...

Se alguém puder acessar a memória anteriormente ocupada por um processo que agora foi encerrado, então, além de terem o root, eles já comprometeram o kernel.

    
por symcbean 30.08.2011 / 18:13
fonte
1

Parece que você perdeu uma lição importante sobre o que os computadores querem dizer com "operações de exclusão".

Veja, nunca é possível para o computador zerar a memória, mas em vez disso eles simplesmente "esquecem" que estavam usando essa memória.

Em outras palavras, se você quiser limpar a memória, você definitivamente precisa sobrescrevê-la, assim como @hakre sugeriu.

Dito isso, dificilmente vejo o ponto do seu roteiro. O PHP simplesmente não é feito para o tipo de coisa que você está fazendo. Você provavelmente está melhor com uma pequena solução dedicada em vez de usar PHP. Mas esta é apenas a minha opinião. Eu acho.

    
por Christian 30.08.2011 / 16:25
fonte
0

Eu não sei se isso funciona, mas se você puder nos seus testes, por favor adicione estas linhas para ver o resultado:

...

// Overwrite it:
echo 'Overwrite secret: ';
for($l = strlen($my_secret_key), $i = 0; $i < $l; $i++)
{
    $my_secret_key[$i] = '@';
}

E eu me pergunto se estou ou não em execução

gc_collect_cycles();

faz a diferença. Mesmo os valores são liberados, eles ainda podem estar na memória (dos scripts pid ou mesmo em algum outro lugar no espaço da memória).

    
por hakre 30.08.2011 / 16:13
fonte
0

Eu tentaria substituir a memória por alguns dados que acabariam com os locais originais das variáveis:

$buffer = '';
for ($i = 0; $i < 1e6; $i++) {
    $buffer .= "\x00";
}

Assim que o php libera a memória, suponho que mais alocações possam receber o mesmo local. É dificilmente prova de falhas.

    
por Mikulas Dite 30.08.2011 / 19:50
fonte