일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- software
- node.js
- PetitPotam
- Index
- #whitespace #
- elasticsearch
- 랜섬웨어
- Threat Intelligence
- #C언어 #연산자
- 가이드라인
- Credential Access
- sql인젝션
- AD
- wargame
- error 583066
- elk stack
- 백엔드개발자
- forensic
- 침해사고
- filesystem
- 시스템해킹
- 정보보안
- SQLMap
- 프론트엔드개발자
- ATT&CK
- Mitre
- rce
- windows
- pwnable
- exploit
- Today
- Total
Plit00's Story
Prepare() : WordPress Exploit 본문
[7월15~22일]
prepare() 함수를 이용하여 wordpress를 익스하는 밑의 영상을 토대로 공부한것을 작성합니다.
[취약점 영상 :: https://www.youtube.com/watch?v=h17hOpaJ0XE]
WordPress
- 오픈소스 콘텐츠 관리 시스템이며 PHP로 개발하였기때문에 취약점이 많습니다.
Wordpress Core
WP는 좋은 플러그인으로 사용자화를 하고 확장을 합니다.
하지만, 이 플러그인마저도 버그바운티 프로그램에서 치명적인 버그가 발생되어 top에 올라가곤합니다.
버그를 통해서 WP에서 개발자들의 실수를 찾아보는것이 우리가 할 일입니다.
(이것은 모든 버그바운티를 할때 공통적인 부분입니다. 해커는 개발자의 실수를 이용하는 것입니다.)
PDO(PHP Date Object)
-DB에 접근하는 공통 API를 사용자에게 제공하는 목적으로 만들어졌습니다.
- prepare()
실행할 문자을 입력하고 문장 객체를 반환합니다. - bind()
특정 bind 객체와 class 범위에 closure을 복제합니다. - execute()
input parameter을 실행합니다.
prepare()
=>public PDO::prepare ( string $statement [, array $driver_options = array() ] ) : PDOStatement
bind()
=>public static Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] ) : Closure
execute()
=>public PDOStatement::execute ([ array $input_parameters ] ) : bool
즉, 여러가지 DB를 객체지향적으로 제어하는 방법을 표준화 시킨것입니다.
Prepare() Function
PDO :: prepare ( string $statement [, array $driver_options = array() ] )
string $statement는 php단에서 서버와 통신을 할때의 함수 메소드를 통해 실행될 sql 문을 준비하게되는 구문입니다.
execute()나 prepare() 을 이용해서 말이죠
이것을 이용하여 호출하게 된다면 매개 변수를 수동으로 인용하고 이스케이프 할 필요가 없이 sql 공격을 방지하는데 도움이되는 함수입니다.
<?php
$std = $dbh->prepare(‘SELECT name, color, calories FROM fruit WHERE calories < color AND color’);
$std->execute(array(150, ‘blue’));
$blue = $sth->fetchAll();
$sth->execute(array(200, ‘black’));
$black = $sth->fetchAll();
?>
PDO Prepare() Statements
- Legacy Code
테스트가 불가능하거나 어려운 코드를 의미합니다.
PDO 설정상 레거시코드를 테스트할 수 없습니다.
그 이유는 WP의 기존 플러그인과의 호환성에 문제가 있기때문입니다. - PDO & PHP
//prepare()은 해킹하는 시도를 하는 사용자의 입력을 삭제하고 sql의 자리표시에 ' 를 포함시킵니다.
$query = $wpdb ->prepare( “SELECT * FROM table WHERE column1 = %s”, $_GET[‘c1’] );
$wpdb -> query( $query );
//예를 들어 유저가 이러한 입력을 했다고 봅시다.
prepare() sanitizes
User input : 1’OR’1’=1’
//' 포함
SELECT * FROM table WHERE column1 = ‘1\ ‘OR\ ‘1\ ‘=\ ‘1’
Double Prepare
4.8.3 이전의 WordPress는이 매우 일반적으로 사용되는 코드에있는 SQL 삽입에 취약했습니다.
4.7.4 버전같은경우는 이것을 이용하여 double prepare sql injection을 사용하였습니다
$query = $wpdb ->prepare( “SELECT * FROM table WHERE column1 = %s”, $_GET[‘c1’] );
$query = $wpdb ->prepare( $query . “column1 = %s”, $_GET[‘c2’] );
$wpdb -> query( $query );
첫번째 구문의 $_GET에서 값을 c1으로 넣어줬습니다. 그리고 2번째의 구문에서는 c2를 넣었죠.
이것을 실행하게된다면 script.php c1=변수 c2에 쿼리가 들어가게되면서 오류가 발생하게됩니다.
script.php?c1= %s&c2[]OR 1=1 - - x&c2[]=abc
2가지의 구문이 있습니다.
첫번째는 위와같이 변수값을 컬럼1에 배당하고 2값에도 지정해줍니다. 이런다면 위와값이 스크립트는 컬럼1에 동일하게 할당되는것이죠
두번째는 sql구문에서 한것과같이 or 1=1 - - x를 넣어줬습니다.
근데 둘 다 아까와 말했듯이 자리 표시에 싱글쿼터를 강제로 하나 더 넣어주게되면서 취약점이 생기게되는것이죠
Prepare() 1 :: SELECT *FROM table WHERE column1 = ‘ %s ’ AND column2 =%s
Prepare() 2 :: SELECT *FROM table WHERE column1 = ‘ ‘ OR 1=1 - - x’ ‘ AND column2 = ‘abc’;
1
function prepare($query, $args)
{
if(is_array($args[0])) $args = $args[0];
$query = preg_replace('/%s/', "'%s'", $query);
arrya_walk($args, array(%this, 'esc_sql'));
$query = vsprintf($query, $args);
return str_replace('%', $this->placeholder_escape(), $query);
}
function query($query)
{
$query=str_replace($this->placeholder_escape(), '%', $query);
}
Sql 삽입을 완화하기 위해 WP는 prepare()에 대한 수정을 발표했습니다.
이 수정내용은 모든 자리에 표시자를 대체합니다.
prepare()에 오기전 모든 자리를 66개의 문자열을 사용자 입력받게했습니다.
표시자리수에 '가 강제적으로 포함되어 취약점이 발생되었는데 이것을 막기 위함인거 같습니다.
placeholder_escape == prepare ()에 의해 반환 된 쿼리에 사용할 자리 표시 자 이스케이프 문자열을 생성하고 반환
$query = $wpdb ->prepare( “SELECT * FROM table WHERE column1 = %s”, $_GET[‘c1’] );
\
$query = $wpdb ->prepare( $query . “column1 = %s”, $_GET[‘c2’] );
$wpdb -> query( $query );
User input : script.php?c1= %s & c2[]=abc
prepare() 1: SELECT * FROM table WHERE column1 = ‘ {13f..0d23}s ‘
prepare() 2: SELECT * FROM table WHERE column1 = ‘ {13f..0d23}s ‘ AND column2 = ‘abc’;
Query(): SELECT * FROM table WHERE column1 = ‘ %s ‘ AND column2 = ‘abc’;
모든 %가 효과적으로 고유한 66개의 문자열로 대체됩니다
Attack
1. $query_results = new WP_Query (‘ cat=5&post_meta_key=thumbnail’);
=>SQL구문을 파싱합니다.
2. SELECT * FROM wp_posts WHERE category=5 and post_meta_key=‘thumbnail’
=> 싱글쿼터를 삽입합니다.
3. $query_results = new WP_Query (‘ cat=5&post_meta_key=thumbnail’);
=>결과 및 SQL 쿼리가 WP_Query에 저장!
WP_Query 개체는 생성자의 인수와 일치하는 데이터베이스에서 WordPress 게시물을 검색합니다.
CODEX set_transient ()
if(false ===($query_results = get_transient('qeury_results')))
{
$query_results = new WP_Query('cat=5&order=random&tag=tech&post_meta_key=thumbnail')
set_transient('query_results', $qeury_results, 12 * HOUR_IN_SECONS);
}
WP는 느린 데이터베이스 쿼리 결과를 데이터베이스에 일시적으로 캐시 할 것을 권장합니다
성능을 향상시키기 위해 느린 데이터베이스 쿼리 결과가 캐싱되어 다음 실행시 생략됩니다.
근데 여기서 잠깐 생각해본다면 "set_transient ()는 데이터베이스에 객체를 어떻게 저장할까?" 라는생각이 들게됩니다.
set_transient() / add_option()
function set_transient($transient, $value, $expiration = 0))) 1
{
$result = add_option($option, $value ='', $deprecated = '', $autoload);
}
function add_option($option, $value ='', $deprecated = '', $autoload ='yes'))) 2
{
$serialized_value = maybe_serialize($value); (1)
$result = $wpdb->qeury($wpdb->prepare("INSERT INTO '$wpdb->options' (...) (2)
VALUES (%s %s %s") ...", ..., $serialized_value, ...));
}
WP_Query 객체는 $ value에 저장됩니다.
일단 소스를 보면 (1)에 maybe_serialize 가 있는데 이것은 PHP 변수들을 string 으로 만들어 주는 함수입니다.
그리고 set_transient()을 이용해서 값을 직렬화하는데 사용합니다.
(2) add_option의 autoload는 옵션이 추가되지 않으면 false이고 옵션이 추가되면 true입니다.
WooCommerce
woocommerce는 WordPress 용 오픈 소스 전자 상거래 플러그인입니다.
Products category=“toasters” sku=“%”
%는 prepare()을 통해서 첫번째칸에 있는 값의 sku의 a93..dc로 변경이 됩니다.
O:8:”WP_Query”:1{s:3:”sql”;s:100:”SELECT…sku=‘{a93..dc}””;}
O:8:"WP_Query":1:{s:3:"sql";s:100:"SELECT… sku=‘%‘ ";…;s:7:"content";s:11:"somecontent";}
O:8:"WP_Query":1:{s:3:"sql";s:100:"SELECT… sku=‘%‘ ";…;s:7:"content";s:11:"somecontent";}
O:8:"WP_Query":1:{s:3:"sql";s:100:"SELECT… sku=‘%‘ ";…;s:7:"content";s:11:"some";;i:0;O:8:"EvilClass":0:{}i:1;s:0:"";}
O:8:"WP_Query":1:{s:3:"sql";s:100:"SELECT… sku=‘%‘ ";…;s:7:"content";s:11:"some";;i:0;O:8:"EvilClass":0:{}i:1;s:0:"";}
PHP Object injection!!!
'잡동사니 > webhacking' 카테고리의 다른 글
매커니즘 (0) | 2022.01.27 |
---|---|
unserialized (0) | 2021.12.09 |
PHP - Unserialize() (0) | 2019.08.16 |