정보실

웹학교

정보실

php PHP의 unserialize()를 사용하여 인증 우회 및 SQL 주입 달성

본문

지난번에, PHP의 직렬화 해제가 어떻게 취약점을 유발하는지와 공격자가 RCE를 달성하기 위해 이를 어떻게 활용할 수 있는지에 대해 이야기했습니다.


오늘은 공격자가 unserialize() 취약점을 악용 할 수 있는 여러 가지 방법에 대해 설명하겠습니다. RCE가 가능하지 않더라도 공격자는 여전히 unserialize() 취약점을 사용하여 인증 우회 및 SQL 주입을 달성 할 수 있습니다.


원본 : https://medium.com/swlh/diving-into-unserialize-more-than-rce-d48d371db7da


인증 우회 


RCE 외에도 unserialize() 문제는 종종 응용 프로그램의 인증 제어를 우회 하는 데 사용됩니다. 액세스 제어로 사용되는 개체 속성을 조작하고 형식 저글링 문제를 사용하여 응용 프로그램을 속이는 두 가지 방법이 있습니다. 두 방법 모두 최종 사용자가 unserialize()에 전달 된 객체를 제어 할 수 있다는 사실에 의존합니다.


인증을 우회하기 위해 객체 속성 조작 


공격자가 역 직렬화 결함을 악용하는 가장 단순하고 가장 일반적인 방법 중 하나는 인증을 우회 하기 위해 개체 속성을 조작하는 것입니다.

class User{  public $username = “vickie”;  public $type = “Regular User”;  # some more PHP code
}


애플리케이션이 가입 과정에서 사용자 정보를 전달하기 위해 User라는 클래스를 사용했다고 가정 해 보겠습니다. 사용자는 양식을 작성하고 직렬화 된 User 개체를 통해 정보를 백엔드에 전달합니다.


최종 사용자는 User 개체를 제어하기 때문에 간단하게 개체를 조작하고 관리자로 등록 할 수 있습니다.

class User{  public $username = “vickie”;  public $type = “Admin User”;  # some more PHP code
}


유형 저글링을 사용하여 인증 우회 


공격자가 역 직렬화 결함으로 인증 우회를 달성 할 수 있는 또 다른 방법은 PHP의 유형 저글링 기능을 이용하는 것입니다. 공격자는 응용 프로그램에 전달 된 개체를 완전히 제어 할 수 있으므로 개체 속성의 변수 유형을 제어 할 수 있습니다.


그런 다음 속성의 변수 유형을 조작하여 PHP가 juggle을 강제로 입력하도록 하여 액세스 제어를 우회 할 수 있습니다. 예를 들어, 응용 프로그램이 관리자에 로그인하기 위해 사용하는 코드 인 경우 :

parse_str($_POST['user_password'], $password_array);$pw = unserialize($password_array[0]);if ($pw->password == “Admin_Password”) {login_as_admin();}


공격자는 다음과 같이 POST 본문을 제출하여 관리자로 로그인 할 수 있습니다.

class Password{  public $password = 0;  # some more PHP code}# submit this string as POST body:print urlencode(serialize(new Password)); 


이것은 PHP에서 (0 ==“Admin_Password”)가 True로 평가되기 때문에 작동합니다. PHP는 다른 유형의 변수를 비교하려고 할 때 공통 변수 유형으로 변환하려고 시도합니다. 이 경우“Admin_Password”는 정수 0으로 변환되므로 (0 ==“Admin_Password”)는 (0 == 0)과 같습니다.


SQL injection 


unserialize() 취약점은 조건에 따라 SQL 인젝션을 유발할 수도 있습니다. 다음은 악용 될 수 있는 방법의 예입니다. (이 예는 owasp.org에서 가져 왔습니다.)


SQL 체인을 사용하여 POP 체인 사용 


(POP 체인의 작동 방식에 익숙하지 않은 경우 먼저 여기에서 이에 대해 읽으십시오.)


응용 프로그램이 코드 어딘가에서 이 작업을 수행한다고 가정 해 봅시다. Example3 클래스를 정의하고 POST 매개 변수 데이터에서 비위생 사용자 입력을 deserialize합니다.

class Example3
{
protected $obj;

function __construct()
{
// some PHP code...
}

function __toString()
{
if (isset($this->obj)) return $this->obj->getValue();
}
}

// some PHP code...

$user_data = unserialize($_POST['data']);

// some PHP code... 


__toString()은 클래스가 문자열로 취급 될 때 호출되는 마술 함수입니다. 이 경우 Example3 인스턴스가 문자열로 처리되면 $obj 속성의 getValue() 메서드 결과가 반환됩니다.


그리고 응용 프로그램 어딘가에 SQL_Row_Value 클래스도 정의되어 있다고 가정 해 봅시다. getValue()라는 메소드가 있으며 SQL 쿼리를 실행합니다. SQL 쿼리는 SQL_Row_Value 인스턴스의 $ _table 속성에서 입력을 받습니다.

class SQL_Row_Value
{
private $_table;

// some PHP code...

function getValue($id)
{
$sql = "SELECT * FROM {$this->_table} WHERE id = " . (int)$id;
$result = mysql_query($sql, $DBFactory::getConnection());
$row = mysql_fetch_assoc($result);

return $row['value'];
}
} 


그런 다음 공격자는 Example3에서 $ obj를 제어하여 SQL 삽입을 달성 할 수 있습니다. 다음 코드는 $ obj가 SQL_Row_Value instant로 설정되고 $ _table이 "SQL Injection"문자열로 설정되어 Example3 인스턴스를 만듭니다.


class SQL_Row_Value
{
private $_table = "SQL Injection";
}

class Example3
{
protected $obj;

function __construct()
{
$this->obj = new SQL_Row_Value;
}
}

print urlencode(serialize(new Example3)); 


이런 식으로 공격자의 Example3 인스턴스가 문자열로 취급 될 때마다 $obj의 get_Value() 메소드가 실행됩니다. 따라서 SQL_Row_Value의 get_Value() 메소드는 $_table 문자열을 "SQL Injection"으로 설정하여 실행됩니다.


공격자는 이제 SQL 쿼리 "SELECT * FROM {$ this-> _ table} WHERE id ="에 전달 된 문자열을 제어 할 수 있으므로 제한된 SQL 주입을 달성했습니다. (int) $ id;



  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 7회 ]  작성일19-10-08 17:44

웹학교