6.12ctf练习

[西湖论剑 2022]Node Magical Login

源码在这里:GitHub - CTF-Archives/2022-xhlj-web-node_magical_login: A web challenge in 2022 西湖论剑大赛打开

打开环境是个登录框,先进行了扫描和抓包都没有看见什么有价值的东西,看源码

大致连接到存在flag1和flag2


function LoginController(req,res) {
    try {
        const username = req.body.username
        const password = req.body.password
        if (username !== "admin" || password !== Math.random().toString()) {
            res.status(401).type("text/html").send("Login Failed")
        } else {
            res.cookie("user",SECRET_COOKIE)
            res.redirect("/flag1")
        }
    } catch (__) {}
}
function Flag1Controller(req,res){
    try {
        if(req.cookies.user === SECRET_COOKIE){
            res.setHeader("This_Is_The_Flag1",flag1.toString().trim())
            res.setHeader("This_Is_The_Flag2",flag2.toString().trim())
            res.status(200).type("text/html").send("Login success. Welcome,admin!")
        }
        if(req.cookies.user === "admin") {
            res.setHeader("This_Is_The_Flag1", flag1.toString().trim())
            res.status(200).type("text/html").send("You Got One Part Of Flag! Try To Get Another Part of Flag!")
        }else{
            res.status(401).type("text/html").send("Unauthorized")
        }
    }catch (__) {}
}

从这两部分代码中能够知道登录成功的条件是"admin/生成随机数转换为的字符串",爆破随机数这个不太可能,应该就要从别的地方入手

由于每次调用 Math.random() 都会产生一个新的随机数,密码验证几乎不可能成功,除非每次用户输入的密码恰好是 Math.random().toString() 的结果(这在实际情况下是不可能的)

看登录成功之后会生成一个名为user的cookie,值为SECRET_COOKIE,再重定向到flag1

在下一部分的代码中,当从客户端发送的cookie中user=admin就会返回第一部分的flag

所以直接抓包flag1修改cookie

接下来获取flag2

function CheckController(req,res) {
    let checkcode = req.body.checkcode?req.body.checkcode:1234;
    console.log(req.body)
    if(checkcode.length === 16){
        try{
            checkcode = checkcode.toLowerCase()
            if(checkcode !== "aGr5AtSp55dRacer"){
                res.status(403).json({"msg":"Invalid Checkcode1:" + checkcode})
            }
        }catch (__) {}
        res.status(200).type("text/html").json({"msg":"You Got Another Part Of Flag: " + flag2.toString().trim()})
    }else{
        res.status(403).type("text/html").json({"msg":"Invalid Checkcode2:" + checkcode})
    }
}

路由

app.post("/getflag2",(req,res)=> {
    controller.CheckController(req,res)
})

请求体中的checkcode长度要为16,并且在toLowerCase()转换为小写后字符串=="aGr5AtSp55dRacer"

在 Web 应用的安全性验证中,toLowerCase() 的验证逻辑如果没有针对输入的数据格式做严格的检查,可能会被利用 JSON 数据结构进行绕过

利用JSON数组来绕过

解释一下这个数组的构造思路

JSON数组的结构

{"数组名称":["a","b","c"]}

"aGr5AtSp55dRacer"在数组中为一个值,所以要满足长度为16,还需要添加除了预期字符串之外的一系列数字,验证代码简单地提取 checkcode 字段,而没有检查其类型,就直接使用整个数组,导致 toLowerCase() 等字符串操作被绕过

{"checkcode":["aGr5AtSp55dRacer",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}

记得把类型改为json,否则会报错

[NCTF 2018]Easy_Audit

源码

<?php
highlight_file(__FILE__);
error_reporting(0);
if($_REQUEST){
    foreach ($_REQUEST as $key => $value) {
        if(preg_match('/[a-zA-Z]/i', $value))   die('waf..');
    }
}

if($_SERVER){
    if(preg_match('/yulige|flag|nctf/i', $_SERVER['QUERY_STRING']))  die('waf..');
}

if(isset($_GET['yulige'])){
    if(!(substr($_GET['yulige'], 32) === md5($_GET['yulige']))){         //日爆md5!!!!!!
        die('waf..');
    }else{
        if(preg_match('/nctfisfun$/', $_GET['nctf']) && $_GET['nctf'] !== 'nctfisfun'){
            $getflag = file_get_contents($_GET['flag']);
        }
        if(isset($getflag) && $getflag === 'ccc_liubi'){
            include 'flag.php';
            echo $flag;
        }else die('waf..');
    }
}


?>

借这题也是比较清楚的认识了php的超级全局变量,现在开始一层一层分析源码

第一层
if($_REQUEST){
    foreach ($_REQUEST as $key => $value) {
        if(preg_match('/[a-zA-Z]/i', $value))   die('waf..');
    }
}

foreach,一个遍历数组并把值赋给value,但是这个$_REQUEST是什么?

$_REQUEST 是 PHP 中的一个超级全局变量数组,用于收集通过 GET、POST 和 COOKIE 发送到当前脚本的请求数据。它整合了 $_GET$_POST$_COOKIE 三个数组中的数据。

同时$_REQUEST还具有一个特性,当同时通过POST和GET传参时,如果POST和GET中含有相同的变量时,只会获取POST传参的变量值

那么第一层就利用POST传参进行变量覆盖,且post传参的值中不能出现字母,绕过第一层的判断

第二层

if($_SERVER){
    if(preg_match('/yulige|flag|nctf/i', $_SERVER['QUERY_STRING']))  die('waf..');
}

$_SERVER也是一个超级全局变量, $_SERVER['QUERY_STRING']指获取get传参的变量和值

http://xxx.com?a=123
那么 $_SERVER['QUERY_STRING']就获取a=123

所以就限制了get传参中不能出现被正则过滤的变量,编码绕过就行

第三层
if(isset($_GET['yulige'])){
    if(!(substr($_GET['yulige'], 32) === md5($_GET['yulige']))){         //日爆md5!!!!!!
        die('waf..');
    }else{
        if(preg_match('/nctfisfun$/', $_GET['nctf']) && $_GET['nctf'] !== 'nctfisfun'){
            $getflag = file_get_contents($_GET['flag']);
        }
        if(isset($getflag) && $getflag === 'ccc_liubi'){
            include 'flag.php';
            echo $flag;
        }else die('waf..');
    }
}
一.md5强比较

GET传参yulige,截取前32位和md5加密后的值相同,其实就是一个md5的强比较,传入数组为空即成立

二.正则表达式的绕过

"$"表示正则匹配的位置,这里放在了末尾说明在字符串的末尾进行正则匹配,所以只要在"nctfisfun"前面加数字或者字母就行,只要末尾能匹配到要求字符串就行

三.php伪协议

file_get_contents读取$flag,赋值给getflag==='ccc_liubi',用data伪协议写入就行

所以完整的GET传参payload

yulige[]=1&nctf=1nctfisfun&flag=data://text/plain,ccc_liubi

POST传参

yulige=1&nctf=1&flag=1

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: CTFsql注入练习题是一种用于训练和测试SQL注入技巧的题目。在这些题目中,参与者需要通过注入恶意的SQL代码来绕过应用程序的安全机制,从而获取敏感信息或者执行未授权的操作。这些题目通常包含了不同的注入场景和技巧,例如基于时间的盲注、报错注入、布尔盲注、宽字节注入等等。参与者需要通过分析应用程序的行为和结构,构造合适的注入语句来实现攻击目标。在解决这些题目的过程中,参与者可以提高对SQL注入漏洞的理解和掌握,并学习如何防范和修复这类漏洞。 #### 引用[.reference_title] - *1* *2* [CTF-SQL注入入门题型](https://blog.csdn.net/weixin_43080961/article/details/121939366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [i 春秋 CTF训练营 web——SQL注入 1(字符型注入)(手动注入)](https://blog.csdn.net/AAAAAAAAAAAA66/article/details/121626527)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值