分类: Security

  • 在Kali Linux中基于Docker容器化部署Gemma大模型踩坑实录

    1. 背景 (The Why)

    作为一名网络安全从业者,我深知 AI 在未来攻防对抗中的重要性。为了验证“安全+AI”的融合场景,我决定在 Kali Linux 环境下,利用 Docker 容器化技术,私有化部署 Google 最新的 Gemma 模型,并搭建漏洞靶场进行联动测试。

    2. 环境准备 (The Setup)

     * 宿主机系统: Kali Linux 2024.4 (VMware)

     * 核心工具: Docker, Ollama

     * 目标模型: gemma3:1b (Google DeepMind 轻量级模型)

    3. 实战过程与踩坑 (The Action)

    Step 1: Docker 环境确认

    首先检查 Docker 服务状态,确保容器环境正常。

    docker ps -a

    可以看到我本地已经运行了 medicean/vulapps 漏洞靶场,为后续 AI 安全测试做好了准备。

    Step 2: 拉取 Ollama 镜像

    使用 Docker 拉取 Ollama 官方镜像。

    docker pull ollama/ollama

    (这里曾遇到网络波动导致下载慢,通过配置镜像加速解决)

    Step 3: 运行 Ollama 容器

    启动容器并映射端口:

    docker run -d -v ollama:/root/.ollama -p 11434:11434 –name ollama ollama/ollama

    Step 4: 模型拉取与排错 (Troubleshooting)

    在尝试拉取模型时,我遇到了 manifest not found 错误:

     * ❌ 错误尝试:docker exec -it ollama ollama run gamma3:1b (拼写错误)

     * ❌ 错误尝试:docker exec -it ollama ollama run llama3 (版本不对)

     * ✅ 解决方案: 查阅官方文档,确认模型准确名称为 gemma3:1b。

     * 成功命令:

       docker exec -it ollama ollama run gemma3:1b

    4. 最终效果 (The Result)

    成功进入交互式对话界面!

    > User: “who are you?”

    > Gemma: “Hi there! I’m Gemma, a large language model created by the Gemma team at Google DeepMind…”

    5. 总结与思考

    这次实战不仅跑通了 AI 私有化部署,更重要的是验证了 Docker 在 Linux 环境下的灵活性。下一步计划:

     * 使用 Python 编写 API 接口调用该模型。

     * 测试用 AI 生成 SQL 注入 Payload 并打向本地的 VulApps 靶场。

  • [Day 5] MySQL 核心复盘:从增删改查到 SQL 注入的底层思考


    很多人觉得 SQL 只是简单的“增删改查”,但在安全工程师眼里,每一条 SQL 语句都是潜在的攻击面

    一、 数据库的“CRUD”与安全映射

    在开发视角下,SQL 的四大金刚是 INSERT, DELETE, UPDATE, SELECT。
    但在我的安全视角下,它们代表着不同的风险:

    1. 查询 (SELECT) —— 信息泄露的源头
    这是 Web 业务中最常用的语句,也是 SQL 注入 (SQLi) 的重灾区。

    • 基础语法: SELECT * FROM users WHERE id = 1;
    • 安全思考: 如果开发者没有过滤 id 的输入,攻击者通过闭合单引号 ‘,配合 UNION SELECT,就能直接把数据库“拖库”。
      • 关键点: 理解 ORDER BY 猜解字段数,理解 UNION 联合查询的逻辑。

    2. 新增 (INSERT) —— 存储型攻击的温床

    • 基础语法: INSERT INTO messages (content) VALUES (‘Hello’);
    • 安全思考: 如果在这里插入了一段恶意的 XSS 代码(如 <script>alert(1)</script>),那么所有查看这条留言的用户都会中招。这就是存储型 XSS

    3. 修改 (UPDATE) & 删除 (DELETE) —— 破坏性攻击

    • 基础语法: UPDATE users SET password=’123′ WHERE user=’admin’;
    • 安全思考: 这类语句如果没有加上 WHERE 限制,或者存在越权漏洞 (IDOR),可能导致全站数据被篡改或清空。

    二、 实战演练:命令行下的数据掌控

    拒绝图形化工具的“傻瓜式操作”,回归命令行(CLI)才是理解数据库的最佳方式。
    今日实战记录:

    环境: 本地 MySQL 5.7 / 8.0 环境。建库建表:
    CREATE DATABASE security_test;

    USE security_test;

    CREATE TABLE users (

        id INT AUTO_INCREMENT PRIMARY KEY,

        username VARCHAR(50),

        password VARCHAR(50)

    );

    1. 数据操纵:
      • 插入一条模拟管理员数据:INSERT INTO users (username, password) VALUES (‘admin’, ‘123456’);
      • 精准查询:SELECT * FROM users WHERE username = ‘admin’;

    Keep Coding, Keep Hacking. 💻🛡️

  • Day 4:前端不只是页面,是漏洞的入口

    一、HTML:寻找“数据入口” (The Gate)

    对于开发来说,HTML 是骨架。
    对于安全来说,HTML 是 攻击载荷(Payload)的发射台

    在浏览了大量的教程后,我发现 90% 的标签(如 div, span, p)对于初级渗透来说只是噪音。我将精力死死锁定在了一个标签上:<form> 表单

    1. 为什么是 Form?

    因为这是用户与服务器交互的核心通道。SQL 注入、文件上传、逻辑绕过,几乎都是从这里开始的。

    2. 攻击者眼里的 Form 结构

    我看代码时,只关注三个属性:

    • action“靶心在哪里?” 数据被送到了哪个后端文件(如 login.php)?这决定了我要攻击的目标。
    • method“子弹怎么飞?”
      • GET:参数在 URL 里裸奔,容易被日志记录,但也容易修改。
      • POST:参数藏在 HTTP Body 里,这也是我在 Burp Suite 里重点抓包的地方。
    • input 的 name 属性“参数名是什么?” 这是后端接收变量的依据(如 $_POST[‘username’]),也是我构造 SQL 注入语句的拼接点。

    实战感悟:
    以后看到一个输入框,我脑子里出现的不再是“请输入密码”,而是:
    select * from users where username = ‘ [我的Payload] ‘

    //Register.html

    <!DOCTYPE html>

    <html lang=”en”>

    <head>

        <meta charset=”UTF-8″>

        <title>Vito Register Page</title>

        <style type=”text/css”>

          div{

            width: 310px;

            background: #ccc;

            padding: 20px;

            margin-top: 50px;

            margin-right: auto;

            margin-bottom: 0px;

            margin-left: auto;

          }

          h1{

            text-align: center;

          }

          input{

            width: 302px;

            height: 30px;

            border: 1px solid #333;

          }

          .submit{

            width: 308px;

            height: 30px;

            border: 1px solid #333;

            margin-top: 20px;

            border-radius: 5px;

            background: green;

            color: #fff;

          }

          a{

            text-decoration: none;

            color: #222;

          }

        </style>

    </head>

    <body>

      <div>

        <h1>Vito Register Page</h1><hr>

        <form action=”” method=”post” name=”form”>

          Username:<br>

          <input type=”text” name=”username”><br>

           <!–为了使用户体验更好 加一个span标签–>

          <span></span><br>

            Password:<br>

          <input type=”password” name=”password”><br>

            <span></span><br>

            Confirm Password:<br>

          <input type=”password” name=”repass”><br><br>

            <span></span><br>

            <input type=”submit” name=”submit” class=”submit” value=”注册”>

        </form>

        <a href=”login.html”>已注册,去登录</a>

      </div>

    </body>

    </html>

    <script>

        //获取元素

        var form = document.forms[‘form’];

        var username = form.elements[‘username’];

        var password = form.elements[‘password’];

        var repass = form.elements[‘repass’];

        var span=form.getElementsByTagName(‘span’);

        //表单验证

        //1.用户体验

        //获取焦点事件

        username.onfocus = function (){

            span[0].innerHTML=”;

        }

        //失去焦点时进行判断

        username.onblur = function (){

            var len = this.value.length;

            if(len == 0){

                span[0].innerHTML = (‘请输入用户名’);

                span[0].style.color=’red’;

            }

            else if(len < 4 || len>18){

                span[0].innerHTML = ‘帐号长度为4-18位!’;

                span[0].style.color=’blue’;

            }

            else{

                span[0].innerHTML = ‘✅’;

                span[0].style.color=’green’;

            }

        }

        //获取焦点事件

        password.onfocus = function (){

            span[1].innerHTML = ”;

        }

        password.onblur = function (){

            var len = this.value.length;

            if(len == 0){

                span[1].innerHTML = (‘请输入密码’);

                span[1].style.color=’red’;

            }

            else if(len < 4 || len>18){

                span[1].innerHTML = ‘密码长度为4-18位!’;

                span[1].style.color=’blue’;

            }

            else{

                span[1].innerHTML = ‘✅’;

                span[1].style.color=’green’;

            }

            repass.onfocus = function (){

                span[2].innerHTML = ”;

            }

            repass.onblur = function (){

                if(password.value != this.value){

                    span[2].innerHTML=’密码不一致’;

                    span[2].style.color = ‘red’;

                }

                else{

                    span[2].innerHTML = ‘✅’;

                    span[2].style.color = ‘green’;

                }

            }

        }

        //2.数据安全

        form.onsubmit = function (){

            if(

                username.value.length ==0||

                username.value.length < 4||

                username.value.length >18||

                password.value.length ==0||

                password.value.length < 4||

                password.value.length >18||

                password.value != repass.value

            ){

                console.log(‘false’);

                return false;

            }

        }

    </script>

    二、JavaScript:操纵“傀儡” (The Puppet Master)

    如果说 HTML 是静态的房子,那 JS 就是房子里的管家。
    只要控制了 JS,我就能控制受害者的浏览器。这就是 XSS(跨站脚本攻击) 的本质。

    今天的 JS 学习,我跳过了所有的算法逻辑,只死磕一个概念:DOM (文档对象模型)

    1. DOM 的本质

    DOM 就是 JS 操作 HTML 的接口。

    • 开发用它来做特效。
    • 黑客用它来窃取数据

    2. 两个危险的 DOM 操作

    在学习过程中,我重点复现了两个场景:

    • 读取敏感信息: document.cookie。只要能让受害者的浏览器执行这行代码,Session ID 就到手了,这一步就是“杀人诛心”。
    • 篡改页面内容: document.write() 或 innerHTML。这是 DOM 型 XSS 的高发区。如果后端没有过滤,我输入的 <script> 标签就会被当成代码执行。

    实战感悟:
    XSS 不仅仅是弹一个窗 alert(1) 那么简单,它的本质是 “JS 代码注入”。只要能运行 JS,浏览器里的秘密就都不是秘密了。

    三、今日总结:构建“攻击面”思维

    今天的学习让我明白,安全工程师看代码的视角是反直觉的:

    • 正常思维: 这个功能怎么实现?
    • 黑客思维: 这个输入框如果不按套路出牌会怎样?这个参数如果被我改了会怎样?

    Day 4 的任务圆满结束。
    HTML 表单是我的发射器,JS DOM 是我的遥控器

    (本文为个人学习笔记,仅供技术交流)

  • Day 3:开启上帝之眼——网络协议与 Burp Suite 实战

    > 📅 训练周期: Day 3 (全天)

    > ⚠️ 战术警报: ⭐⭐⭐⭐⭐ (极度重要 – 这是黑客的必修课)

    > ⚔️ 核心任务: 理解 HTTP 协议、安装 Burp Suite、完成第一次“中间人”数据篡改。

    1. 为什么要学这一章?(战前动员)

    很多新手黑客只知道用工具乱扫,结果扫出一堆乱码根本看不懂。

    原因很简单:你看不见数据的“裸体”。

    我们在浏览器里看到的精美网页,只是外表的“皮肤”。

    而在皮肤之下,网络世界里流动的全是纯文本的数据包。

     * 你输入的密码是怎么传给服务器的?

     * 服务器是怎么知道你是谁的?

     * 为什么改了一个参数,我就能看到别人的订单?

    **只有掌握了 HTTP 协议和抓包工具(Burp Suite),你才能像《黑客帝国》里的 Neo 一样,看到的不再是网页,而是绿色的代码瀑布。**这就是黑客的“天眼”。

    2. 协议分层:网络的“洋葱结构”

    别被 OSI 七层模型那些学术名词吓倒。作为实战派,你只需要理解这个**“洋葱结构”**。

     * 应用层 (Application Layer): (重点) 这里是 HTTP/HTTPS 协议。是我们和浏览器直接打交道的地方。我们 90% 的黑客攻击都发生在这里。

     * 传输层 (Transport Layer): 这里是 TCP/UDP。负责把数据包安全送达(像是快递员)。

     * 网络层 (Network Layer): 这里是 IP。负责定位地址(像是门牌号)。

    士兵笔记: 今天我们只死磕 HTTP 协议。底层的 TCP/IP 以后搞内网渗透时再说。

    3. HTTP 基础:互联网的“对话艺术”

    HTTP (HyperText Transfer Protocol) 本质上就是**“一问一答”**。

    A. 请求 (Request) —— 你想要什么?

    当你点击一个链接,浏览器其实向服务器发送了一封信:

    GET /login.php HTTP/1.1      <– 请求行:我要拿(GET)登录页

    Host: www.example.com        <– 请求头:目标是谁

    User-Agent: Mozilla/5.0…   <– 请求头:我是用什么浏览器访问的

    Cookie: session_id=xyz123    <– 核心:我的身份令牌

     * GET: 就像去取快递。我要拿数据。

     * POST: 就像去寄快递。我要提交数据(比如账号密码)。

    B. 响应 (Response) —— 服务器给什么?

    服务器收到信后,回你一封信:

    HTTP/1.1 200 OK              <– 状态行:收到,没问题

    Server: Apache/2.4           <– 响应头:我的服务器型号

    Content-Type: text/html      <– 响应头:给你的是网页代码

    <html>…</html>             <– 响应体:具体的网页内容

    C. 关键状态码 (Status Codes)

     * 200 OK: 成功。

     * 302 Found: 搬家了,你去别的地方找(重定向)。

     * 404 Not Found: 你找的东西不存在。

     * 403 Forbidden: 禁止访问(不管有没有,反正不给你看)。

     * 500 Internal Server Error: 服务器炸了(可能是你把它搞崩了)。

    4. 武器库:Burp Suite (黑客神器)

    Burp Suite 是什么?

    它是一个代理服务器 (Proxy)。

     * 正常流程: 浏览器 <—> 服务器

     * Burp 介入后: 浏览器 <—> Burp Suite (中间人) <—> 服务器

    这就意味着,所有的数据包都要经过 Burp。你可以截获 (Intercept) 它们,让它们停在半空中,修改 里面的数据,然后再放行 (Forward) 出去。

    🛠️ 安装指引

     * 下载: 去 PortSwigger 官网下载 Burp Suite Community Edition (社区版免费,够用了)。

     * 安装: 一路 Next。

     * 启动: 打开软件,选择 “Temporary Project” -> “Start Burp”。

    5. 今日任务:第一次“上帝之手”操作 🎯

    任务目标: 截获一个数据包,修改它,欺骗服务器。

    Step 1: 打开浏览器

    在 Burp Suite 的 Proxy 选项卡下,点击 Open Browser 按钮。

    (这是 Burp 自带的浏览器,不需要配置代理,最方便)

    Step 2: 开启拦截

    确保 Burp 里的 Intercept is on 按钮是亮着的。

    Step 3: 触发请求

    在刚才打开的浏览器里,访问百度 (baidu.com),在搜索框输入:Hello,然后点击搜索。

    现象: 你会发现浏览器一直在转圈圈,加载不出来。

    原因: 数据包被 Burp 抓住了!

    Step 4: 修改命运 (上帝之手)

    回到 Burp Suite,你会看到一大段代码。找到类似下面这一行:

    GET /s?wd=Hello HTTP/1.1

     * 把 Hello 删掉,改成 Hacker。

     * 这就叫篡改参数。

    Step 5: 放行

    点击 Burp 上的 Forward 按钮。

    Step 6: 见证奇迹

    回到浏览器。

    你会发现,你明明搜的是 “Hello”,但百度的搜索结果显示的却是 “Hacker” 的内容!

    📝 课后总结

    士兵,恭喜你完成了第一次**“中间人攻击”**的模拟。

    虽然改一个搜索词看起来很幼稚,但你想象一下:

     * 如果那个参数是 转账金额 呢?(把 100 改成 1)

     * 如果那个参数是 商品价格 呢?(把 1000 元改成 0.01 元)

     * 如果那个参数是 用户ID 呢?(把我的 ID 改成管理员的 ID)

    这就是 Web 渗透的本质:在数据流动的过程中,寻找信任的裂缝。

    明天,我们将带着这双“天眼”,去挑战更刺激的漏洞。

    Day 3 任务结束。Keep hacking! 💻🏴‍☠️

  • #C++ Day44 Basic Data Structure Chapter3  review-2 & Sequential list version 3.0 December 31 2025

    //Sequential list version 3.0

    #include <iostream>

    using namespace std;

    #define eleType int

    //1.define a structure

    struct SequentialList {

    eleType* elements;

    int capacity;

    int size;

    };

    //2.initialize

    void initializeList(SequentialList* list, int capacity) {

    list->elements = new eleType[capacity];

    list->capacity = capacity;

    list->size = 0;

    }

    //3.destroy

    void destroyList(SequentialList* list) {

    delete[] list->elements;

    list->elements = nullptr;

    list->size = 0;

    list->capacity = 0;

    }

    //4.size and is it empty

    int sizeOfList(SequentialList* list) {

    return list->size;

    }

    bool isEmpty(SequentialList* list) {

    return list->size == 0;

    }

    //5.insert

    void insertElement(SequentialList* list, int index,eleType element) {

    if (index<0 || index>list->size) {

    throw std::invalid_argument(“invalid index”);

    }

    if (list->capacity == list->size) {

    int newcapacity =(list->capacity==0) ? 4 : list->capacity * 2;

    eleType* newlist = new eleType[newcapacity];

    for (int i = 0; i < list->size; i++) {

    newlist[i] = list->elements[i];

    }

    delete[] list->elements;

    list->elements = newlist;

    list->capacity = newcapacity;

    }

    for (int i = list->size; i > index; i–) {

    list->elements[i] = list->elements[i – 1];

    }

    list->elements[index] = element;

    list->size++;

    }

    //6.delete

    void deleteElement(SequentialList* list, int index) {

    if (index < 0 || index >= list->size) {

    throw std::invalid_argument(“invalid index”);

    }

    for (int i = index; i < list->size – 1; i++) {

    list->elements[i] = list->elements[i + 1];

    }

    list->size–;

    }

    //7.findindex

    int findIndex(SequentialList* list, eleType element) {

    for(int i=0;i<list->size;i++){

    if (list->elements[i] == element) {

    return i;

    }

    }

    return -1;

    }

    //8.get

    eleType getElement(SequentialList* list, int index) {

    if (index < 0 || index >= list->size) {

    throw std::invalid_argument(“invalid index”);

    }

    return list->elements[index];

    }

    //9.update

    void updateElement(SequentialList* list, int index, eleType element) {

    if (index < 0 || index >= list->size) {

    throw std::invalid_argument(“invalid index”);

    }

    list->elements[index] = element;

    }

    int main() {

    SequentialList mylist;

    int capa=10;

    initializeList(&mylist, capa);

    cout << “isEmpty:” << isEmpty(&mylist)<<endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    for (int i = 0; i < capa; i++) {

    insertElement(&mylist, i, i * 10);

    }

    cout << “isEmpty:” << isEmpty(&mylist) << endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    for (int i = 0; i < sizeOfList(&mylist); i++) {

    cout << getElement(&mylist, i) << ‘ ‘;

    }cout << endl;

    insertElement(&mylist,3, 5050);

    for (int i = 0; i < sizeOfList(&mylist); i++) {

    cout << getElement(&mylist, i) << ‘ ‘;

    }cout << endl;

    cout << “isEmpty:” << isEmpty(&mylist) << endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    int id = findIndex(&mylist, 50);

    if (id != -1) {

    cout << “Found:” << getElement(&mylist, id) << endl;

    deleteElement(&mylist, id);

    }

    else {

    cout << “Not found!” << endl;

    }

    for (int i = 0; i < sizeOfList(&mylist); i++) {

    cout << getElement(&mylist, i) << ‘ ‘;

    }cout << endl;

    cout << “isEmpty:” << isEmpty(&mylist) << endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    updateElement(&mylist, 5, 9090);

    for (int i = 0; i < sizeOfList(&mylist); i++) {

    cout << getElement(&mylist, i) << ‘ ‘;

    }cout << endl;

    cout << “isEmpty:” << isEmpty(&mylist) << endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    destroyList(&mylist);

    for (int i = 0; i < sizeOfList(&mylist); i++) {

    cout << getElement(&mylist, i) << ‘ ‘;

    }cout << endl;

    cout << “isEmpty:” << isEmpty(&mylist) << endl;

    cout << “size:” << sizeOfList(&mylist) << endl;

    return 0;

    }

  • [Day 1] 网络安全入坑指南 & 学习路线图

    🗺️ 学习路线 (The Map)

    我接下来的升级路线是什么?

    前端基础 (HTML/JS)

    ⚠️ 避坑指南 (Warning)

    • 绝对不能扫描未经授权的公网网站(容易喝茶)。
    • 只能在靶场或者自己的虚拟机里练手。

    💡 我的思考 (My Thoughts)

    • 今天的课让我觉得最有意思的是自学能力
    • 我对安全研究员方向比较感兴趣